Merge changes I1276375c,I3fd96558,I39f7b1af

* changes:
  Remove detached wallpaper animations
  Remove WSA.mAnimLayer
  Remove WindowStateAnimator.isAnimationSet
diff --git a/Android.bp b/Android.bp
index a603006..faad6f3 100644
--- a/Android.bp
+++ b/Android.bp
@@ -77,6 +77,7 @@
         "core/java/android/app/ISearchManager.aidl",
         "core/java/android/app/ISearchManagerCallback.aidl",
         "core/java/android/app/IServiceConnection.aidl",
+        "core/java/android/app/ISmsAppService.aidl",
         "core/java/android/app/IStopUserCallback.aidl",
         "core/java/android/app/job/IJobCallback.aidl",
         "core/java/android/app/job/IJobScheduler.aidl",
@@ -515,11 +516,14 @@
         "telephony/java/android/telephony/ims/aidl/IImsSmsListener.aidl",
         "telephony/java/android/telephony/mbms/IMbmsDownloadSessionCallback.aidl",
         "telephony/java/android/telephony/mbms/IMbmsStreamingSessionCallback.aidl",
+        "telephony/java/android/telephony/mbms/IMbmsGroupCallSessionCallback.aidl",
         "telephony/java/android/telephony/mbms/IDownloadStatusListener.aidl",
         "telephony/java/android/telephony/mbms/IDownloadProgressListener.aidl",
         "telephony/java/android/telephony/mbms/IStreamingServiceCallback.aidl",
+        "telephony/java/android/telephony/mbms/IGroupCallCallback.aidl",
         "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/INetworkService.aidl",
         "telephony/java/android/telephony/INetworkServiceCallback.aidl",
         "telephony/java/com/android/ims/internal/IImsCallSession.aidl",
@@ -703,7 +707,6 @@
 
     // Loaded with System.loadLibrary by android.view.textclassifier
     required: [
-        "libtextclassifier",
         "libmedia2_jni",
     ],
 
@@ -807,12 +810,16 @@
 java_library {
     name: "ext",
     installable: true,
-    no_framework_libs: true,
+    sdk_version: "core_current",
     static_libs: [
         "libphonenumber-platform",
         "nist-sip",
         "tagsoup",
         "rappor",
+        "libtextclassifier-java",
+    ],
+    required: [
+        "libtextclassifier",
     ],
     dxflags: ["--core-library"],
 }
@@ -1282,6 +1289,9 @@
 }
 
 droiddoc {
+    // Please sync with android-api-council@ before making any changes for the name property below.
+    // Since there's cron jobs that fetch offline-sdk-referenceonly-docs-docs.zip periodically.
+    // See b/116221385 for reference.
     name: "offline-sdk-referenceonly-docs",
     defaults: ["framework-docs-default"],
     srcs: [
@@ -1298,6 +1308,9 @@
 }
 
 droiddoc {
+    // Please sync with android-api-council@ before making any changes for the name property below.
+    // Since there's cron jobs that fetch offline-system-sdk-referenceonly-docs-docs.zip periodically.
+    // See b/116221385 for reference.
     name: "offline-system-sdk-referenceonly-docs",
     defaults: ["framework-docs-default"],
     srcs: [
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 2247e43..6deda0c 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -247,6 +247,7 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/framework/com.android.mediadrm.signer.jar)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/framework/com.android.location.provider.jar)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/framework/com.android.future.usb.accessory.jar)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/framework/com.android.media.remotedisplay.jar)
 # ******************************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
 # ******************************************************************
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index de83f3e..ff40f75 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -8,6 +8,11 @@
                       services/print/
                       services/usb/
                       telephony/
+                      tests/ActivityViewTest/
+                      tests/LotsOfApps/
+                      tests/NativeProcessesMemoryTest/
+                      tests/OdmApps/
+                      tests/SystemMemoryTest/
                       wifi/
 
 api_lint_hook = ${REPO_ROOT}/frameworks/base/tools/apilint/apilint_sha.sh ${PREUPLOAD_COMMIT}
diff --git a/api/current.txt b/api/current.txt
index 2b9c594..e6a31af 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -7,6 +7,7 @@
   public static final class Manifest.permission {
     ctor public Manifest.permission();
     field public static final java.lang.String ACCEPT_HANDOVER = "android.permission.ACCEPT_HANDOVER";
+    field public static final java.lang.String ACCESS_BACKGROUND_LOCATION = "android.permission.ACCESS_BACKGROUND_LOCATION";
     field public static final java.lang.String ACCESS_CHECKIN_PROPERTIES = "android.permission.ACCESS_CHECKIN_PROPERTIES";
     field public static final java.lang.String ACCESS_COARSE_LOCATION = "android.permission.ACCESS_COARSE_LOCATION";
     field public static final java.lang.String ACCESS_FINE_LOCATION = "android.permission.ACCESS_FINE_LOCATION";
@@ -37,6 +38,7 @@
     field public static final java.lang.String BIND_QUICK_SETTINGS_TILE = "android.permission.BIND_QUICK_SETTINGS_TILE";
     field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
     field public static final java.lang.String BIND_SCREENING_SERVICE = "android.permission.BIND_SCREENING_SERVICE";
+    field public static final java.lang.String BIND_SMS_APP_SERVICE = "android.permission.BIND_SMS_APP_SERVICE";
     field public static final java.lang.String BIND_TELECOM_CONNECTION_SERVICE = "android.permission.BIND_TELECOM_CONNECTION_SERVICE";
     field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
     field public static final java.lang.String BIND_TV_INPUT = "android.permission.BIND_TV_INPUT";
@@ -772,9 +774,11 @@
     field public static final int isFeatureSplit = 16844123; // 0x101055b
     field public static final int isGame = 16843764; // 0x10103f4
     field public static final int isIndicator = 16843079; // 0x1010147
+    field public static final int isLightTheme = 16844175; // 0x101058f
     field public static final int isModifier = 16843334; // 0x1010246
     field public static final int isRepeatable = 16843336; // 0x1010248
     field public static final int isScrollContainer = 16843342; // 0x101024e
+    field public static final int isSplitRequired = 16844176; // 0x1010590
     field public static final int isStatic = 16844122; // 0x101055a
     field public static final int isSticky = 16843335; // 0x1010247
     field public static final int isolatedProcess = 16843689; // 0x10103a9
@@ -4296,6 +4300,20 @@
     method public abstract void onActivityCreated(android.app.Activity, android.os.Bundle);
     method public abstract void onActivityDestroyed(android.app.Activity);
     method public abstract void onActivityPaused(android.app.Activity);
+    method public default void onActivityPostCreated(android.app.Activity, android.os.Bundle);
+    method public default void onActivityPostDestroyed(android.app.Activity);
+    method public default void onActivityPostPaused(android.app.Activity);
+    method public default void onActivityPostResumed(android.app.Activity);
+    method public default void onActivityPostSaveInstanceState(android.app.Activity, android.os.Bundle);
+    method public default void onActivityPostStarted(android.app.Activity);
+    method public default void onActivityPostStopped(android.app.Activity);
+    method public default void onActivityPreCreated(android.app.Activity, android.os.Bundle);
+    method public default void onActivityPreDestroyed(android.app.Activity);
+    method public default void onActivityPrePaused(android.app.Activity);
+    method public default void onActivityPreResumed(android.app.Activity);
+    method public default void onActivityPreSaveInstanceState(android.app.Activity, android.os.Bundle);
+    method public default void onActivityPreStarted(android.app.Activity);
+    method public default void onActivityPreStopped(android.app.Activity);
     method public abstract void onActivityResumed(android.app.Activity);
     method public abstract void onActivitySaveInstanceState(android.app.Activity, android.os.Bundle);
     method public abstract void onActivityStarted(android.app.Activity);
@@ -6095,6 +6113,11 @@
     method public abstract void onSharedElementsReady();
   }
 
+  public class SmsAppService extends android.app.Service {
+    ctor public SmsAppService();
+    method public final android.os.IBinder onBind(android.content.Intent);
+  }
+
   public deprecated class TabActivity extends android.app.ActivityGroup {
     ctor public TabActivity();
     method public android.widget.TabHost getTabHost();
@@ -14007,6 +14030,10 @@
     method public float getRunAdvance(char[], int, int, int, int, boolean, int);
     method public float getRunAdvance(java.lang.CharSequence, int, int, int, int, boolean, int);
     method public android.graphics.Shader getShader();
+    method public int getShadowLayerColor();
+    method public float getShadowLayerDx();
+    method public float getShadowLayerDy();
+    method public float getShadowLayerRadius();
     method public float getStrikeThruPosition();
     method public float getStrikeThruThickness();
     method public android.graphics.Paint.Cap getStrokeCap();
@@ -15310,7 +15337,7 @@
     method public static java.lang.String toFontVariationSettings(android.graphics.fonts.FontVariationAxis[]);
   }
 
-  public class SystemFonts {
+  public final class SystemFonts {
     method public static java.util.Set<android.graphics.fonts.Font> getAvailableFonts();
   }
 
@@ -21623,7 +21650,7 @@
     method public android.view.inputmethod.InputConnection getCurrentInputConnection();
     method public android.view.inputmethod.EditorInfo getCurrentInputEditorInfo();
     method public boolean getCurrentInputStarted();
-    method public int getInputMethodWindowRecommendedHeight();
+    method public deprecated int getInputMethodWindowRecommendedHeight();
     method public android.view.LayoutInflater getLayoutInflater();
     method public int getMaxWidth();
     method public java.lang.CharSequence getTextForImeAction(int);
@@ -32496,6 +32523,7 @@
 
   public class Build {
     ctor public Build();
+    method public static java.util.List<android.os.Build.Partition> getPartitions();
     method public static java.lang.String getRadioVersion();
     method public static java.lang.String getSerial();
     field public static final java.lang.String BOARD;
@@ -32524,6 +32552,14 @@
     field public static final java.lang.String USER;
   }
 
+  public static class Build.Partition {
+    ctor public Build.Partition();
+    method public java.lang.String getFingerprint();
+    method public java.lang.String getName();
+    method public long getTimeMillis();
+    field public static final java.lang.String PARTITION_NAME_SYSTEM = "system";
+  }
+
   public static class Build.VERSION {
     ctor public Build.VERSION();
     field public static final java.lang.String BASE_OS;
@@ -33698,6 +33734,7 @@
     field public static final java.lang.String DISALLOW_FUN = "no_fun";
     field public static final java.lang.String DISALLOW_INSTALL_APPS = "no_install_apps";
     field public static final java.lang.String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources";
+    field public static final java.lang.String DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY = "no_install_unknown_sources_globally";
     field public static final java.lang.String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
     field public static final java.lang.String DISALLOW_MOUNT_PHYSICAL_MEDIA = "no_physical_media";
     field public static final java.lang.String DISALLOW_NETWORK_RESET = "no_network_reset";
@@ -40106,6 +40143,7 @@
     field public static final int SHOW_SOURCE_ACTIVITY = 16; // 0x10
     field public static final int SHOW_SOURCE_APPLICATION = 8; // 0x8
     field public static final int SHOW_SOURCE_ASSIST_GESTURE = 4; // 0x4
+    field public static final int SHOW_SOURCE_NOTIFICATION = 64; // 0x40
     field public static final int SHOW_SOURCE_PUSH_TO_TALK = 32; // 0x20
     field public static final int SHOW_WITH_ASSIST = 1; // 0x1
     field public static final int SHOW_WITH_SCREENSHOT = 2; // 0x2
@@ -41311,6 +41349,7 @@
     field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 128; // 0x80
     field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10
     field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40
+    field public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 2048; // 0x800
     field public static final int PROPERTY_RTT = 1024; // 0x400
     field public static final int PROPERTY_SELF_MANAGED = 256; // 0x100
     field public static final int PROPERTY_WIFI = 8; // 0x8
@@ -42264,6 +42303,7 @@
     field public static final deprecated java.lang.String KEY_RESTART_RADIO_ON_PDP_FAIL_REGULAR_DEACTIVATION_BOOL = "restart_radio_on_pdp_fail_regular_deactivation_bool";
     field public static final java.lang.String KEY_RTT_SUPPORTED_BOOL = "rtt_supported_bool";
     field public static final java.lang.String KEY_SHOW_APN_SETTING_CDMA_BOOL = "show_apn_setting_cdma_bool";
+    field public static final java.lang.String KEY_SHOW_CALL_BLOCKING_DISABLED_NOTIFICATION_ALWAYS_BOOL = "show_call_blocking_disabled_notification_always_bool";
     field public static final java.lang.String KEY_SHOW_CDMA_CHOICES_BOOL = "show_cdma_choices_bool";
     field public static final java.lang.String KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL = "show_iccid_in_sim_status_bool";
     field public static final java.lang.String KEY_SHOW_ONSCREEN_DIAL_BUTTON_BOOL = "show_onscreen_dial_button_bool";
@@ -42525,6 +42565,13 @@
     field public static final int STATUS_UNKNOWN = 0; // 0x0
   }
 
+  public class MbmsGroupCallSession implements java.lang.AutoCloseable {
+    method public void close();
+    method public static android.telephony.MbmsGroupCallSession create(android.content.Context, java.util.concurrent.Executor, int, android.telephony.mbms.MbmsGroupCallSessionCallback);
+    method public static android.telephony.MbmsGroupCallSession create(android.content.Context, java.util.concurrent.Executor, android.telephony.mbms.MbmsGroupCallSessionCallback);
+    method public android.telephony.mbms.GroupCall startGroupCall(java.util.concurrent.Executor, long, int[], int[], android.telephony.mbms.GroupCallCallback);
+  }
+
   public class MbmsStreamingSession implements java.lang.AutoCloseable {
     method public void close();
     method public static android.telephony.MbmsStreamingSession create(android.content.Context, java.util.concurrent.Executor, int, android.telephony.mbms.MbmsStreamingSessionCallback);
@@ -42533,7 +42580,7 @@
     method public android.telephony.mbms.StreamingService startStreaming(android.telephony.mbms.StreamingServiceInfo, java.util.concurrent.Executor, android.telephony.mbms.StreamingServiceCallback);
   }
 
-  public class NeighboringCellInfo implements android.os.Parcelable {
+  public deprecated class NeighboringCellInfo implements android.os.Parcelable {
     ctor public deprecated NeighboringCellInfo();
     ctor public deprecated NeighboringCellInfo(int, int);
     ctor public NeighboringCellInfo(int, java.lang.String, int);
@@ -42906,6 +42953,7 @@
     method public static int getSlotIndex(int);
     method public static int[] getSubscriptionIds(int);
     method public java.util.List<android.telephony.SubscriptionPlan> getSubscriptionPlans(int);
+    method public boolean isActiveSubscriptionId(int);
     method public boolean isNetworkRoaming(int);
     method public static boolean isValidSubscriptionId(int);
     method public void removeOnOpportunisticSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener);
@@ -42993,7 +43041,6 @@
     method public java.lang.String getMmsUAProfUrl();
     method public java.lang.String getMmsUserAgent();
     method public java.lang.String getNai();
-    method public deprecated java.util.List<android.telephony.NeighboringCellInfo> getNeighboringCellInfo();
     method public java.lang.String getNetworkCountryIso();
     method public java.lang.String getNetworkOperator();
     method public java.lang.String getNetworkOperatorName();
@@ -43058,6 +43105,7 @@
     field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
     field public static final java.lang.String ACTION_SECRET_CODE = "android.telephony.action.SECRET_CODE";
     field public static final java.lang.String ACTION_SHOW_VOICEMAIL_NOTIFICATION = "android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION";
+    field public static final java.lang.String ACTION_SMS_APP_SERVICE = "android.telephony.action.SMS_APP_SERVICE";
     field public static final java.lang.String ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED = "android.telephony.action.SUBSCRIPTION_CARRIER_IDENTITY_CHANGED";
     field public static final int APPTYPE_CSIM = 4; // 0x4
     field public static final int APPTYPE_ISIM = 5; // 0x5
@@ -43474,6 +43522,29 @@
     field public static final android.os.Parcelable.Creator<android.telephony.mbms.FileServiceInfo> CREATOR;
   }
 
+  public class GroupCall implements java.lang.AutoCloseable {
+    method public void close();
+    method public long getTmgi();
+    method public void updateGroupCall(int[], int[]);
+    field public static final int REASON_BY_USER_REQUEST = 1; // 0x1
+    field public static final int REASON_FREQUENCY_CONFLICT = 3; // 0x3
+    field public static final int REASON_LEFT_MBMS_BROADCAST_AREA = 6; // 0x6
+    field public static final int REASON_NONE = 0; // 0x0
+    field public static final int REASON_NOT_CONNECTED_TO_HOMECARRIER_LTE = 5; // 0x5
+    field public static final int REASON_OUT_OF_MEMORY = 4; // 0x4
+    field public static final int STATE_STALLED = 3; // 0x3
+    field public static final int STATE_STARTED = 2; // 0x2
+    field public static final int STATE_STOPPED = 1; // 0x1
+  }
+
+  public class GroupCallCallback {
+    ctor public GroupCallCallback();
+    method public void onBroadcastSignalStrengthUpdated(int);
+    method public void onError(int, java.lang.String);
+    method public void onGroupCallStateChanged(int, int);
+    field public static final int SIGNAL_STRENGTH_UNAVAILABLE = -1; // 0xffffffff
+  }
+
   public class MbmsDownloadReceiver extends android.content.BroadcastReceiver {
     ctor public MbmsDownloadReceiver();
     method public void onReceive(android.content.Context, android.content.Intent);
@@ -43522,6 +43593,14 @@
     field public static final int ERROR_UNABLE_TO_START_SERVICE = 302; // 0x12e
   }
 
+  public class MbmsGroupCallSessionCallback {
+    ctor public MbmsGroupCallSessionCallback();
+    method public void onAvailableSaisUpdated(java.util.List<java.lang.Integer>, java.util.List<java.util.List<java.lang.Integer>>);
+    method public void onError(int, java.lang.String);
+    method public void onMiddlewareReady();
+    method public void onServiceInterfaceAvailable(java.lang.String, int);
+  }
+
   public class MbmsStreamingSessionCallback {
     ctor public MbmsStreamingSessionCallback();
     method public void onError(int, java.lang.String);
@@ -44156,6 +44235,8 @@
     field public float density;
     field public int[] drawableState;
     field public int linkColor;
+    field public int underlineColor;
+    field public float underlineThickness;
   }
 
   public class TextUtils {
@@ -44970,11 +45051,20 @@
     ctor public TextAppearanceSpan(android.os.Parcel);
     method public int describeContents();
     method public java.lang.String getFamily();
+    method public java.lang.String getFontFeatureSettings();
+    method public java.lang.String getFontVariationSettings();
     method public android.content.res.ColorStateList getLinkTextColor();
+    method public int getShadowColor();
+    method public float getShadowDx();
+    method public float getShadowDy();
+    method public float getShadowRadius();
     method public int getSpanTypeId();
     method public android.content.res.ColorStateList getTextColor();
+    method public int getTextFontWeight();
     method public int getTextSize();
     method public int getTextStyle();
+    method public android.graphics.Typeface getTypeface();
+    method public boolean isElegantTextHeight();
     method public void updateDrawState(android.text.TextPaint);
     method public void updateMeasureState(android.text.TextPaint);
     method public void writeToParcel(android.os.Parcel, int);
@@ -45617,6 +45707,7 @@
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
     method public V get(java.lang.Object);
     method public int indexOfKey(java.lang.Object);
+    method public int indexOfValue(java.lang.Object);
     method public boolean isEmpty();
     method public K keyAt(int);
     method public java.util.Set<K> keySet();
@@ -45637,6 +45728,7 @@
     ctor public ArraySet();
     ctor public ArraySet(int);
     ctor public ArraySet(android.util.ArraySet<E>);
+    ctor public ArraySet(java.util.Collection<? extends E>);
     method public boolean add(E);
     method public void addAll(android.util.ArraySet<? extends E>);
     method public boolean addAll(java.util.Collection<? extends E>);
@@ -46208,6 +46300,7 @@
     method public int keyAt(int);
     method public void put(int, boolean);
     method public void removeAt(int);
+    method public void setValueAt(int, boolean);
     method public int size();
     method public boolean valueAt(int);
   }
@@ -46226,6 +46319,7 @@
     method public int keyAt(int);
     method public void put(int, int);
     method public void removeAt(int);
+    method public void setValueAt(int, int);
     method public int size();
     method public int valueAt(int);
   }
@@ -51360,7 +51454,7 @@
   }
 
   public abstract class CookieManager {
-    ctor public CookieManager();
+    ctor public deprecated CookieManager();
     method public abstract boolean acceptCookie();
     method public abstract boolean acceptThirdPartyCookies(android.webkit.WebView);
     method public static boolean allowFileSchemeCookies();
@@ -51460,13 +51554,13 @@
   }
 
   public abstract class RenderProcessGoneDetail {
-    ctor public RenderProcessGoneDetail();
+    ctor public deprecated RenderProcessGoneDetail();
     method public abstract boolean didCrash();
     method public abstract int rendererPriorityAtExit();
   }
 
   public abstract class SafeBrowsingResponse {
-    ctor public SafeBrowsingResponse();
+    ctor public deprecated SafeBrowsingResponse();
     method public abstract void backToSafety(boolean);
     method public abstract void proceed(boolean);
     method public abstract void showInterstitial(boolean);
@@ -51478,7 +51572,7 @@
   }
 
   public abstract class ServiceWorkerController {
-    ctor public ServiceWorkerController();
+    ctor public deprecated ServiceWorkerController();
     method public static android.webkit.ServiceWorkerController getInstance();
     method public abstract android.webkit.ServiceWorkerWebSettings getServiceWorkerWebSettings();
     method public abstract void setServiceWorkerClient(android.webkit.ServiceWorkerClient);
@@ -51527,7 +51621,7 @@
   }
 
   public abstract class TracingController {
-    ctor public TracingController();
+    ctor public deprecated TracingController();
     method public static android.webkit.TracingController getInstance();
     method public abstract boolean isTracing();
     method public abstract void start(android.webkit.TracingConfig);
@@ -52067,7 +52161,7 @@
   }
 
   public abstract class WebViewDatabase {
-    ctor public WebViewDatabase();
+    ctor public deprecated WebViewDatabase();
     method public abstract deprecated void clearFormData();
     method public abstract void clearHttpAuthUsernamePassword();
     method public abstract deprecated void clearUsernamePassword();
@@ -53347,7 +53441,7 @@
   }
 
   public final class Magnifier {
-    ctor public Magnifier(android.view.View);
+    ctor public deprecated Magnifier(android.view.View);
     method public void dismiss();
     method public float getCornerRadius();
     method public int getDefaultHorizontalSourceToMagnifierOffset();
@@ -55175,6 +55269,7 @@
   public final class DelegateLastClassLoader extends dalvik.system.PathClassLoader {
     ctor public DelegateLastClassLoader(java.lang.String, java.lang.ClassLoader);
     ctor public DelegateLastClassLoader(java.lang.String, java.lang.String, java.lang.ClassLoader);
+    ctor public DelegateLastClassLoader(java.lang.String, java.lang.String, java.lang.ClassLoader, boolean);
   }
 
   public class DexClassLoader extends dalvik.system.BaseDexClassLoader {
diff --git a/api/removed.txt b/api/removed.txt
index b6dabcd..f7106d2 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -545,6 +545,7 @@
   }
 
   public class TelephonyManager {
+    method public deprecated java.util.List<android.telephony.NeighboringCellInfo> getNeighboringCellInfo();
     method public deprecated android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, android.telephony.TelephonyScanManager.NetworkScanCallback);
   }
 
diff --git a/api/system-current.txt b/api/system-current.txt
index 0038afb..5785e4a 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -950,6 +950,7 @@
     field public static final java.lang.String HDMI_CONTROL_SERVICE = "hdmi_control";
     field public static final java.lang.String NETWORK_SCORE_SERVICE = "network_score";
     field public static final java.lang.String OEM_LOCK_SERVICE = "oem_lock";
+    field public static final java.lang.String PERMISSION_SERVICE = "permission";
     field public static final java.lang.String PERSISTENT_DATA_BLOCK_SERVICE = "persistent_data_block";
     field public static final java.lang.String SECURE_ELEMENT_SERVICE = "secure_element";
     field public static final java.lang.String STATS_MANAGER = "stats";
@@ -4192,6 +4193,20 @@
 
 }
 
+package android.permission {
+
+  public final class PermissionManager {
+    method public java.util.List<android.permission.PermissionManager.SplitPermissionInfo> getSplitPermissions();
+  }
+
+  public static final class PermissionManager.SplitPermissionInfo {
+    method public java.lang.String[] getNewPermissions();
+    method public java.lang.String getRootPermission();
+    method public int getTargetSdk();
+  }
+
+}
+
 package android.permissionpresenterservice {
 
   public abstract class RuntimePermissionPresenterService extends android.app.Service {
@@ -5230,6 +5245,7 @@
     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();
     field public static final java.lang.String EXTRA_CALL_BACK_INTENT = "android.telecom.extra.CALL_BACK_INTENT";
@@ -5256,6 +5272,10 @@
     field public static final java.lang.String MBMS_DOWNLOAD_SERVICE_ACTION = "android.telephony.action.EmbmsDownload";
   }
 
+  public class MbmsGroupCallSession implements java.lang.AutoCloseable {
+    field public static final java.lang.String MBMS_GROUP_CALL_SERVICE_ACTION = "android.telephony.action.EmbmsGroupCall";
+  }
+
   public class MbmsStreamingSession implements java.lang.AutoCloseable {
     field public static final java.lang.String MBMS_STREAMING_SERVICE_ACTION = "android.telephony.action.EmbmsStreaming";
   }
@@ -5419,6 +5439,7 @@
     method public boolean disableDataConnectivity();
     method public boolean enableDataConnectivity();
     method public void enableVideoCalling(boolean);
+    method public java.lang.String getAidForAppType(int);
     method public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int);
     method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
     method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int);
@@ -5433,6 +5454,8 @@
     method public deprecated boolean getDataEnabled();
     method public deprecated boolean getDataEnabled(int);
     method public boolean getEmergencyCallbackMode();
+    method public java.lang.String getIsimDomain();
+    method public int getPreferredNetworkType(int);
     method public int getSimApplicationState();
     method public int getSimCardState();
     method public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms();
@@ -5442,10 +5465,7 @@
     method public boolean handlePinMmi(java.lang.String);
     method public boolean handlePinMmiForSubscriber(int, java.lang.String);
     method public boolean isDataConnectivityPossible();
-    method public deprecated boolean isIdle();
-    method public deprecated boolean isOffhook();
     method public deprecated boolean isRadioOn();
-    method public deprecated boolean isRinging();
     method public boolean isVideoCallingEnabled();
     method public deprecated boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle);
     method public boolean needsOtaServiceProvisioning();
@@ -5459,7 +5479,6 @@
     method public void setSimPowerStateForSlot(int, int);
     method public deprecated void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean);
     method public void setVoiceActivationState(int);
-    method public deprecated void silenceRinger();
     method public boolean supplyPin(java.lang.String);
     method public int[] supplyPinReportResult(java.lang.String);
     method public boolean supplyPuk(java.lang.String, java.lang.String);
@@ -5477,6 +5496,29 @@
     field public static final java.lang.String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE";
     field public static final java.lang.String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL = "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL";
     field public static final java.lang.String EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING = "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING";
+    field public static final int NETWORK_MODE_CDMA_EVDO = 4; // 0x4
+    field public static final int NETWORK_MODE_CDMA_NO_EVDO = 5; // 0x5
+    field public static final int NETWORK_MODE_EVDO_NO_CDMA = 6; // 0x6
+    field public static final int NETWORK_MODE_GLOBAL = 7; // 0x7
+    field public static final int NETWORK_MODE_GSM_ONLY = 1; // 0x1
+    field public static final int NETWORK_MODE_GSM_UMTS = 3; // 0x3
+    field public static final int NETWORK_MODE_LTE_CDMA_EVDO = 8; // 0x8
+    field public static final int NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA = 10; // 0xa
+    field public static final int NETWORK_MODE_LTE_GSM_WCDMA = 9; // 0x9
+    field public static final int NETWORK_MODE_LTE_ONLY = 11; // 0xb
+    field public static final int NETWORK_MODE_LTE_TDSCDMA = 15; // 0xf
+    field public static final int NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA = 22; // 0x16
+    field public static final int NETWORK_MODE_LTE_TDSCDMA_GSM = 17; // 0x11
+    field public static final int NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA = 20; // 0x14
+    field public static final int NETWORK_MODE_LTE_TDSCDMA_WCDMA = 19; // 0x13
+    field public static final int NETWORK_MODE_LTE_WCDMA = 12; // 0xc
+    field public static final int NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA = 21; // 0x15
+    field public static final int NETWORK_MODE_TDSCDMA_GSM = 16; // 0x10
+    field public static final int NETWORK_MODE_TDSCDMA_GSM_WCDMA = 18; // 0x12
+    field public static final int NETWORK_MODE_TDSCDMA_ONLY = 13; // 0xd
+    field public static final int NETWORK_MODE_TDSCDMA_WCDMA = 14; // 0xe
+    field public static final int NETWORK_MODE_WCDMA_ONLY = 2; // 0x2
+    field public static final int NETWORK_MODE_WCDMA_PREF = 0; // 0x0
     field public static final int SIM_ACTIVATION_STATE_ACTIVATED = 2; // 0x2
     field public static final int SIM_ACTIVATION_STATE_ACTIVATING = 1; // 0x1
     field public static final int SIM_ACTIVATION_STATE_DEACTIVATED = 3; // 0x3
@@ -5812,6 +5854,7 @@
     field public static final java.lang.String EXTRA_CODEC = "Codec";
     field public static final java.lang.String EXTRA_DIALSTRING = "dialstring";
     field public static final java.lang.String EXTRA_DISPLAY_TEXT = "DisplayText";
+    field public static final java.lang.String EXTRA_E_CALL = "e_call";
     field public static final java.lang.String EXTRA_IS_CALL_PULL = "CallPull";
     field public static final java.lang.String EXTRA_OI = "oi";
     field public static final java.lang.String EXTRA_OIR = "oir";
@@ -6556,6 +6599,17 @@
     method public int setTempFileRootDirectory(int, java.lang.String) throws android.os.RemoteException;
   }
 
+  public class MbmsGroupCallServiceBase extends android.app.Service {
+    ctor public MbmsGroupCallServiceBase();
+    method public void dispose(int) throws android.os.RemoteException;
+    method public int initialize(android.telephony.mbms.MbmsGroupCallSessionCallback, int) throws android.os.RemoteException;
+    method public void onAppCallbackDied(int, int);
+    method public android.os.IBinder onBind(android.content.Intent);
+    method public int startGroupCall(int, long, int[], int[], android.telephony.mbms.GroupCallCallback);
+    method public void stopGroupCall(int, long);
+    method public void updateGroupCall(int, long, int[], int[]);
+  }
+
   public class MbmsStreamingServiceBase extends android.os.Binder {
     ctor public MbmsStreamingServiceBase();
     method public void dispose(int) throws android.os.RemoteException;
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 9012c33..2246562 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -148,6 +148,10 @@
   public class TelephonyManager {
     method public deprecated void answerRingingCall();
     method public deprecated boolean endCall();
+    method public deprecated boolean isIdle();
+    method public deprecated boolean isOffhook();
+    method public deprecated boolean isRinging();
+    method public deprecated void silenceRinger();
   }
 
 }
diff --git a/api/test-current.txt b/api/test-current.txt
index f4d7cbc..9567616 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1188,6 +1188,10 @@
     field public static final java.lang.String MBMS_DOWNLOAD_SERVICE_OVERRIDE_METADATA = "mbms-download-service-override";
   }
 
+  public class MbmsGroupCallSession implements java.lang.AutoCloseable {
+    field public static final java.lang.String MBMS_GROUP_CALL_SERVICE_OVERRIDE_METADATA = "mbms-group-call-service-override";
+  }
+
   public class MbmsStreamingSession implements java.lang.AutoCloseable {
     field public static final java.lang.String MBMS_STREAMING_SERVICE_OVERRIDE_METADATA = "mbms-streaming-service-override";
   }
@@ -1257,6 +1261,17 @@
     method public int setTempFileRootDirectory(int, java.lang.String) throws android.os.RemoteException;
   }
 
+  public class MbmsGroupCallServiceBase extends android.app.Service {
+    ctor public MbmsGroupCallServiceBase();
+    method public void dispose(int) throws android.os.RemoteException;
+    method public int initialize(android.telephony.mbms.MbmsGroupCallSessionCallback, int) throws android.os.RemoteException;
+    method public void onAppCallbackDied(int, int);
+    method public android.os.IBinder onBind(android.content.Intent);
+    method public int startGroupCall(int, long, int[], int[], android.telephony.mbms.GroupCallCallback);
+    method public void stopGroupCall(int, long);
+    method public void updateGroupCall(int, long, int[], int[]);
+  }
+
   public class MbmsStreamingServiceBase extends android.os.Binder {
     ctor public MbmsStreamingServiceBase();
     method public void dispose(int) throws android.os.RemoteException;
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index 27c5a17..f6b0db8 100644
--- a/cmds/statsd/Android.mk
+++ b/cmds/statsd/Android.mk
@@ -99,6 +99,7 @@
     libhidlbase \
     libhidltransport \
     libhwbinder \
+    android.frameworks.stats@1.0 \
     android.hardware.health@2.0 \
     android.hardware.power@1.0 \
     android.hardware.power@1.1 \
@@ -146,10 +147,10 @@
 LOCAL_MODULE_CLASS := EXECUTABLES
 
 # Enable sanitizer ONLY on eng builds.
-ifeq ($(TARGET_BUILD_VARIANT),eng)
-    LOCAL_CLANG := true
-    LOCAL_SANITIZE := address
-endif
+#ifeq ($(TARGET_BUILD_VARIANT),eng)
+#    LOCAL_CLANG := true
+#    LOCAL_SANITIZE := address
+#endif
 
 # Add a flag to enable stats log printing from statsd on debug builds.
 ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT)))
@@ -227,7 +228,8 @@
     tests/e2e/Anomaly_count_e2e_test.cpp \
     tests/e2e/Anomaly_duration_sum_e2e_test.cpp \
     tests/e2e/ConfigTtl_e2e_test.cpp \
-    tests/e2e/PartialBucket_e2e_test.cpp
+    tests/e2e/PartialBucket_e2e_test.cpp \
+    tests/shell/ShellSubscriber_test.cpp
 
 LOCAL_STATIC_LIBRARIES := \
     $(statsd_common_static_libraries) \
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 2ef1169..8da2d44 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -992,6 +992,60 @@
     return Status::ok();
 }
 
+hardware::Return<void> StatsService::reportSpeakerImpedance(
+        const SpeakerImpedance& speakerImpedance) {
+    LogEvent event(getWallClockSec() * NS_PER_SEC, getElapsedRealtimeNs(), speakerImpedance);
+    mProcessor->OnLogEvent(&event);
+
+    return hardware::Void();
+}
+
+hardware::Return<void> StatsService::reportHardwareFailed(const HardwareFailed& hardwareFailed) {
+    LogEvent event(getWallClockSec() * NS_PER_SEC, getElapsedRealtimeNs(), hardwareFailed);
+    mProcessor->OnLogEvent(&event);
+
+    return hardware::Void();
+}
+
+hardware::Return<void> StatsService::reportPhysicalDropDetected(
+        const PhysicalDropDetected& physicalDropDetected) {
+    LogEvent event(getWallClockSec() * NS_PER_SEC, getElapsedRealtimeNs(), physicalDropDetected);
+    mProcessor->OnLogEvent(&event);
+
+    return hardware::Void();
+}
+
+hardware::Return<void> StatsService::reportChargeCycles(const ChargeCycles& chargeCycles) {
+    LogEvent event(getWallClockSec() * NS_PER_SEC, getElapsedRealtimeNs(), chargeCycles);
+    mProcessor->OnLogEvent(&event);
+
+    return hardware::Void();
+}
+
+hardware::Return<void> StatsService::reportBatteryHealthSnapshot(
+        const BatteryHealthSnapshotArgs& batteryHealthSnapshotArgs) {
+    LogEvent event(getWallClockSec() * NS_PER_SEC, getElapsedRealtimeNs(),
+                   batteryHealthSnapshotArgs);
+    mProcessor->OnLogEvent(&event);
+
+    return hardware::Void();
+}
+
+hardware::Return<void> StatsService::reportSlowIo(const SlowIo& slowIo) {
+    LogEvent event(getWallClockSec() * NS_PER_SEC, getElapsedRealtimeNs(), slowIo);
+    mProcessor->OnLogEvent(&event);
+
+    return hardware::Void();
+}
+
+hardware::Return<void> StatsService::reportBatteryCausedShutdown(
+        const BatteryCausedShutdown& batteryCausedShutdown) {
+    LogEvent event(getWallClockSec() * NS_PER_SEC, getElapsedRealtimeNs(), batteryCausedShutdown);
+    mProcessor->OnLogEvent(&event);
+
+    return hardware::Void();
+}
+
 void StatsService::binderDied(const wp <IBinder>& who) {
     ALOGW("statscompanion service died");
     StatsdStats::getInstance().noteSystemServerRestart(getWallClockSec());
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index 0618927..1f1d782 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -27,6 +27,8 @@
 #include "shell/ShellSubscriber.h"
 #include "statscompanion_util.h"
 
+#include <android/frameworks/stats/1.0/IStats.h>
+#include <android/frameworks/stats/1.0/types.h>
 #include <android/os/BnStatsManager.h>
 #include <android/os/IStatsCompanionService.h>
 #include <binder/IResultReceiver.h>
@@ -38,6 +40,7 @@
 using namespace android;
 using namespace android::base;
 using namespace android::binder;
+using namespace android::frameworks::stats::V1_0;
 using namespace android::os;
 using namespace std;
 
@@ -45,7 +48,12 @@
 namespace os {
 namespace statsd {
 
-class StatsService : public BnStatsManager, public LogListener, public IBinder::DeathRecipient {
+using android::hardware::Return;
+
+class StatsService : public BnStatsManager,
+                     public LogListener,
+                     public IStats,
+                     public IBinder::DeathRecipient {
 public:
     StatsService(const sp<Looper>& handlerLooper);
     virtual ~StatsService();
@@ -146,6 +154,44 @@
      */
     virtual Status sendAppBreadcrumbAtom(int32_t label, int32_t state) override;
 
+    /**
+     * Binder call to get SpeakerImpedance atom.
+     */
+    virtual Return<void> reportSpeakerImpedance(const SpeakerImpedance& speakerImpedance) override;
+
+    /**
+     * Binder call to get HardwareFailed atom.
+     */
+    virtual Return<void> reportHardwareFailed(const HardwareFailed& hardwareFailed) override;
+
+    /**
+     * Binder call to get PhysicalDropDetected atom.
+     */
+    virtual Return<void> reportPhysicalDropDetected(
+            const PhysicalDropDetected& physicalDropDetected) override;
+
+    /**
+     * Binder call to get ChargeCyclesReported atom.
+     */
+    virtual Return<void> reportChargeCycles(const ChargeCycles& chargeCycles) override;
+
+    /**
+     * Binder call to get BatteryHealthSnapshot atom.
+     */
+    virtual Return<void> reportBatteryHealthSnapshot(
+            const BatteryHealthSnapshotArgs& batteryHealthSnapshotArgs) override;
+
+    /**
+     * Binder call to get SlowIo atom.
+     */
+    virtual Return<void> reportSlowIo(const SlowIo& slowIo) override;
+
+    /**
+     * Binder call to get BatteryCausedShutdown atom.
+     */
+    virtual Return<void> reportBatteryCausedShutdown(
+            const BatteryCausedShutdown& batteryCausedShutdown) override;
+
     /** IBinder::DeathRecipient */
     virtual void binderDied(const wp<IBinder>& who) override;
 
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 485b91f..988ffc4 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -80,7 +80,8 @@
         BatteryLevelChanged battery_level_changed = 30;
         ChargingStateChanged charging_state_changed = 31;
         PluggedStateChanged plugged_state_changed = 32;
-        // 33 - 34 are available
+        InteractiveStateChanged interactive_state_changed = 33;
+        // 34 is available
         WakeupAlarmOccurred wakeup_alarm_occurred = 35;
         KernelWakeupReported kernel_wakeup_reported = 36;
         WifiLockStateChanged wifi_lock_state_changed = 37;
@@ -136,6 +137,10 @@
         FingerprintAcquired fingerprint_acquired = 87;
         FingerprintAuthenticated fingerprint_authenticated = 88;
         FingerprintErrorOccurred fingerprint_error_occurred = 89;
+        Notification notification = 90;
+        BatteryHealthSnapshot battery_health_snapshot = 91;
+        SlowIo slow_io = 92;
+        BatteryCausedShutdown battery_caused_shutdown = 93;
     }
 
     // Pulled events will start at field 10000.
@@ -173,6 +178,7 @@
         BatteryVoltage battery_voltage = 10030;
         NumFingerprints num_fingerprints = 10031;
         ProcStats proc_stats = 10029;
+        DiskIo disk_io = 10032;
     }
 
     // DO NOT USE field numbers above 100,000 in AOSP.
@@ -198,9 +204,10 @@
 message KeyValuePair {
     optional int32 key = 1;
     oneof value {
-        int64 value_int = 2;
-        string value_str = 3;
-        float value_float = 4;
+        int32 value_int = 2;
+        int64 value_long = 3;
+        string value_str = 4;
+        float value_float = 5;
     }
 }
 
@@ -664,6 +671,20 @@
 }
 
 /**
+ * Logs when the device is interactive, according to the PowerManager Notifier.
+ *
+ * Logged from:
+ *   frameworks/base/services/core/java/com/android/server/power/Notifier.java
+ */
+message InteractiveStateChanged {
+    enum State {
+        OFF = 0;
+        ON = 1;
+    }
+    optional State state = 1;
+}
+
+/**
  * Logs Battery Saver state change.
  *
  * Logged from:
@@ -753,6 +774,9 @@
 
     // Name of the wakeup alarm.
     optional string tag = 2;
+
+    // Name of source package (for historical reasons, since BatteryStats tracked it).
+    optional string package_name = 3;
 }
 
 /**
@@ -1293,6 +1317,68 @@
 }
 
 /**
+ * Log battery health snapshot.
+ *
+ * Resistance, Voltage, Open Circuit Voltage, Temperature, and Charge Level
+ * are snapshotted periodically over 24hrs.
+ */
+message BatteryHealthSnapshot {
+    enum BatterySnapshotType {
+        UNKNOWN = 0;
+        MIN_TEMP = 1;         // Snapshot at min batt temp over 24hrs.
+        MAX_TEMP = 2;         // Snapshot at max batt temp over 24hrs.
+        MIN_RESISTANCE = 3;   // Snapshot at min batt resistance over 24hrs.
+        MAX_RESISTANCE = 4;   // Snapshot at max batt resistance over 24hrs.
+        MIN_VOLTAGE = 5;      // Snapshot at min batt voltage over 24hrs.
+        MAX_VOLTAGE = 6;      // Snapshot at max batt voltage over 24hrs.
+        MIN_CURRENT = 7;      // Snapshot at min batt current over 24hrs.
+        MAX_CURRENT = 8;      // Snapshot at max batt current over 24hrs.
+        MIN_BATT_LEVEL = 9;   // Snapshot at min battery level (SoC) over 24hrs.
+        MAX_BATT_LEVEL = 10;  // Snapshot at max battery level (SoC) over 24hrs.
+        AVG_RESISTANCE = 11;  // Snapshot at average battery resistance over 24hrs.
+    }
+    optional BatterySnapshotType type = 1;
+    // Temperature, in 1/10ths of degree C.
+    optional int32 temperature_deci_celcius = 2;
+    // Voltage Battery Voltage, in microVolts.
+    optional int32 voltage_micro_volt = 3;
+    // Current Battery current, in microAmps.
+    optional int32 current_micro_amps = 4;
+    // OpenCircuitVoltage Battery Open Circuit Voltage, in microVolts.
+    optional int32 open_circuit_micro_volt = 5;
+    // Resistance Battery Resistance, in microOhms.
+    optional int32 resistance_micro_ohm = 6;
+    // Level Battery Level, as % of full.
+    optional int32 level_percent = 7;
+}
+
+/**
+ * Log slow I/O operations on the primary storage.
+ */
+message SlowIo {
+    // Classifications of IO Operations.
+    enum IoOperation {
+        UNKNOWN = 0;
+        READ = 1;
+        WRITE = 2;
+        UNMAP = 3;
+        SYNC = 4;
+    }
+    optional IoOperation operation = 1;
+
+    // The number of slow IO operations of this type over 24 hours.
+    optional int32 count = 2;
+}
+
+/**
+ * Log battery caused shutdown with the last recorded voltage.
+ */
+message BatteryCausedShutdown {
+    // The last recorded battery voltage prior to shutdown.
+    optional int32 last_recorded_micro_volt = 1;
+}
+
+/**
  * Logs the duration of a davey (jank of >=700ms) when it occurs
  *
  * Logged from:
@@ -1891,6 +1977,69 @@
     // The type of error.
     optional Error error = 3;
 }
+
+message Notification {
+
+    // Type of notification event.
+    enum Type {
+        TYPE_UNKNOWN = 0;
+        // Notification became visible to the user.
+        TYPE_OPEN = 1;
+        // Notification became hidden.
+        TYPE_CLOSE = 2;
+        // Notification switched to detail mode.
+        TYPE_DETAIL = 3;
+        // Notification was clicked.
+        TYPE_ACTION = 4;
+        // Notification was dismissed.
+        TYPE_DISMISS = 5;
+        // Notification switched to summary mode. The enum value of 14 is to
+        // match that of metrics_constants.
+        TYPE_COLLAPSE = 14;
+    }
+    optional Type type = 1;
+
+    // Package name associated with the notification.
+    optional string package_name = 2;
+
+    // Tag associated with notification.
+    optional string tag = 3;
+
+    // Application-supplied ID associated with the notification.
+    optional int32 id = 4;
+
+    // Index of notification in the notification panel.
+    optional int32 shade_index = 5;
+
+    // The number of notifications in the notification panel.
+    optional int32 shade_count = 6;
+
+    // Importance for the notification.
+    optional int32 importance = 7;
+
+    // ID for the notification channel.
+    optional int32 channel_id = 8;
+
+    // Importance for the notification channel.
+    optional int32 channel_importance = 9;
+
+    // Whether notification was a group summary.
+    optional bool group_summary = 10;
+
+    // Time since notification was created in milliseconds.
+    optional int64 since_create_millis = 11;
+
+    // Time since notification was interrupted in milliseconds.
+    optional int64 since_interruption_millis = 12;
+
+    // Time since notification was updated in milliseconds.
+    optional int64 since_update_millis = 13;
+
+    // Time since notification was visible in milliseconds.
+    optional int64 since_visible_millis = 14;
+}
+
+
 //////////////////////////////////////////////////////////////////////
 // Pulled atoms below this line //
 //////////////////////////////////////////////////////////////////////
@@ -2156,6 +2305,11 @@
 
     // SWAP
     optional int64 swap_in_bytes = 8;
+
+    // RSS high watermark.
+    // Peak RSS usage of the process. Value is read from the VmHWM field in /proc/PID/status or
+    // from memory.max_usage_in_bytes under /dev/memcg if the device uses per-app memory cgroups.
+    optional int64 rss_high_watermark_in_bytes = 9;
 }
 
 /*
@@ -2469,6 +2623,30 @@
 }
 
 /**
+ * Pulls per uid I/O stats. The stats are cumulative since boot.
+ *
+ * Read/write bytes are I/O events from a storage device
+ * Read/write chars are data requested by read/write syscalls, and can be
+ *   satisfied by caching.
+ *
+ * Pulled from StatsCompanionService, which reads proc/uid_io/stats.
+ */
+message DiskIo {
+    optional int32 uid = 1 [(is_uid) = true];
+    optional int64 fg_chars_read = 2;
+    optional int64 fg_chars_write = 3;
+    optional int64 fg_bytes_read = 4;
+    optional int64 fg_bytes_write = 5;
+    optional int64 bg_chars_read = 6;
+    optional int64 bg_chars_write = 7;
+    optional int64 bg_bytes_read = 8;
+    optional int64 bg_bytes_write = 9;
+    optional int64 fg_fsync = 10;
+    optional int64 bg_fsync= 11;
+}
+
+
+/**
  * Pulls the number of fingerprints for each user.
  *
  * Pulled from StatsCompanionService, which queries FingerprintManager.
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 5a0172b..fd86714 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -163,13 +163,10 @@
           new ResourceHealthManagerPuller(android::util::FULL_BATTERY_CAPACITY)}},
         // battery_voltage
         {android::util::BATTERY_VOLTAGE,
-         {{},
-          {},
-          1 * NS_PER_SEC,
-          new ResourceHealthManagerPuller(android::util::BATTERY_VOLTAGE)}},
+         {{}, {}, 1 * NS_PER_SEC, new ResourceHealthManagerPuller(android::util::BATTERY_VOLTAGE)}},
         // process_memory_state
         {android::util::PROCESS_MEMORY_STATE,
-         {{4, 5, 6, 7, 8},
+         {{4, 5, 6, 7, 8, 9},
           {2, 3},
           1 * NS_PER_SEC,
           new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_STATE)}},
@@ -204,17 +201,23 @@
          {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::APP_SIZE)}},
         // Size of specific categories of files. Eg. Music.
         {android::util::CATEGORY_SIZE,
-         {{},
-          {},
-          1 * NS_PER_SEC,
-          new StatsCompanionServicePuller(android::util::CATEGORY_SIZE)}},
+         {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CATEGORY_SIZE)}},
         // Number of fingerprints registered to each user.
         {android::util::NUM_FINGERPRINTS,
          {{},
           {},
           1 * NS_PER_SEC,
           new StatsCompanionServicePuller(android::util::NUM_FINGERPRINTS)}},
-        };
+        // ProcStats.
+        {android::util::PROC_STATS,
+         {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::PROC_STATS)}},
+        // Disk I/O stats per uid.
+        {android::util::DISK_IO,
+         {{2,3,4,5,6,7,8,9,10,11},
+          {},
+          3 * NS_PER_SEC,
+          new StatsCompanionServicePuller(android::util::DISK_IO)}},
+};
 
 StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) {
 }
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index f9f1b38..4bbcfd5 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -92,7 +92,8 @@
 
 LogEvent::LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
                    int32_t uid,
-                   const std::map<int32_t, int64_t>& int_map,
+                   const std::map<int32_t, int32_t>& int_map,
+                   const std::map<int32_t, int64_t>& long_map,
                    const std::map<int32_t, std::string>& string_map,
                    const std::map<int32_t, float>& float_map) {
     mLogdTimestampNs = wallClockTimestampNs;
@@ -113,7 +114,7 @@
         pos[1]++;
     }
 
-    for (const auto&itr : string_map) {
+    for (const auto&itr : long_map) {
         pos[2] = 1;
         mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.first)));
         pos[2] = 3;
@@ -122,7 +123,7 @@
         pos[1]++;
     }
 
-    for (const auto&itr : float_map) {
+    for (const auto&itr : string_map) {
         pos[2] = 1;
         mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.first)));
         pos[2] = 4;
@@ -130,12 +131,142 @@
         mValues.back().mField.decorateLastPos(2);
         pos[1]++;
     }
+
+    for (const auto&itr : float_map) {
+        pos[2] = 1;
+        mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.first)));
+        pos[2] = 5;
+        mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.second)));
+        mValues.back().mField.decorateLastPos(2);
+        pos[1]++;
+    }
     if (!mValues.empty()) {
         mValues.back().mField.decorateLastPos(1);
         mValues.at(mValues.size() - 2).mField.decorateLastPos(1);
     }
 }
 
+LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
+                   const SpeakerImpedance& speakerImpedance) {
+    mLogdTimestampNs = wallClockTimestampNs;
+    mElapsedTimestampNs = elapsedTimestampNs;
+    mTagId = android::util::SPEAKER_IMPEDANCE_REPORTED;
+
+    mValues.push_back(
+            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,
+                   const HardwareFailed& hardwareFailed) {
+    mLogdTimestampNs = wallClockTimestampNs;
+    mElapsedTimestampNs = elapsedTimestampNs;
+    mTagId = android::util::HARDWARE_FAILED;
+
+    mValues.push_back(FieldValue(Field(mTagId, getSimpleField(1)),
+                                 Value(int32_t(hardwareFailed.hardwareType))));
+    mValues.push_back(
+            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,
+                   const PhysicalDropDetected& physicalDropDetected) {
+    mLogdTimestampNs = wallClockTimestampNs;
+    mElapsedTimestampNs = elapsedTimestampNs;
+    mTagId = android::util::PHYSICAL_DROP_DETECTED;
+
+    mValues.push_back(FieldValue(Field(mTagId, getSimpleField(1)),
+                                 Value(int32_t(physicalDropDetected.confidencePctg))));
+    mValues.push_back(
+            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,
+                   const ChargeCycles& chargeCycles) {
+    mLogdTimestampNs = wallClockTimestampNs;
+    mElapsedTimestampNs = elapsedTimestampNs;
+    mTagId = android::util::CHARGE_CYCLES_REPORTED;
+
+    for (size_t i = 0; i < chargeCycles.cycleBucket.size(); i++) {
+        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,
+                   const BatteryHealthSnapshotArgs& batteryHealthSnapshotArgs) {
+    mLogdTimestampNs = wallClockTimestampNs;
+    mElapsedTimestampNs = elapsedTimestampNs;
+    mTagId = android::util::BATTERY_HEALTH_SNAPSHOT;
+
+    mValues.push_back(FieldValue(Field(mTagId, getSimpleField(1)),
+                                 Value(int32_t(batteryHealthSnapshotArgs.type))));
+    mValues.push_back(FieldValue(Field(mTagId, getSimpleField(2)),
+                                 Value(batteryHealthSnapshotArgs.temperatureDeciC)));
+    mValues.push_back(FieldValue(Field(mTagId, getSimpleField(3)),
+                                 Value(batteryHealthSnapshotArgs.voltageMicroV)));
+    mValues.push_back(FieldValue(Field(mTagId, getSimpleField(4)),
+                                 Value(batteryHealthSnapshotArgs.currentMicroA)));
+    mValues.push_back(FieldValue(Field(mTagId, getSimpleField(5)),
+                                 Value(batteryHealthSnapshotArgs.openCircuitVoltageMicroV)));
+    mValues.push_back(FieldValue(Field(mTagId, getSimpleField(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) {
+    mLogdTimestampNs = wallClockTimestampNs;
+    mElapsedTimestampNs = elapsedTimestampNs;
+    mTagId = android::util::SLOW_IO;
+
+    int pos[] = {1};
+    mValues.push_back(
+            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,
+                   const BatteryCausedShutdown& batteryCausedShutdown) {
+    mLogdTimestampNs = wallClockTimestampNs;
+    mElapsedTimestampNs = elapsedTimestampNs;
+    mTagId = android::util::BATTERY_CAUSED_SHUTDOWN;
+
+    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) {
     mLogdTimestampNs = timestampNs;
     mTagId = tagId;
@@ -213,9 +344,8 @@
     return false;
 }
 
-
-
-bool LogEvent::writeKeyValuePairs(const std::map<int32_t, int64_t>& int_map,
+bool LogEvent::writeKeyValuePairs(const std::map<int32_t, int32_t>& int_map,
+                                  const std::map<int32_t, int64_t>& long_map,
                                   const std::map<int32_t, std::string>& string_map,
                                   const std::map<int32_t, float>& float_map) {
     if (mContext) {
@@ -233,6 +363,17 @@
              }
          }
 
+         for (const auto& itr : long_map) {
+             if (android_log_write_list_begin(mContext) < 0) {
+                return false;
+             }
+             write(itr.first);
+             write(itr.second);
+             if (android_log_write_list_end(mContext) < 0) {
+                return false;
+             }
+         }
+
          for (const auto& itr : string_map) {
              if (android_log_write_list_begin(mContext) < 0) {
                 return false;
diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h
index 9ef0bf4..c7e2a8c 100644
--- a/cmds/statsd/src/logd/LogEvent.h
+++ b/cmds/statsd/src/logd/LogEvent.h
@@ -18,6 +18,7 @@
 
 #include "FieldValue.h"
 
+#include <android/frameworks/stats/1.0/types.h>
 #include <android/os/StatsLogEventWrapper.h>
 #include <android/util/ProtoOutputStream.h>
 #include <log/log_event_list.h>
@@ -28,6 +29,8 @@
 #include <string>
 #include <vector>
 
+using namespace android::frameworks::stats::V1_0;
+
 namespace android {
 namespace os {
 namespace statsd {
@@ -77,10 +80,32 @@
      */
     explicit LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
                       int32_t uid,
-                      const std::map<int32_t, int64_t>& int_map,
+                      const std::map<int32_t, int32_t>& int_map,
+                      const std::map<int32_t, int64_t>& long_map,
                       const std::map<int32_t, std::string>& string_map,
                       const std::map<int32_t, float>& float_map);
 
+    explicit LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
+                      const SpeakerImpedance& speakerImpedance);
+
+    explicit LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
+                      const HardwareFailed& hardwareFailed);
+
+    explicit LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
+                      const PhysicalDropDetected& physicalDropDetected);
+
+    explicit LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
+                      const ChargeCycles& chargeCycles);
+
+    explicit LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
+                      const BatteryHealthSnapshotArgs& batteryHealthSnapshotArgs);
+
+    explicit LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
+                      const SlowIo& slowIo);
+
+    explicit LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
+                      const BatteryCausedShutdown& batteryCausedShutdown);
+
     ~LogEvent();
 
     /**
@@ -122,7 +147,8 @@
     bool write(float value);
     bool write(const std::vector<AttributionNodeInternal>& nodes);
     bool write(const AttributionNodeInternal& node);
-    bool writeKeyValuePairs(const std::map<int32_t, int64_t>& int_map,
+    bool writeKeyValuePairs(const std::map<int32_t, int32_t>& int_map,
+                            const std::map<int32_t, int64_t>& long_map,
                             const std::map<int32_t, std::string>& string_map,
                             const std::map<int32_t, float>& float_map);
 
diff --git a/cmds/statsd/src/main.cpp b/cmds/statsd/src/main.cpp
index 9002f07..a5dac08 100644
--- a/cmds/statsd/src/main.cpp
+++ b/cmds/statsd/src/main.cpp
@@ -25,6 +25,7 @@
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
 #include <binder/Status.h>
+#include <hidl/HidlTransportSupport.h>
 #include <utils/Looper.h>
 #include <utils/StrongPointer.h>
 
@@ -56,12 +57,21 @@
     ps->giveThreadPoolName();
     IPCThreadState::self()->disableBackgroundScheduling(true);
 
+    ::android::hardware::configureRpcThreadpool(1 /*threads*/, false /*willJoin*/);
+
     // Create the service
     sp<StatsService> service = new StatsService(looper);
     if (defaultServiceManager()->addService(String16("stats"), service) != 0) {
-        ALOGE("Failed to add service");
+        ALOGE("Failed to add service as AIDL service");
         return -1;
     }
+
+    auto ret = service->registerAsService();
+    if (ret != ::android::OK) {
+        ALOGE("Failed to add service as HIDL service");
+        return 1; // or handle error
+    }
+
     service->sayHiToStatsCompanion();
 
     service->Startup();
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index 9d9e5be..dd3402d 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -781,7 +781,7 @@
         if (whatIt != mCurrentSlicedDurationTrackerMap.end()) {
             for (const auto& condIt : whatIt->second) {
                 const bool cond = dimensionKeysInCondition.find(condIt.first) !=
-                        dimensionKeysInCondition.end();
+                        dimensionKeysInCondition.end() && condition;
                 handleStartEvent(MetricDimensionKey(dimensionInWhat, condIt.first),
                     conditionKey, cond, event);
                 dimensionKeysInCondition.erase(condIt.first);
diff --git a/cmds/statsd/src/shell/ShellSubscriber.cpp b/cmds/statsd/src/shell/ShellSubscriber.cpp
index 3cd49d7..1306a46 100644
--- a/cmds/statsd/src/shell/ShellSubscriber.cpp
+++ b/cmds/statsd/src/shell/ShellSubscriber.cpp
@@ -113,12 +113,12 @@
 
     for (const auto& matcher : mPushedMatchers) {
         if (matchesSimple(*mUidMap, matcher, event)) {
+            event.ToProto(mProto);
             // First write the payload size.
             size_t bufferSize = mProto.size();
             write(mOutput, &bufferSize, sizeof(bufferSize));
 
             // Then write the payload.
-            event.ToProto(mProto);
             mProto.flush(mOutput);
             mProto.clear();
             break;
@@ -137,4 +137,4 @@
 
 }  // namespace statsd
 }  // namespace os
-}  // namespace android
\ No newline at end of file
+}  // namespace android
diff --git a/cmds/statsd/tests/LogEvent_test.cpp b/cmds/statsd/tests/LogEvent_test.cpp
index 6e3b04c..d490701 100644
--- a/cmds/statsd/tests/LogEvent_test.cpp
+++ b/cmds/statsd/tests/LogEvent_test.cpp
@@ -91,12 +91,16 @@
 
 TEST(LogEventTest, TestKeyValuePairsAtomParsing) {
     LogEvent event1(83, 2000);
-    std::map<int32_t, int64_t> int_map;
+    std::map<int32_t, int32_t> int_map;
+    std::map<int32_t, int64_t> long_map;
     std::map<int32_t, std::string> string_map;
     std::map<int32_t, float> float_map;
 
-    int_map[11] = 123L;
-    int_map[22] = 345L;
+    int_map[11] = 123;
+    int_map[22] = 345;
+
+    long_map[33] = 678L;
+    long_map[44] = 890L;
 
     string_map[1] = "test2";
     string_map[2] = "test1";
@@ -104,12 +108,15 @@
     float_map[111] = 2.2f;
     float_map[222] = 1.1f;
 
-    EXPECT_TRUE(event1.writeKeyValuePairs(int_map, string_map, float_map));
+    EXPECT_TRUE(event1.writeKeyValuePairs(int_map,
+                                          long_map,
+                                          string_map,
+                                          float_map));
     event1.init();
 
     EXPECT_EQ(83, event1.GetTagId());
     const auto& items = event1.getValues();
-    EXPECT_EQ((size_t)12, items.size());
+    EXPECT_EQ((size_t)16, items.size());
 
     const FieldValue& item0 = event1.getValues()[0];
     EXPECT_EQ(0x2010101, item0.mField.getField());
@@ -118,8 +125,8 @@
 
     const FieldValue& item1 = event1.getValues()[1];
     EXPECT_EQ(0x2010182, item1.mField.getField());
-    EXPECT_EQ(Type::LONG, item1.mValue.getType());
-    EXPECT_EQ(123L, item1.mValue.long_value);
+    EXPECT_EQ(Type::INT, item1.mValue.getType());
+    EXPECT_EQ(123, item1.mValue.int_value);
 
     const FieldValue& item2 = event1.getValues()[2];
     EXPECT_EQ(0x2010201, item2.mField.getField());
@@ -128,48 +135,68 @@
 
     const FieldValue& item3 = event1.getValues()[3];
     EXPECT_EQ(0x2010282, item3.mField.getField());
-    EXPECT_EQ(Type::LONG, item3.mValue.getType());
-    EXPECT_EQ(345L, item3.mValue.long_value);
+    EXPECT_EQ(Type::INT, item3.mValue.getType());
+    EXPECT_EQ(345, item3.mValue.int_value);
 
     const FieldValue& item4 = event1.getValues()[4];
     EXPECT_EQ(0x2010301, item4.mField.getField());
     EXPECT_EQ(Type::INT, item4.mValue.getType());
-    EXPECT_EQ(1, item4.mValue.int_value);
+    EXPECT_EQ(33, item4.mValue.int_value);
 
     const FieldValue& item5 = event1.getValues()[5];
-    EXPECT_EQ(0x2010383, item5.mField.getField());
-    EXPECT_EQ(Type::STRING, item5.mValue.getType());
-    EXPECT_EQ("test2", item5.mValue.str_value);
+    EXPECT_EQ(0x2010382, item5.mField.getField());
+    EXPECT_EQ(Type::LONG, item5.mValue.getType());
+    EXPECT_EQ(678L, item5.mValue.int_value);
 
     const FieldValue& item6 = event1.getValues()[6];
     EXPECT_EQ(0x2010401, item6.mField.getField());
     EXPECT_EQ(Type::INT, item6.mValue.getType());
-    EXPECT_EQ(2, item6.mValue.int_value);
+    EXPECT_EQ(44, item6.mValue.int_value);
 
     const FieldValue& item7 = event1.getValues()[7];
-    EXPECT_EQ(0x2010483, item7.mField.getField());
-    EXPECT_EQ(Type::STRING, item7.mValue.getType());
-    EXPECT_EQ("test1", item7.mValue.str_value);
+    EXPECT_EQ(0x2010482, item7.mField.getField());
+    EXPECT_EQ(Type::LONG, item7.mValue.getType());
+    EXPECT_EQ(890L, item7.mValue.int_value);
 
     const FieldValue& item8 = event1.getValues()[8];
     EXPECT_EQ(0x2010501, item8.mField.getField());
     EXPECT_EQ(Type::INT, item8.mValue.getType());
-    EXPECT_EQ(111, item8.mValue.int_value);
+    EXPECT_EQ(1, item8.mValue.int_value);
 
     const FieldValue& item9 = event1.getValues()[9];
-    EXPECT_EQ(0x2010584, item9.mField.getField());
-    EXPECT_EQ(Type::FLOAT, item9.mValue.getType());
-    EXPECT_EQ(2.2f, item9.mValue.float_value);
+    EXPECT_EQ(0x2010583, item9.mField.getField());
+    EXPECT_EQ(Type::STRING, item9.mValue.getType());
+    EXPECT_EQ("test2", item9.mValue.str_value);
 
     const FieldValue& item10 = event1.getValues()[10];
-    EXPECT_EQ(0x2018601, item10.mField.getField());
+    EXPECT_EQ(0x2010601, item10.mField.getField());
     EXPECT_EQ(Type::INT, item10.mValue.getType());
-    EXPECT_EQ(222, item10.mValue.int_value);
+    EXPECT_EQ(2, item10.mValue.int_value);
 
     const FieldValue& item11 = event1.getValues()[11];
-    EXPECT_EQ(0x2018684, item11.mField.getField());
-    EXPECT_EQ(Type::FLOAT, item11.mValue.getType());
-    EXPECT_EQ(1.1f, item11.mValue.float_value);
+    EXPECT_EQ(0x2010683, item11.mField.getField());
+    EXPECT_EQ(Type::STRING, item11.mValue.getType());
+    EXPECT_EQ("test1", item11.mValue.str_value);
+
+    const FieldValue& item12 = event1.getValues()[12];
+    EXPECT_EQ(0x2010701, item12.mField.getField());
+    EXPECT_EQ(Type::INT, item12.mValue.getType());
+    EXPECT_EQ(111, item12.mValue.int_value);
+
+    const FieldValue& item13 = event1.getValues()[13];
+    EXPECT_EQ(0x2010784, item13.mField.getField());
+    EXPECT_EQ(Type::FLOAT, item13.mValue.getType());
+    EXPECT_EQ(2.2f, item13.mValue.float_value);
+
+    const FieldValue& item14 = event1.getValues()[14];
+    EXPECT_EQ(0x2018801, item14.mField.getField());
+    EXPECT_EQ(Type::INT, item14.mValue.getType());
+    EXPECT_EQ(222, item14.mValue.int_value);
+
+    const FieldValue& item15 = event1.getValues()[15];
+    EXPECT_EQ(0x2018884, item15.mField.getField());
+    EXPECT_EQ(Type::FLOAT, item15.mValue.getType());
+    EXPECT_EQ(1.1f, item15.mValue.float_value);
 }
 
 TEST(LogEventTest, TestLogParsing2) {
@@ -242,12 +269,16 @@
 }
 
 TEST(LogEventTest, TestKeyValuePairsEvent) {
-    std::map<int32_t, int64_t> int_map;
+    std::map<int32_t, int32_t> int_map;
+    std::map<int32_t, int64_t> long_map;
     std::map<int32_t, std::string> string_map;
     std::map<int32_t, float> float_map;
 
-    int_map[11] = 123L;
-    int_map[22] = 345L;
+    int_map[11] = 123;
+    int_map[22] = 345;
+
+    long_map[33] = 678L;
+    long_map[44] = 890L;
 
     string_map[1] = "test2";
     string_map[2] = "test1";
@@ -255,7 +286,7 @@
     float_map[111] = 2.2f;
     float_map[222] = 1.1f;
 
-    LogEvent event1(83, 2000, 2001, 10001, int_map, string_map, float_map);
+    LogEvent event1(83, 2000, 2001, 10001, int_map, long_map, string_map, float_map);
     event1.init();
 
     EXPECT_EQ(83, event1.GetTagId());
@@ -263,7 +294,7 @@
     EXPECT_EQ((int64_t)2001, event1.GetElapsedTimestampNs());
 
     const auto& items = event1.getValues();
-    EXPECT_EQ((size_t)13, items.size());
+    EXPECT_EQ((size_t)17, items.size());
 
     const FieldValue& item0 = event1.getValues()[0];
     EXPECT_EQ(0x00010000, item0.mField.getField());
@@ -277,8 +308,8 @@
 
     const FieldValue& item2 = event1.getValues()[2];
     EXPECT_EQ(0x2020182, item2.mField.getField());
-    EXPECT_EQ(Type::LONG, item2.mValue.getType());
-    EXPECT_EQ(123L, item2.mValue.long_value);
+    EXPECT_EQ(Type::INT, item2.mValue.getType());
+    EXPECT_EQ(123, item2.mValue.int_value);
 
     const FieldValue& item3 = event1.getValues()[3];
     EXPECT_EQ(0x2020201, item3.mField.getField());
@@ -287,48 +318,68 @@
 
     const FieldValue& item4 = event1.getValues()[4];
     EXPECT_EQ(0x2020282, item4.mField.getField());
-    EXPECT_EQ(Type::LONG, item4.mValue.getType());
-    EXPECT_EQ(345L, item4.mValue.long_value);
+    EXPECT_EQ(Type::INT, item4.mValue.getType());
+    EXPECT_EQ(345, item4.mValue.int_value);
 
     const FieldValue& item5 = event1.getValues()[5];
     EXPECT_EQ(0x2020301, item5.mField.getField());
     EXPECT_EQ(Type::INT, item5.mValue.getType());
-    EXPECT_EQ(1, item5.mValue.int_value);
+    EXPECT_EQ(33, item5.mValue.int_value);
 
     const FieldValue& item6 = event1.getValues()[6];
-    EXPECT_EQ(0x2020383, item6.mField.getField());
-    EXPECT_EQ(Type::STRING, item6.mValue.getType());
-    EXPECT_EQ("test2", item6.mValue.str_value);
+    EXPECT_EQ(0x2020382, item6.mField.getField());
+    EXPECT_EQ(Type::LONG, item6.mValue.getType());
+    EXPECT_EQ(678L, item6.mValue.long_value);
 
     const FieldValue& item7 = event1.getValues()[7];
     EXPECT_EQ(0x2020401, item7.mField.getField());
     EXPECT_EQ(Type::INT, item7.mValue.getType());
-    EXPECT_EQ(2, item7.mValue.int_value);
+    EXPECT_EQ(44, item7.mValue.int_value);
 
     const FieldValue& item8 = event1.getValues()[8];
-    EXPECT_EQ(0x2020483, item8.mField.getField());
-    EXPECT_EQ(Type::STRING, item8.mValue.getType());
-    EXPECT_EQ("test1", item8.mValue.str_value);
+    EXPECT_EQ(0x2020482, item8.mField.getField());
+    EXPECT_EQ(Type::LONG, item8.mValue.getType());
+    EXPECT_EQ(890L, item8.mValue.long_value);
 
     const FieldValue& item9 = event1.getValues()[9];
     EXPECT_EQ(0x2020501, item9.mField.getField());
     EXPECT_EQ(Type::INT, item9.mValue.getType());
-    EXPECT_EQ(111, item9.mValue.int_value);
+    EXPECT_EQ(1, item9.mValue.int_value);
 
     const FieldValue& item10 = event1.getValues()[10];
-    EXPECT_EQ(0x2020584, item10.mField.getField());
-    EXPECT_EQ(Type::FLOAT, item10.mValue.getType());
-    EXPECT_EQ(2.2f, item10.mValue.float_value);
+    EXPECT_EQ(0x2020583, item10.mField.getField());
+    EXPECT_EQ(Type::STRING, item10.mValue.getType());
+    EXPECT_EQ("test2", item10.mValue.str_value);
 
     const FieldValue& item11 = event1.getValues()[11];
-    EXPECT_EQ(0x2028601, item11.mField.getField());
+    EXPECT_EQ(0x2020601, item11.mField.getField());
     EXPECT_EQ(Type::INT, item11.mValue.getType());
-    EXPECT_EQ(222, item11.mValue.int_value);
+    EXPECT_EQ(2, item11.mValue.int_value);
 
     const FieldValue& item12 = event1.getValues()[12];
-    EXPECT_EQ(0x2028684, item12.mField.getField());
-    EXPECT_EQ(Type::FLOAT, item12.mValue.getType());
-    EXPECT_EQ(1.1f, item12.mValue.float_value);
+    EXPECT_EQ(0x2020683, item12.mField.getField());
+    EXPECT_EQ(Type::STRING, item12.mValue.getType());
+    EXPECT_EQ("test1", item12.mValue.str_value);
+
+    const FieldValue& item13 = event1.getValues()[13];
+    EXPECT_EQ(0x2020701, item13.mField.getField());
+    EXPECT_EQ(Type::INT, item13.mValue.getType());
+    EXPECT_EQ(111, item13.mValue.int_value);
+
+    const FieldValue& item14 = event1.getValues()[14];
+    EXPECT_EQ(0x2020784, item14.mField.getField());
+    EXPECT_EQ(Type::FLOAT, item14.mValue.getType());
+    EXPECT_EQ(2.2f, item14.mValue.float_value);
+
+    const FieldValue& item15 = event1.getValues()[15];
+    EXPECT_EQ(0x2028801, item15.mField.getField());
+    EXPECT_EQ(Type::INT, item15.mValue.getType());
+    EXPECT_EQ(222, item15.mValue.int_value);
+
+    const FieldValue& item16 = event1.getValues()[16];
+    EXPECT_EQ(0x2028884, item16.mField.getField());
+    EXPECT_EQ(Type::FLOAT, item16.mValue.getType());
+    EXPECT_EQ(1.1f, item16.mValue.float_value);
 }
 
 
@@ -337,4 +388,4 @@
 }  // namespace android
 #else
 GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif
\ No newline at end of file
+#endif
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 f038214..75bd40f 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
@@ -81,6 +81,34 @@
 
 }  // namespace
 
+/*
+ The following test has the following input.
+
+{ 10000000002 10000000002 (8)9999[I], [S], job0[S], 1[I],  }
+{ 10000000010 10000000010 (7)111[I], App1[S], 222[I], GMSCoreModule1[S], 222[I], GMSCoreModule2[S], ReadEmail[S], 1[I],  }
+{ 10000000011 10000000011 (29)1[I],  }
+{ 10000000040 10000000040 (29)2[I],  }
+{ 10000000050 10000000050 (7)111[I], App1[S], 222[I], GMSCoreModule1[S], 222[I], GMSCoreModule2[S], ReadEmail[S], 0[I],  }
+{ 10000000101 10000000101 (8)9999[I], [S], job0[S], 0[I],  }
+{ 10000000102 10000000102 (29)1[I],  }
+{ 10000000200 10000000200 (7)111[I], App1[S], 222[I], GMSCoreModule1[S], 222[I], GMSCoreModule2[S], ReadEmail[S], 1[I],  }
+{ 10000000201 10000000201 (8)9999[I], [S], job2[S], 1[I],  }
+{ 10000000400 10000000400 (7)111[I], App1[S], 222[I], GMSCoreModule1[S], 222[I], GMSCoreModule2[S], ReadDoc[S], 1[I],  }
+{ 10000000401 10000000401 (7)333[I], App2[S], 222[I], GMSCoreModule1[S], 555[I], GMSCoreModule2[S], ReadEmail[S], 1[I],  }
+{ 10000000450 10000000450 (29)2[I],  }
+{ 10000000500 10000000500 (8)9999[I], [S], job2[S], 0[I],  }
+{ 10000000600 10000000600 (8)8888[I], [S], job2[S], 1[I],  }
+{ 10000000650 10000000650 (29)1[I],  }
+{ 309999999999 309999999999 (7)111[I], App1[S], 222[I], GMSCoreModule1[S], 222[I], GMSCoreModule2[S], ReadDoc[S], 0[I],  }
+{ 310000000100 310000000100 (29)2[I],  }
+{ 310000000300 310000000300 (7)111[I], App1[S], 222[I], GMSCoreModule1[S], 222[I], GMSCoreModule2[S], ReadEmail[S], 0[I],  }
+{ 310000000600 310000000600 (8)8888[I], [S], job1[S], 1[I],  }
+{ 310000000640 310000000640 (29)1[I],  }
+{ 310000000650 310000000650 (29)2[I],  }
+{ 310000000700 310000000700 (7)333[I], App2[S], 222[I], GMSCoreModule1[S], 555[I], GMSCoreModule2[S], ReadEmail[S], 0[I],  }
+{ 310000000850 310000000850 (8)8888[I], [S], job2[S], 0[I],  }
+{ 310000000900 310000000900 (8)8888[I], [S], job1[S], 0[I],  }
+*/
 TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_AND_CombinationCondition) {
     for (const bool hashStringInReport : { true, false }) {
         for (bool isDimensionInConditionSubSetOfConditionTrackerDimension : { true, false }) {
@@ -250,7 +278,7 @@
                     EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
                     EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
                               bucketStartTimeNs + bucketSizeNs);
-                    EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 201 + bucketSizeNs - 600);
+                    EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 201 + bucketSizeNs - 650);
                     EXPECT_EQ(data.bucket_info(1).duration_nanos(), 100);
                     EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
                               bucketStartTimeNs + bucketSizeNs);
@@ -269,7 +297,7 @@
                             data.dimensions_in_condition(),
                             android::util::SYNC_STATE_CHANGED, 333, "App2");
                     EXPECT_EQ(data.bucket_info_size(), 2);
-                    EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 401 + bucketSizeNs - 600);
+                    EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 401 + bucketSizeNs - 650);
                     EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
                     EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
                               bucketStartTimeNs + bucketSizeNs);
@@ -331,7 +359,7 @@
                     EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
                               bucketStartTimeNs + bucketSizeNs);
                     EXPECT_EQ(data.bucket_info(0).duration_nanos(), 450 - 201);
-                    EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 600 + 100);
+                    EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 650 + 100);
                     EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
                               bucketStartTimeNs + bucketSizeNs);
                     EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
@@ -353,7 +381,7 @@
                     EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
                     EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(),
                               bucketStartTimeNs + bucketSizeNs);
-                    EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 600 + 110);
+                    EXPECT_EQ(data.bucket_info(1).duration_nanos(), bucketSizeNs - 650 + 110);
                     EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(),
                               bucketStartTimeNs + bucketSizeNs);
                     EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(),
diff --git a/cmds/statsd/tests/shell/ShellSubscriber_test.cpp b/cmds/statsd/tests/shell/ShellSubscriber_test.cpp
new file mode 100644
index 0000000..b380b03
--- /dev/null
+++ b/cmds/statsd/tests/shell/ShellSubscriber_test.cpp
@@ -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.
+
+#include <gtest/gtest.h>
+
+#include <unistd.h>
+#include "frameworks/base/cmds/statsd/src/atoms.pb.h"
+#include "frameworks/base/cmds/statsd/src/shell/shell_config.pb.h"
+#include "src/shell/ShellSubscriber.h"
+#include "tests/metrics/metrics_test_helper.h"
+
+#include <stdio.h>
+#include <vector>
+
+using namespace android::os::statsd;
+using android::sp;
+using std::vector;
+using testing::NaggyMock;
+
+#ifdef __ANDROID__
+
+class MyResultReceiver : public BnResultReceiver {
+public:
+    Mutex mMutex;
+    Condition mCondition;
+    bool mHaveResult = false;
+    int32_t mResult = 0;
+
+    virtual void send(int32_t resultCode) {
+        AutoMutex _l(mMutex);
+        mResult = resultCode;
+        mHaveResult = true;
+        mCondition.signal();
+    }
+
+    int32_t waitForResult() {
+        AutoMutex _l(mMutex);
+        mCondition.waitRelative(mMutex, 1000000000);
+        return mResult;
+    }
+};
+
+TEST(ShellSubscriberTest, testPushedSubscription) {
+    // set up 2 pipes for read/write config and data
+    int fds_config[2];
+    ASSERT_EQ(0, pipe(fds_config));
+
+    int fds_data[2];
+    ASSERT_EQ(0, pipe(fds_data));
+
+    // create a simple config to get screen events
+    ShellSubscription config;
+    config.add_pushed()->set_atom_id(29);
+
+    size_t bufferSize = config.ByteSize();
+
+    // write the config to pipe, first write size of the config
+    vector<uint8_t> size_buffer(sizeof(bufferSize));
+    std::memcpy(size_buffer.data(), &bufferSize, sizeof(bufferSize));
+    write(fds_config[1], &bufferSize, sizeof(bufferSize));
+    // then write config itself
+    vector<uint8_t> buffer(bufferSize);
+    config.SerializeToArray(&buffer[0], bufferSize);
+    write(fds_config[1], buffer.data(), bufferSize);
+    close(fds_config[1]);
+
+    // create a shell subscriber.
+    sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
+    sp<ShellSubscriber> shellClient = new ShellSubscriber(uidMap);
+    sp<MyResultReceiver> resultReceiver = new MyResultReceiver();
+
+    LogEvent event1(29, 1000);
+    event1.write(2);
+    event1.init();
+
+    // mimic a binder thread that a shell subscriber runs on. it would block.
+    std::thread reader([&resultReceiver, &fds_config, &fds_data, &shellClient] {
+        shellClient->startNewSubscription(fds_config[0], fds_data[1], resultReceiver);
+    });
+    reader.detach();
+
+    // let the shell subscriber to receive the config from pipe.
+    std::this_thread::sleep_for(100ms);
+
+    // send a log event that matches the config.
+    std::thread log_reader([&shellClient, &event1] { shellClient->onLogEvent(event1); });
+    log_reader.detach();
+
+    if (log_reader.joinable()) {
+        log_reader.join();
+    }
+
+    // wait for the data to be written.
+    std::this_thread::sleep_for(100ms);
+
+    // this is the expected screen event atom.
+    Atom atom;
+    atom.mutable_screen_state_changed()->set_state(
+            ::android::view::DisplayStateEnum::DISPLAY_STATE_ON);
+
+    int atom_size = atom.ByteSize();
+
+    // now read from the pipe. firstly read the atom size.
+    size_t dataSize = 0;
+    EXPECT_EQ((int)sizeof(dataSize), read(fds_data[0], &dataSize, sizeof(dataSize)));
+    EXPECT_EQ(atom_size, (int)dataSize);
+
+    // then read that much data which is the atom in proto binary format
+    vector<uint8_t> dataBuffer(dataSize);
+    EXPECT_EQ((int)dataSize, read(fds_data[0], dataBuffer.data(), dataSize));
+
+    // make sure the received bytes can be parsed to an atom
+    Atom receivedAtom;
+    EXPECT_TRUE(receivedAtom.ParseFromArray(dataBuffer.data(), dataSize) != 0);
+
+    // serialze the expected atom to bytes. and compare. to make sure they are the same.
+    vector<uint8_t> atomBuffer(atom_size);
+    atom.SerializeToArray(&atomBuffer[0], atom_size);
+    EXPECT_EQ(atomBuffer, dataBuffer);
+    close(fds_data[0]);
+}
+
+#else
+GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 0472461..ac16fd3 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -2076,27 +2076,20 @@
 Lcom/android/internal/telephony/ISub;->getDefaultSubId()I
 Lcom/android/internal/telephony/ISub;->setDefaultDataSubId(I)V
 Lcom/android/internal/telephony/ITelephony$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Lcom/android/internal/telephony/ITelephony$Stub$Proxy;->endCall()Z
-Lcom/android/internal/telephony/ITelephony$Stub$Proxy;->endCallForSubscriber(I)Z
 Lcom/android/internal/telephony/ITelephony$Stub$Proxy;->getDeviceId(Ljava/lang/String;)Ljava/lang/String;
 Lcom/android/internal/telephony/ITelephony$Stub$Proxy;->isRadioOn(Ljava/lang/String;)Z
 Lcom/android/internal/telephony/ITelephony$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Lcom/android/internal/telephony/ITelephony$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ITelephony;
 Lcom/android/internal/telephony/ITelephony$Stub;->DESCRIPTOR:Ljava/lang/String;
-Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_answerRingingCall:I
 Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_call:I
 Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_dial:I
-Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_endCall:I
 Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_getDeviceId:I
-Lcom/android/internal/telephony/ITelephony;->answerRingingCall()V
 Lcom/android/internal/telephony/ITelephony;->call(Ljava/lang/String;Ljava/lang/String;)V
 Lcom/android/internal/telephony/ITelephony;->dial(Ljava/lang/String;)V
 Lcom/android/internal/telephony/ITelephony;->disableDataConnectivity()Z
 Lcom/android/internal/telephony/ITelephony;->disableLocationUpdates()V
 Lcom/android/internal/telephony/ITelephony;->enableDataConnectivity()Z
 Lcom/android/internal/telephony/ITelephony;->enableLocationUpdates()V
-Lcom/android/internal/telephony/ITelephony;->endCall()Z
-Lcom/android/internal/telephony/ITelephony;->endCallForSubscriber(I)Z
 Lcom/android/internal/telephony/ITelephony;->getActivePhoneType()I
 Lcom/android/internal/telephony/ITelephony;->getCallState()I
 Lcom/android/internal/telephony/ITelephony;->getDataActivity()I
@@ -2108,12 +2101,8 @@
 Lcom/android/internal/telephony/ITelephony;->hasIccCard()Z
 Lcom/android/internal/telephony/ITelephony;->iccCloseLogicalChannel(II)Z
 Lcom/android/internal/telephony/ITelephony;->iccTransmitApduLogicalChannel(IIIIIIILjava/lang/String;)Ljava/lang/String;
-Lcom/android/internal/telephony/ITelephony;->isIdle(Ljava/lang/String;)Z
-Lcom/android/internal/telephony/ITelephony;->isIdleForSubscriber(ILjava/lang/String;)Z
 Lcom/android/internal/telephony/ITelephony;->isRadioOnForSubscriber(ILjava/lang/String;)Z
-Lcom/android/internal/telephony/ITelephony;->isRinging(Ljava/lang/String;)Z
 Lcom/android/internal/telephony/ITelephony;->setRadio(Z)Z
-Lcom/android/internal/telephony/ITelephony;->silenceRinger()V
 Lcom/android/internal/telephony/ITelephony;->supplyPin(Ljava/lang/String;)Z
 Lcom/android/internal/telephony/ITelephony;->toggleRadioOnOff()V
 Lcom/android/internal/telephony/ITelephony;->updateServiceLocation()V
diff --git a/config/preloaded-classes b/config/preloaded-classes
index d93befd..56ca98f 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -1022,6 +1022,7 @@
 android.graphics.-$$Lambda$ColorSpace$Rgb$bWzafC8vMHNuVmRuTUPEFUMlfuY
 android.graphics.-$$Lambda$ColorSpace$S2rlqJvkXGTpUF6mZhvkElds8JE
 android.graphics.BaseCanvas
+android.graphics.BaseRecordingCanvas
 android.graphics.Bitmap
 android.graphics.Bitmap$1
 android.graphics.Bitmap$2
@@ -3303,7 +3304,6 @@
 android.view.OrientationEventListener$SensorEventListenerImpl
 android.view.PointerIcon
 android.view.PointerIcon$1
-android.view.RecordingCanvas
 android.view.RenderNode
 android.view.RenderNode$NoImagePreloadHolder
 android.view.RenderNodeAnimator
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 2ee266d..482ef2d 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -394,7 +394,7 @@
  *         <td>The final call you receive before your
  *             activity is destroyed.  This can happen either because the
  *             activity is finishing (someone called {@link Activity#finish} on
- *             it, or because the system is temporarily destroying this
+ *             it), or because the system is temporarily destroying this
  *             instance of the activity to save space.  You can distinguish
  *             between these two scenarios with the {@link
  *             Activity#isFinishing} method.</td>
@@ -1588,11 +1588,13 @@
      * @param outState The bundle to save the state to.
      */
     final void performSaveInstanceState(@NonNull Bundle outState) {
+        getApplication().dispatchActivityPreSaveInstanceState(this, outState);
         onSaveInstanceState(outState);
         saveManagedDialogs(outState);
         mActivityTransitionState.saveState(outState);
         storeHasCurrentPermissionRequest(outState);
         if (DEBUG_LIFECYCLE) Slog.v(TAG, "onSaveInstanceState " + this + ": " + outState);
+        getApplication().dispatchActivityPostSaveInstanceState(this, outState);
     }
 
     /**
@@ -1606,11 +1608,13 @@
      */
     final void performSaveInstanceState(@NonNull Bundle outState,
             @NonNull PersistableBundle outPersistentState) {
+        getApplication().dispatchActivityPreSaveInstanceState(this, outState);
         onSaveInstanceState(outState, outPersistentState);
         saveManagedDialogs(outState);
         storeHasCurrentPermissionRequest(outState);
         if (DEBUG_LIFECYCLE) Slog.v(TAG, "onSaveInstanceState " + this + ": " + outState +
                 ", " + outPersistentState);
+        getApplication().dispatchActivityPostSaveInstanceState(this, outState);
     }
 
     /**
@@ -1981,7 +1985,7 @@
     /**
      * Perform any final cleanup before an activity is destroyed.  This can
      * happen either because the activity is finishing (someone called
-     * {@link #finish} on it, or because the system is temporarily destroying
+     * {@link #finish} on it), or because the system is temporarily destroying
      * this instance of the activity to save space.  You can distinguish
      * between these two scenarios with the {@link #isFinishing} method.
      *
@@ -7195,6 +7199,7 @@
 
     @UnsupportedAppUsage
     final void performCreate(Bundle icicle, PersistableBundle persistentState) {
+        getApplication().dispatchActivityPreCreated(this, icicle);
         mCanEnterPictureInPicture = true;
         restoreHasCurrentPermissionRequest(icicle);
         if (persistentState != null) {
@@ -7209,6 +7214,7 @@
                 com.android.internal.R.styleable.Window_windowNoDisplay, false);
         mFragments.dispatchActivityCreated();
         mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
+        getApplication().dispatchActivityPostCreated(this, icicle);
     }
 
     final void performNewIntent(@NonNull Intent intent) {
@@ -7217,6 +7223,7 @@
     }
 
     final void performStart(String reason) {
+        getApplication().dispatchActivityPreStarted(this);
         mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
         mFragments.noteStateNotSaved();
         mCalled = false;
@@ -7284,6 +7291,7 @@
         }
 
         mActivityTransitionState.enterReady(this);
+        getApplication().dispatchActivityPostStarted(this);
     }
 
     /**
@@ -7338,6 +7346,7 @@
     }
 
     final void performResume(boolean followedByPause, String reason) {
+        getApplication().dispatchActivityPreResumed(this);
         performRestart(true /* start */, reason);
 
         mFragments.execPendingActions();
@@ -7387,9 +7396,11 @@
                 "Activity " + mComponent.toShortString() +
                 " did not call through to super.onPostResume()");
         }
+        getApplication().dispatchActivityPostResumed(this);
     }
 
     final void performPause() {
+        getApplication().dispatchActivityPrePaused(this);
         mDoReportFullyDrawn = false;
         mFragments.dispatchPause();
         mCalled = false;
@@ -7402,6 +7413,7 @@
                     "Activity " + mComponent.toShortString() +
                     " did not call through to super.onPause()");
         }
+        getApplication().dispatchActivityPostPaused(this);
     }
 
     final void performUserLeaving() {
@@ -7417,6 +7429,7 @@
         mCanEnterPictureInPicture = false;
 
         if (!mStopped) {
+            getApplication().dispatchActivityPreStopped(this);
             if (mWindow != null) {
                 mWindow.closeAllPanels();
             }
@@ -7451,11 +7464,13 @@
             }
 
             mStopped = true;
+            getApplication().dispatchActivityPostStopped(this);
         }
         mResumed = false;
     }
 
     final void performDestroy() {
+        getApplication().dispatchActivityPreDestroyed(this);
         mDestroyed = true;
         mWindow.destroy();
         mFragments.dispatchDestroy();
@@ -7465,6 +7480,7 @@
         if (mVoiceInteractor != null) {
             mVoiceInteractor.detachActivity();
         }
+        getApplication().dispatchActivityPostDestroyed(this);
     }
 
     final void dispatchMultiWindowModeChanged(boolean isInMultiWindowMode,
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index be1f2db..294a3ec 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -19,11 +19,14 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.ComponentName;
+import android.content.IIntentReceiver;
 import android.content.IIntentSender;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.UserInfo;
+import android.os.Bundle;
 import android.os.IBinder;
+import android.os.TransactionTooLargeException;
 import android.view.RemoteAnimationAdapter;
 
 import java.util.ArrayList;
@@ -232,4 +235,14 @@
     public abstract void setBooted(boolean booted);
     public abstract boolean isBooted();
     public abstract void finishBooting();
+
+    public abstract void tempWhitelistForPendingIntent(int callerPid, int callerUid, int targetUid,
+            long duration, String tag);
+    public abstract int broadcastIntentInPackage(String packageName, int uid, Intent intent,
+            String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData,
+            Bundle resultExtras, String requiredPermission, Bundle bOptions, boolean serialized,
+            boolean sticky, int userId);
+    public abstract ComponentName startServiceInPackage(int uid, Intent service,
+            String resolvedType, boolean fgRequired, String callingPackage, int userId)
+            throws TransactionTooLargeException;
 }
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index fd92174..9c47e79 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -429,8 +429,8 @@
     /** @hide */
     @UnsupportedAppUsage
     public static final int OP_BLUETOOTH_SCAN = 77;
-    /** @hide Use the face authentication API. */
-    public static final int OP_USE_FACE = 78;
+    /** @hide Use the BiometricPrompt/BiometricManager APIs. */
+    public static final int OP_USE_BIOMETRIC = 78;
     /** @hide */
     @UnsupportedAppUsage
     public static final int _NUM_OP = 79;
@@ -678,8 +678,8 @@
     /** @hide */
     public static final String OPSTR_BLUETOOTH_SCAN = "android:bluetooth_scan";
 
-    /** @hide Use the face authentication API. */
-    public static final String OPSTR_USE_FACE = "android:use_face";
+    /** @hide Use the BiometricPrompt/BiometricManager APIs. */
+    public static final String OPSTR_USE_BIOMETRIC = "android:use_biometric";
 
     // Warning: If an permission is added here it also has to be added to
     // com.android.packageinstaller.permission.utils.EventLogger
@@ -818,7 +818,7 @@
             OP_MANAGE_IPSEC_TUNNELS,            // MANAGE_IPSEC_HANDOVERS
             OP_START_FOREGROUND,                // START_FOREGROUND
             OP_COARSE_LOCATION,                 // BLUETOOTH_SCAN
-            OP_USE_FACE,                        // FACE
+            OP_USE_BIOMETRIC,                   // BIOMETRIC
     };
 
     /**
@@ -903,7 +903,7 @@
             OPSTR_MANAGE_IPSEC_TUNNELS,
             OPSTR_START_FOREGROUND,
             OPSTR_BLUETOOTH_SCAN,
-            OPSTR_USE_FACE,
+            OPSTR_USE_BIOMETRIC,
     };
 
     /**
@@ -989,7 +989,7 @@
             "MANAGE_IPSEC_TUNNELS",
             "START_FOREGROUND",
             "BLUETOOTH_SCAN",
-            "USE_FACE",
+            "USE_BIOMETRIC",
     };
 
     /**
@@ -1163,7 +1163,7 @@
             null, // MANAGE_IPSEC_TUNNELS
             null, // START_FOREGROUND
             null, // maybe should be UserManager.DISALLOW_SHARE_LOCATION, //BLUETOOTH_SCAN
-            null, // USE_FACE
+            null, // USE_BIOMETRIC
     };
 
     /**
@@ -1249,7 +1249,7 @@
             false, // MANAGE_IPSEC_HANDOVERS
             false, // START_FOREGROUND
             true, // BLUETOOTH_SCAN
-            false, // USE_FACE
+            false, // USE_BIOMETRIC
     };
 
     /**
@@ -1334,7 +1334,7 @@
             AppOpsManager.MODE_ERRORED,  // MANAGE_IPSEC_TUNNELS
             AppOpsManager.MODE_ALLOWED,  // OP_START_FOREGROUND
             AppOpsManager.MODE_ALLOWED,  // OP_BLUETOOTH_SCAN
-            AppOpsManager.MODE_ALLOWED,  // USE_FACE
+            AppOpsManager.MODE_ALLOWED,  // USE_BIOMETRIC
     };
 
     /**
@@ -1423,7 +1423,7 @@
             false, // MANAGE_IPSEC_TUNNELS
             false, // START_FOREGROUND
             false, // BLUETOOTH_SCAN
-            false, // USE_FACE
+            false, // USE_BIOMETRIC
     };
 
     /**
diff --git a/core/java/android/app/Application.java b/core/java/android/app/Application.java
index 68b745d..e12942f 100644
--- a/core/java/android/app/Application.java
+++ b/core/java/android/app/Application.java
@@ -65,13 +65,144 @@
     public LoadedApk mLoadedApk;
 
     public interface ActivityLifecycleCallbacks {
+
+        /**
+         * Called as the first step of the Activity being created. This is always called before
+         * {@link Activity#onCreate}.
+         */
+        default void onActivityPreCreated(@NonNull Activity activity,
+                @Nullable Bundle savedInstanceState) {
+        }
+
+        /**
+         * Called when the Activity calls {@link Activity#onCreate super.onCreate()}.
+         */
         void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState);
+
+        /**
+         * Called as the last step of the Activity being created. This is always called after
+         * {@link Activity#onCreate}.
+         */
+        default void onActivityPostCreated(@NonNull Activity activity,
+                @Nullable Bundle savedInstanceState) {
+        }
+
+        /**
+         * Called as the first step of the Activity being started. This is always called before
+         * {@link Activity#onStart}.
+         */
+        default void onActivityPreStarted(@NonNull Activity activity) {
+        }
+
+        /**
+         * Called when the Activity calls {@link Activity#onStart super.onStart()}.
+         */
         void onActivityStarted(@NonNull Activity activity);
+
+        /**
+         * Called as the last step of the Activity being started. This is always called after
+         * {@link Activity#onStart}.
+         */
+        default void onActivityPostStarted(@NonNull Activity activity) {
+        }
+
+        /**
+         * Called as the first step of the Activity being resumed. This is always called before
+         * {@link Activity#onResume}.
+         */
+        default void onActivityPreResumed(@NonNull Activity activity) {
+        }
+
+        /**
+         * Called when the Activity calls {@link Activity#onResume super.onResume()}.
+         */
         void onActivityResumed(@NonNull Activity activity);
+
+        /**
+         * Called as the last step of the Activity being resumed. This is always called after
+         * {@link Activity#onResume} and {@link Activity#onPostResume}.
+         */
+        default void onActivityPostResumed(@NonNull Activity activity) {
+        }
+
+        /**
+         * Called as the first step of the Activity being paused. This is always called before
+         * {@link Activity#onPause}.
+         */
+        default void onActivityPrePaused(@NonNull Activity activity) {
+        }
+
+        /**
+         * Called when the Activity calls {@link Activity#onPause super.onPause()}.
+         */
         void onActivityPaused(@NonNull Activity activity);
+
+        /**
+         * Called as the last step of the Activity being paused. This is always called after
+         * {@link Activity#onPause}.
+         */
+        default void onActivityPostPaused(@NonNull Activity activity) {
+        }
+
+        /**
+         * Called as the first step of the Activity being stopped. This is always called before
+         * {@link Activity#onStop}.
+         */
+        default void onActivityPreStopped(@NonNull Activity activity) {
+        }
+
+        /**
+         * Called when the Activity calls {@link Activity#onStop super.onStop()}.
+         */
         void onActivityStopped(@NonNull Activity activity);
+
+        /**
+         * Called as the last step of the Activity being stopped. This is always called after
+         * {@link Activity#onStop}.
+         */
+        default void onActivityPostStopped(@NonNull Activity activity) {
+        }
+
+        /**
+         * Called as the first step of the Activity saving its instance state. This is always
+         * called before {@link Activity#onSaveInstanceState}.
+         */
+        default void onActivityPreSaveInstanceState(@NonNull Activity activity,
+                @NonNull Bundle outState) {
+        }
+
+        /**
+         * Called when the Activity calls
+         * {@link Activity#onSaveInstanceState super.onSaveInstanceState()}.
+         */
         void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState);
+
+        /**
+         * Called as the last step of the Activity saving its instance state. This is always
+         * called after{@link Activity#onSaveInstanceState}.
+         */
+        default void onActivityPostSaveInstanceState(@NonNull Activity activity,
+                @NonNull Bundle outState) {
+        }
+
+        /**
+         * Called as the first step of the Activity being destroyed. This is always called before
+         * {@link Activity#onDestroy}.
+         */
+        default void onActivityPreDestroyed(@NonNull Activity activity) {
+        }
+
+        /**
+         * Called when the Activity calls {@link Activity#onDestroy super.onDestroy()}.
+         */
         void onActivityDestroyed(@NonNull Activity activity);
+
+        /**
+         * Called as the last step of the Activity being destroyed. This is always called after
+         * {@link Activity#onDestroy}.
+         */
+        default void onActivityPostDestroyed(@NonNull Activity activity) {
+        }
     }
 
     /**
@@ -222,6 +353,18 @@
     }
 
     @UnsupportedAppUsage
+        /* package */ void dispatchActivityPreCreated(@NonNull Activity activity,
+            @Nullable Bundle savedInstanceState) {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = 0; i < callbacks.length; i++) {
+                ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPreCreated(activity,
+                        savedInstanceState);
+            }
+        }
+    }
+
+    @UnsupportedAppUsage
     /* package */ void dispatchActivityCreated(@NonNull Activity activity,
             @Nullable Bundle savedInstanceState) {
         Object[] callbacks = collectActivityLifecycleCallbacks();
@@ -234,6 +377,28 @@
     }
 
     @UnsupportedAppUsage
+        /* package */ void dispatchActivityPostCreated(@NonNull Activity activity,
+            @Nullable Bundle savedInstanceState) {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = 0; i < callbacks.length; i++) {
+                ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPostCreated(activity,
+                        savedInstanceState);
+            }
+        }
+    }
+
+    @UnsupportedAppUsage
+        /* package */ void dispatchActivityPreStarted(@NonNull Activity activity) {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = 0; i < callbacks.length; i++) {
+                ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPreStarted(activity);
+            }
+        }
+    }
+
+    @UnsupportedAppUsage
     /* package */ void dispatchActivityStarted(@NonNull Activity activity) {
         Object[] callbacks = collectActivityLifecycleCallbacks();
         if (callbacks != null) {
@@ -244,6 +409,26 @@
     }
 
     @UnsupportedAppUsage
+        /* package */ void dispatchActivityPostStarted(@NonNull Activity activity) {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = 0; i < callbacks.length; i++) {
+                ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPostStarted(activity);
+            }
+        }
+    }
+
+    @UnsupportedAppUsage
+        /* package */ void dispatchActivityPreResumed(@NonNull Activity activity) {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = 0; i < callbacks.length; i++) {
+                ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPreResumed(activity);
+            }
+        }
+    }
+
+    @UnsupportedAppUsage
     /* package */ void dispatchActivityResumed(@NonNull Activity activity) {
         Object[] callbacks = collectActivityLifecycleCallbacks();
         if (callbacks != null) {
@@ -254,6 +439,26 @@
     }
 
     @UnsupportedAppUsage
+        /* package */ void dispatchActivityPostResumed(@NonNull Activity activity) {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = 0; i < callbacks.length; i++) {
+                ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPostResumed(activity);
+            }
+        }
+    }
+
+    @UnsupportedAppUsage
+        /* package */ void dispatchActivityPrePaused(@NonNull Activity activity) {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = 0; i < callbacks.length; i++) {
+                ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPrePaused(activity);
+            }
+        }
+    }
+
+    @UnsupportedAppUsage
     /* package */ void dispatchActivityPaused(@NonNull Activity activity) {
         Object[] callbacks = collectActivityLifecycleCallbacks();
         if (callbacks != null) {
@@ -264,6 +469,26 @@
     }
 
     @UnsupportedAppUsage
+        /* package */ void dispatchActivityPostPaused(@NonNull Activity activity) {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = 0; i < callbacks.length; i++) {
+                ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPostPaused(activity);
+            }
+        }
+    }
+
+    @UnsupportedAppUsage
+        /* package */ void dispatchActivityPreStopped(@NonNull Activity activity) {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = 0; i < callbacks.length; i++) {
+                ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPreStopped(activity);
+            }
+        }
+    }
+
+    @UnsupportedAppUsage
     /* package */ void dispatchActivityStopped(@NonNull Activity activity) {
         Object[] callbacks = collectActivityLifecycleCallbacks();
         if (callbacks != null) {
@@ -274,6 +499,28 @@
     }
 
     @UnsupportedAppUsage
+        /* package */ void dispatchActivityPostStopped(@NonNull Activity activity) {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = 0; i < callbacks.length; i++) {
+                ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPostStopped(activity);
+            }
+        }
+    }
+
+    @UnsupportedAppUsage
+        /* package */ void dispatchActivityPreSaveInstanceState(@NonNull Activity activity,
+            @NonNull Bundle outState) {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = 0; i < callbacks.length; i++) {
+                ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPreSaveInstanceState(
+                        activity, outState);
+            }
+        }
+    }
+
+    @UnsupportedAppUsage
     /* package */ void dispatchActivitySaveInstanceState(@NonNull Activity activity,
             @NonNull Bundle outState) {
         Object[] callbacks = collectActivityLifecycleCallbacks();
@@ -286,6 +533,28 @@
     }
 
     @UnsupportedAppUsage
+        /* package */ void dispatchActivityPostSaveInstanceState(@NonNull Activity activity,
+            @NonNull Bundle outState) {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = 0; i < callbacks.length; i++) {
+                ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPostSaveInstanceState(
+                        activity, outState);
+            }
+        }
+    }
+
+    @UnsupportedAppUsage
+        /* package */ void dispatchActivityPreDestroyed(@NonNull Activity activity) {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = 0; i < callbacks.length; i++) {
+                ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPreDestroyed(activity);
+            }
+        }
+    }
+
+    @UnsupportedAppUsage
     /* package */ void dispatchActivityDestroyed(@NonNull Activity activity) {
         Object[] callbacks = collectActivityLifecycleCallbacks();
         if (callbacks != null) {
@@ -295,6 +564,16 @@
         }
     }
 
+    @UnsupportedAppUsage
+        /* package */ void dispatchActivityPostDestroyed(@NonNull Activity activity) {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = 0; i < callbacks.length; i++) {
+                ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPostDestroyed(activity);
+            }
+        }
+    }
+
     private Object[] collectComponentCallbacks() {
         Object[] callbacks = null;
         synchronized (mComponentCallbacks) {
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/events/StoppedDragingEvent.java b/core/java/android/app/ISmsAppService.aidl
similarity index 64%
rename from packages/SystemUI/src/com/android/systemui/stackdivider/events/StoppedDragingEvent.java
rename to core/java/android/app/ISmsAppService.aidl
index c50d6d6..1ac2ec6 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/events/StoppedDragingEvent.java
+++ b/core/java/android/app/ISmsAppService.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 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.
@@ -11,15 +11,13 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
  */
 
-package com.android.systemui.stackdivider.events;
-
-import com.android.systemui.recents.events.EventBus;
+package android.app;
 
 /**
- * Sent when the divider isn't draging anymore.
+ * @hide
  */
-public class StoppedDragingEvent extends EventBus.Event {
+interface ISmsAppService {
 }
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 3638bc4..81df447 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -4440,7 +4440,7 @@
         }
 
         private CharSequence processTextSpans(CharSequence text) {
-            if (hasForegroundColor()) {
+            if (hasForegroundColor() || mInNightMode) {
                 return ContrastColorUtil.clearColorSpans(text);
             }
             return text;
diff --git a/core/java/android/app/ProcessMemoryState.java b/core/java/android/app/ProcessMemoryState.java
index 39db16d..9bfdae0 100644
--- a/core/java/android/app/ProcessMemoryState.java
+++ b/core/java/android/app/ProcessMemoryState.java
@@ -23,19 +23,20 @@
  * The memory stats for a process.
  * {@hide}
  */
-public class ProcessMemoryState implements Parcelable {
-    public int uid;
-    public String processName;
-    public int oomScore;
-    public long pgfault;
-    public long pgmajfault;
-    public long rssInBytes;
-    public long cacheInBytes;
-    public long swapInBytes;
+public final class ProcessMemoryState implements Parcelable {
+    public final int uid;
+    public final String processName;
+    public final int oomScore;
+    public final long pgfault;
+    public final long pgmajfault;
+    public final long rssInBytes;
+    public final long cacheInBytes;
+    public final long swapInBytes;
+    public final long rssHighWatermarkInBytes;
 
     public ProcessMemoryState(int uid, String processName, int oomScore, long pgfault,
                               long pgmajfault, long rssInBytes, long cacheInBytes,
-                              long swapInBytes) {
+                              long swapInBytes, long rssHighWatermarkInBytes) {
         this.uid = uid;
         this.processName = processName;
         this.oomScore = oomScore;
@@ -44,6 +45,7 @@
         this.rssInBytes = rssInBytes;
         this.cacheInBytes = cacheInBytes;
         this.swapInBytes = swapInBytes;
+        this.rssHighWatermarkInBytes = rssHighWatermarkInBytes;
     }
 
     private ProcessMemoryState(Parcel in) {
@@ -55,6 +57,7 @@
         rssInBytes = in.readLong();
         cacheInBytes = in.readLong();
         swapInBytes = in.readLong();
+        rssHighWatermarkInBytes = in.readLong();
     }
 
     public static final Creator<ProcessMemoryState> CREATOR = new Creator<ProcessMemoryState>() {
@@ -84,5 +87,6 @@
         parcel.writeLong(rssInBytes);
         parcel.writeLong(cacheInBytes);
         parcel.writeLong(swapInBytes);
+        parcel.writeLong(rssHighWatermarkInBytes);
     }
 }
diff --git a/core/java/android/app/SmsAppService.java b/core/java/android/app/SmsAppService.java
new file mode 100644
index 0000000..3f2b025
--- /dev/null
+++ b/core/java/android/app/SmsAppService.java
@@ -0,0 +1,57 @@
+/*
+ * 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.app;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.IBinder;
+
+/**
+ * If the default SMS app has a service that extends this class, the system always tries to bind
+ * it so that the process is always running, which allows the app to have a persistent connection
+ * to the server.
+ *
+ * <p>The service must have {@link android.telephony.TelephonyManager#ACTION_SMS_APP_SERVICE}
+ * action in the intent handler, and be protected with
+ * {@link android.Manifest.permission#BIND_SMS_APP_SERVICE}. However the service does not have to
+ * be exported.
+ *
+ * <p>Apps can use
+ * {@link android.content.pm.PackageManager#setComponentEnabledSetting(ComponentName, int, int)}
+ * to disable/enable the service. Apps should use it to disable the service when it no longer needs
+ * to be running.
+ *
+ * <p>When the owner process crashes, the service will be re-bound automatically after a
+ * back-off.
+ *
+ * <p>Note the process may still be killed if the system is under heavy memory pressure, in which
+ * case the process will be re-started later.
+ */
+public class SmsAppService extends Service {
+    private final ISmsAppService mImpl;
+
+    public SmsAppService() {
+        mImpl = new ISmsAppServiceImpl();
+    }
+
+    @Override
+    public final IBinder onBind(Intent intent) {
+        return mImpl.asBinder();
+    }
+
+    private class ISmsAppServiceImpl extends ISmsAppService.Stub {
+    }
+}
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index 2718bfa..bf3d885 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -17,6 +17,7 @@
 package android.app;
 
 import android.annotation.IntDef;
+import android.annotation.Nullable;
 import android.annotation.SystemService;
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
@@ -208,10 +209,11 @@
     }
 
     /**
-     * Expand the settings panel and open a subPanel, pass null to just open the settings panel.
+     * Expand the settings panel and open a subPanel. If the subpanel is null or does not have a
+     * corresponding tile, the QS panel is simply expanded
      */
     @UnsupportedAppUsage
-    public void expandSettingsPanel(String subPanel) {
+    public void expandSettingsPanel(@Nullable String subPanel) {
         try {
             final IStatusBarService svc = getService();
             if (svc != null) {
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index a679166..0044005 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -134,6 +134,7 @@
 import android.os.Vibrator;
 import android.os.health.SystemHealthManager;
 import android.os.storage.StorageManager;
+import android.permission.PermissionManager;
 import android.print.IPrintManager;
 import android.print.PrintManager;
 import android.service.oemlock.IOemLockService;
@@ -380,7 +381,7 @@
                 new StaticServiceFetcher<InputMethodManager>() {
             @Override
             public InputMethodManager createService() {
-                return InputMethodManager.getInstance();
+                return InputMethodManager.getInstanceInternal();
             }});
 
         registerService(Context.TEXT_SERVICES_MANAGER_SERVICE, TextServicesManager.class,
@@ -1064,6 +1065,13 @@
                             throws ServiceNotFoundException {
                         return new TimeZoneDetector();
                     }});
+
+        registerService(Context.PERMISSION_SERVICE, PermissionManager.class,
+                new CachedServiceFetcher<PermissionManager>() {
+                    @Override
+                    public PermissionManager createService(ContextImpl ctx) {
+                        return new PermissionManager(ctx.getOuterContext());
+                    }});
     }
 
     /**
diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java
index e6fb5dc..096c7aa 100644
--- a/core/java/android/app/WindowConfiguration.java
+++ b/core/java/android/app/WindowConfiguration.java
@@ -28,9 +28,13 @@
 import android.graphics.Rect;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.proto.ProtoInputStream;
 import android.util.proto.ProtoOutputStream;
+import android.util.proto.WireTypeMismatchException;
 import android.view.DisplayInfo;
 
+import java.io.IOException;
+
 /**
  * Class that contains windowing configuration/state for other objects that contain windows directly
  * or indirectly. E.g. Activities, Task, Displays, ...
@@ -511,6 +515,38 @@
     }
 
     /**
+     * Read from a protocol buffer input stream.
+     * Protocol buffer message definition at {@link android.app.WindowConfigurationProto}
+     *
+     * @param proto   Stream to read the WindowConfiguration object from.
+     * @param fieldId Field Id of the WindowConfiguration as defined in the parent message
+     * @hide
+     */
+    public void readFromProto(ProtoInputStream proto, long fieldId)
+            throws IOException, WireTypeMismatchException {
+        final long token = proto.start(fieldId);
+        try {
+            while (proto.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+                switch (proto.getFieldNumber()) {
+                    case (int) APP_BOUNDS:
+                        mAppBounds = new Rect();
+                        mAppBounds.readFromProto(proto, APP_BOUNDS);
+                        break;
+                    case (int) WINDOWING_MODE:
+                        mWindowingMode = proto.readInt(WINDOWING_MODE);
+                        break;
+                    case (int) ACTIVITY_TYPE:
+                        mActivityType = proto.readInt(ACTIVITY_TYPE);
+                        break;
+                }
+            }
+        } finally {
+            // Let caller handle any exceptions
+            proto.end(token);
+        }
+    }
+
+    /**
      * Returns true if the activities associated with this window configuration display a shadow
      * around their border.
      * @hide
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index fc67c10..1839263 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -7404,6 +7404,10 @@
      * If any app targeting {@link android.os.Build.VERSION_CODES#O} or higher calls this method
      * with {@link android.provider.Settings.Secure#INSTALL_NON_MARKET_APPS},
      * an {@link UnsupportedOperationException} is thrown.
+     *
+     * Starting from Android Q, the device and profile owner can also call
+     * {@link UserManager#DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY} to restrict unknown sources for
+     * all users.
      * </strong>
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index 9f22ad1..308b39e 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -165,6 +165,12 @@
          */
         public static final int KEYGUARD_HIDDEN = 18;
 
+        /**
+         * Keep in sync with the greatest event type value.
+         * @hide
+         */
+        public static final int MAX_EVENT_TYPE = 18;
+
         /** @hide */
         public static final int FLAG_IS_PACKAGE_INSTANT_APP = 1 << 0;
 
@@ -176,6 +182,12 @@
         public @interface EventFlags {}
 
         /**
+         * Bitwise OR all valid flag constants to create this constant.
+         * @hide
+         */
+        public static final int VALID_FLAG_BITS = FLAG_IS_PACKAGE_INSTANT_APP;
+
+        /**
          * {@hide}
          */
         @UnsupportedAppUsage
diff --git a/core/java/android/bluetooth/BluetoothMapClient.java b/core/java/android/bluetooth/BluetoothMapClient.java
index 183be5f..559a59b 100644
--- a/core/java/android/bluetooth/BluetoothMapClient.java
+++ b/core/java/android/bluetooth/BluetoothMapClient.java
@@ -73,6 +73,8 @@
     /** Connection canceled before completion. */
     public static final int RESULT_CANCELED = 2;
 
+    private static final int UPLOADING_FEATURE_BITMASK = 0x08;
+
     private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
             new IBluetoothStateChangeCallback.Stub() {
                 public void onBluetoothStateChange(boolean up) {
@@ -395,6 +397,23 @@
         return false;
     }
 
+    /**
+     * Returns the "Uploading" feature bit value from the SDP record's
+     * MapSupportedFeatures field (see Bluetooth MAP 1.4 spec, page 114).
+     * @param device The Bluetooth device to get this value for.
+     * @return Returns true if the Uploading bit value in SDP record's
+     *         MapSupportedFeatures field is set. False is returned otherwise.
+     */
+    public boolean isUploadingSupported(BluetoothDevice device) {
+        try {
+            return (mService != null && isEnabled() && isValidDevice(device))
+                && ((mService.getSupportedFeatures(device) & UPLOADING_FEATURE_BITMASK) > 0);
+        } catch (RemoteException e) {
+            Log.e(TAG, e.getMessage());
+        }
+        return false;
+    }
+
     private final ServiceConnection mConnection = new ServiceConnection() {
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) Log.d(TAG, "Proxy object connected");
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index bd1e6a4..a64eead 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -51,6 +51,8 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileNotFoundException;
@@ -58,6 +60,7 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Objects;
 
 /**
  * Content providers are one of the primary building blocks of Android applications, providing
@@ -99,6 +102,7 @@
  * <p>For more information about using content providers, read the
  * <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
  * developer guide.</p>
+ * </div>
  */
 public abstract class ContentProvider implements ComponentCallbacks2 {
 
@@ -220,7 +224,7 @@
         @Override
         public Cursor query(String callingPkg, Uri uri, @Nullable String[] projection,
                 @Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal) {
-            validateIncomingUri(uri);
+            uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
             if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
                 // The caller has no access to the data, so return an empty cursor with
@@ -268,7 +272,7 @@
         @Override
         public String getType(Uri uri) {
             // getCallingPackage() isn't available in getType(), as the javadoc states.
-            validateIncomingUri(uri);
+            uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
             Trace.traceBegin(TRACE_TAG_DATABASE, "getType");
             try {
@@ -280,7 +284,7 @@
 
         @Override
         public Uri insert(String callingPkg, Uri uri, ContentValues initialValues) {
-            validateIncomingUri(uri);
+            uri = validateIncomingUri(uri);
             int userId = getUserIdFromUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
             if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
@@ -303,7 +307,7 @@
 
         @Override
         public int bulkInsert(String callingPkg, Uri uri, ContentValues[] initialValues) {
-            validateIncomingUri(uri);
+            uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
             if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
                 return 0;
@@ -327,11 +331,12 @@
             for (int i = 0; i < numOperations; i++) {
                 ContentProviderOperation operation = operations.get(i);
                 Uri uri = operation.getUri();
-                validateIncomingUri(uri);
                 userIds[i] = getUserIdFromUri(uri);
-                if (userIds[i] != UserHandle.USER_CURRENT) {
-                    // Removing the user id from the uri.
-                    operation = new ContentProviderOperation(operation, true);
+                uri = validateIncomingUri(uri);
+                uri = maybeGetUriWithoutUserId(uri);
+                // Rebuild operation if we changed the Uri above
+                if (!Objects.equals(operation.getUri(), uri)) {
+                    operation = new ContentProviderOperation(operation, uri);
                     operations.set(i, operation);
                 }
                 if (operation.isReadOperation()) {
@@ -368,7 +373,7 @@
 
         @Override
         public int delete(String callingPkg, Uri uri, String selection, String[] selectionArgs) {
-            validateIncomingUri(uri);
+            uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
             if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
                 return 0;
@@ -386,7 +391,7 @@
         @Override
         public int update(String callingPkg, Uri uri, ContentValues values, String selection,
                 String[] selectionArgs) {
-            validateIncomingUri(uri);
+            uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
             if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
                 return 0;
@@ -405,7 +410,7 @@
         public ParcelFileDescriptor openFile(
                 String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal,
                 IBinder callerToken) throws FileNotFoundException {
-            validateIncomingUri(uri);
+            uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
             enforceFilePermission(callingPkg, uri, mode, callerToken);
             Trace.traceBegin(TRACE_TAG_DATABASE, "openFile");
@@ -423,7 +428,7 @@
         public AssetFileDescriptor openAssetFile(
                 String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal)
                 throws FileNotFoundException {
-            validateIncomingUri(uri);
+            uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
             enforceFilePermission(callingPkg, uri, mode, null);
             Trace.traceBegin(TRACE_TAG_DATABASE, "openAssetFile");
@@ -454,7 +459,7 @@
         @Override
         public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
             // getCallingPackage() isn't available in getType(), as the javadoc states.
-            validateIncomingUri(uri);
+            uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
             Trace.traceBegin(TRACE_TAG_DATABASE, "getStreamTypes");
             try {
@@ -468,7 +473,7 @@
         public AssetFileDescriptor openTypedAssetFile(String callingPkg, Uri uri, String mimeType,
                 Bundle opts, ICancellationSignal cancellationSignal) throws FileNotFoundException {
             Bundle.setDefusable(opts, true);
-            validateIncomingUri(uri);
+            uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
             enforceFilePermission(callingPkg, uri, "r", null);
             Trace.traceBegin(TRACE_TAG_DATABASE, "openTypedAssetFile");
@@ -489,7 +494,7 @@
 
         @Override
         public Uri canonicalize(String callingPkg, Uri uri) {
-            validateIncomingUri(uri);
+            uri = validateIncomingUri(uri);
             int userId = getUserIdFromUri(uri);
             uri = getUriWithoutUserId(uri);
             if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
@@ -507,7 +512,7 @@
 
         @Override
         public Uri uncanonicalize(String callingPkg, Uri uri) {
-            validateIncomingUri(uri);
+            uri = validateIncomingUri(uri);
             int userId = getUserIdFromUri(uri);
             uri = getUriWithoutUserId(uri);
             if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
@@ -526,7 +531,7 @@
         @Override
         public boolean refresh(String callingPkg, Uri uri, Bundle args,
                 ICancellationSignal cancellationSignal) throws RemoteException {
-            validateIncomingUri(uri);
+            uri = validateIncomingUri(uri);
             uri = getUriWithoutUserId(uri);
             if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
                 return false;
@@ -1965,7 +1970,7 @@
          */
         if (mContext == null) {
             mContext = context;
-            if (context != null) {
+            if (context != null && mTransport != null) {
                 mTransport.mAppOpsManager = (AppOpsManager) context.getSystemService(
                         Context.APP_OPS_SERVICE);
             }
@@ -2074,7 +2079,8 @@
     }
 
     /** @hide */
-    private void validateIncomingUri(Uri uri) throws SecurityException {
+    @VisibleForTesting
+    public Uri validateIncomingUri(Uri uri) throws SecurityException {
         String auth = uri.getAuthority();
         if (!mSingleUser) {
             int userId = getUserIdFromAuthority(auth, UserHandle.USER_CURRENT);
@@ -2093,6 +2099,15 @@
             }
             throw new SecurityException(message);
         }
+
+        // Normalize the path by removing any empty path segments, which can be
+        // a source of security issues.
+        final String encodedPath = uri.getEncodedPath();
+        if (encodedPath != null && encodedPath.indexOf("//") != -1) {
+            return uri.buildUpon().encodedPath(encodedPath.replaceAll("//+", "/")).build();
+        } else {
+            return uri;
+        }
     }
 
     /** @hide */
diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java
index e3d9b19..7dc4577 100644
--- a/core/java/android/content/ContentProviderOperation.java
+++ b/core/java/android/content/ContentProviderOperation.java
@@ -101,13 +101,9 @@
     }
 
     /** @hide */
-    public ContentProviderOperation(ContentProviderOperation cpo, boolean removeUserIdFromUri) {
+    public ContentProviderOperation(ContentProviderOperation cpo, Uri withUri) {
         mType = cpo.mType;
-        if (removeUserIdFromUri) {
-            mUri = ContentProvider.getUriWithoutUserId(cpo.mUri);
-        } else {
-            mUri = cpo.mUri;
-        }
+        mUri = withUri;
         mValues = cpo.mValues;
         mSelection = cpo.mSelection;
         mSelectionArgs = cpo.mSelectionArgs;
@@ -117,14 +113,6 @@
         mYieldAllowed = cpo.mYieldAllowed;
     }
 
-    /** @hide */
-    public ContentProviderOperation getWithoutUserIdInUri() {
-        if (ContentProvider.uriHasUserId(mUri)) {
-            return new ContentProviderOperation(this, true);
-        }
-        return this;
-    }
-
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(mType);
         Uri.writeToParcel(dest, mUri);
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 981be83..d711574 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3088,6 +3088,7 @@
             //@hide: SYSTEM_UPDATE_SERVICE,
             //@hide: TIME_DETECTOR_SERVICE,
             //@hide: TIME_ZONE_DETECTOR_SERVICE,
+            PERMISSION_SERVICE,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ServiceName {}
@@ -3860,6 +3861,14 @@
      */
     public static final String SOUND_TRIGGER_SERVICE = "soundtrigger";
 
+    /**
+     * Official published name of the (internal) permission service.
+     *
+     * @see #getSystemService(String)
+     * @hide
+     */
+    @SystemApi
+    public static final String PERMISSION_SERVICE = "permission";
 
     /**
      * Use with {@link #getSystemService(String)} to retrieve an
@@ -4302,6 +4311,12 @@
     public static final String TIME_ZONE_DETECTOR_SERVICE = "time_zone_detector";
 
     /**
+     * Binder service name for {@link AppBindingService}.
+     * @hide
+     */
+    public static final String APP_BINDING_SERVICE = "app_binding";
+
+    /**
      * 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/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index a15711f5..3032d16 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1170,6 +1170,14 @@
     public static final int INSTALL_FAILED_SANDBOX_VERSION_DOWNGRADE = -27;
 
     /**
+     * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+     * if the new package requires at least one split and it was not provided.
+     *
+     * @hide
+     */
+    public static final int INSTALL_FAILED_MISSING_SPLIT = -28;
+
+    /**
      * Installation parse return code: this is passed in the
      * {@link PackageInstaller#EXTRA_LEGACY_STATUS} if the parser was given a path that is not a
      * file, or does not end with the expected '.apk' extension.
@@ -5927,8 +5935,8 @@
             case INSTALL_FAILED_DUPLICATE_PERMISSION: return "INSTALL_FAILED_DUPLICATE_PERMISSION";
             case INSTALL_FAILED_NO_MATCHING_ABIS: return "INSTALL_FAILED_NO_MATCHING_ABIS";
             case INSTALL_FAILED_ABORTED: return "INSTALL_FAILED_ABORTED";
-            case INSTALL_FAILED_BAD_DEX_METADATA:
-                return "INSTALL_FAILED_BAD_DEX_METADATA";
+            case INSTALL_FAILED_BAD_DEX_METADATA: return "INSTALL_FAILED_BAD_DEX_METADATA";
+            case INSTALL_FAILED_MISSING_SPLIT: return "INSTALL_FAILED_MISSING_SPLIT";
             default: return Integer.toString(status);
         }
     }
@@ -5979,6 +5987,7 @@
             case INSTALL_FAILED_DUPLICATE_PERMISSION: return PackageInstaller.STATUS_FAILURE_CONFLICT;
             case INSTALL_FAILED_NO_MATCHING_ABIS: return PackageInstaller.STATUS_FAILURE_INCOMPATIBLE;
             case INSTALL_FAILED_ABORTED: return PackageInstaller.STATUS_FAILURE_ABORTED;
+            case INSTALL_FAILED_MISSING_SPLIT: return PackageInstaller.STATUS_FAILURE_INCOMPATIBLE;
             default: return PackageInstaller.STATUS_FAILURE;
         }
     }
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 03a3d1f..f5431ca 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -40,7 +40,6 @@
 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
 
-import android.Manifest;
 import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
@@ -73,6 +72,7 @@
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.storage.StorageManager;
+import android.permission.PermissionManager;
 import android.system.ErrnoException;
 import android.system.OsConstants;
 import android.system.StructStat;
@@ -258,19 +258,6 @@
         }
     }
 
-    /** @hide */
-    public static class SplitPermissionInfo {
-        public final String rootPerm;
-        public final String[] newPerms;
-        public final int targetSdk;
-
-        public SplitPermissionInfo(String rootPerm, String[] newPerms, int targetSdk) {
-            this.rootPerm = rootPerm;
-            this.newPerms = newPerms;
-            this.targetSdk = targetSdk;
-        }
-    }
-
     /**
      * List of new permissions that have been added since 1.0.
      * NOTE: These must be declared in SDK version order, with permissions
@@ -290,34 +277,6 @@
     };
 
     /**
-     * List of permissions that have been split into more granular or dependent
-     * permissions.
-     * @hide
-     */
-    public static final PackageParser.SplitPermissionInfo SPLIT_PERMISSIONS[] =
-        new PackageParser.SplitPermissionInfo[] {
-            // READ_EXTERNAL_STORAGE is always required when an app requests
-            // WRITE_EXTERNAL_STORAGE, because we can't have an app that has
-            // write access without read access.  The hack here with the target
-            // target SDK version ensures that this grant is always done.
-            new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
-                    new String[] { android.Manifest.permission.READ_EXTERNAL_STORAGE },
-                    android.os.Build.VERSION_CODES.CUR_DEVELOPMENT+1),
-            new PackageParser.SplitPermissionInfo(android.Manifest.permission.READ_CONTACTS,
-                    new String[] { android.Manifest.permission.READ_CALL_LOG },
-                    android.os.Build.VERSION_CODES.JELLY_BEAN),
-            new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_CONTACTS,
-                    new String[] { android.Manifest.permission.WRITE_CALL_LOG },
-                    android.os.Build.VERSION_CODES.JELLY_BEAN),
-            new PackageParser.SplitPermissionInfo(Manifest.permission.ACCESS_FINE_LOCATION,
-                    new String[] { android.Manifest.permission.ACCESS_BACKGROUND_LOCATION },
-                    android.os.Build.VERSION_CODES.P0),
-            new PackageParser.SplitPermissionInfo(Manifest.permission.ACCESS_COARSE_LOCATION,
-                    new String[] { android.Manifest.permission.ACCESS_BACKGROUND_LOCATION },
-                    android.os.Build.VERSION_CODES.P0),
-    };
-
-    /**
      * @deprecated callers should move to explicitly passing around source path.
      */
     @Deprecated
@@ -493,10 +452,12 @@
         public final boolean use32bitAbi;
         public final boolean extractNativeLibs;
         public final boolean isolatedSplits;
+        public final boolean isSplitRequired;
 
         public ApkLite(String codePath, String packageName, String splitName,
                 boolean isFeatureSplit,
-                String configForSplit, String usesSplitName, int versionCode, int versionCodeMajor,
+                String configForSplit, String usesSplitName, boolean isSplitRequired,
+                int versionCode, int versionCodeMajor,
                 int revisionCode, int installLocation, List<VerifierInfo> verifiers,
                 SigningDetails signingDetails, boolean coreApp,
                 boolean debuggable, boolean multiArch, boolean use32bitAbi,
@@ -519,6 +480,7 @@
             this.use32bitAbi = use32bitAbi;
             this.extractNativeLibs = extractNativeLibs;
             this.isolatedSplits = isolatedSplits;
+            this.isSplitRequired = isSplitRequired;
         }
 
         public long getLongVersionCode() {
@@ -1736,6 +1698,7 @@
         boolean extractNativeLibs = true;
         boolean isolatedSplits = false;
         boolean isFeatureSplit = false;
+        boolean isSplitRequired = false;
         String configForSplit = null;
         String usesSplitName = null;
 
@@ -1758,6 +1721,8 @@
                 configForSplit = attrs.getAttributeValue(i);
             } else if (attr.equals("isFeatureSplit")) {
                 isFeatureSplit = attrs.getAttributeBooleanValue(i, false);
+            } else if (attr.equals("isSplitRequired")) {
+                isSplitRequired = attrs.getAttributeBooleanValue(i, false);
             }
         }
 
@@ -1813,8 +1778,8 @@
         }
 
         return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit,
-                configForSplit, usesSplitName, versionCode, versionCodeMajor, revisionCode,
-                installLocation, verifiers, signingDetails, coreApp, debuggable,
+                configForSplit, usesSplitName, isSplitRequired, versionCode, versionCodeMajor,
+                revisionCode, installLocation, verifiers, signingDetails, coreApp, debuggable,
                 multiArch, use32bitAbi, extractNativeLibs, isolatedSplits);
     }
 
@@ -2474,16 +2439,18 @@
             Slog.i(TAG, implicitPerms.toString());
         }
 
-        final int NS = PackageParser.SPLIT_PERMISSIONS.length;
+
+        final int NS = PermissionManager.SPLIT_PERMISSIONS.length;
         for (int is=0; is<NS; is++) {
-            final PackageParser.SplitPermissionInfo spi
-                    = PackageParser.SPLIT_PERMISSIONS[is];
-            if (pkg.applicationInfo.targetSdkVersion >= spi.targetSdk
-                    || !pkg.requestedPermissions.contains(spi.rootPerm)) {
+            final PermissionManager.SplitPermissionInfo spi =
+                    PermissionManager.SPLIT_PERMISSIONS[is];
+            if (pkg.applicationInfo.targetSdkVersion >= spi.getTargetSdk()
+                    || !pkg.requestedPermissions.contains(spi.getRootPermission())) {
                 continue;
             }
-            for (int in=0; in<spi.newPerms.length; in++) {
-                final String perm = spi.newPerms[in];
+            final String[] newPerms = spi.getNewPermissions();
+            for (int in = 0; in < newPerms.length; in++) {
+                final String perm = newPerms[in];
                 if (!pkg.requestedPermissions.contains(perm)) {
                     pkg.requestedPermissions.add(perm);
                 }
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 121b432..799f8e5 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -46,6 +46,7 @@
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.app.WindowConfiguration;
+import android.content.LocaleProto;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ActivityInfo.Config;
 import android.os.Build;
@@ -54,7 +55,9 @@
 import android.os.Parcelable;
 import android.text.TextUtils;
 import android.util.DisplayMetrics;
+import android.util.proto.ProtoInputStream;
 import android.util.proto.ProtoOutputStream;
+import android.util.proto.WireTypeMismatchException;
 import android.view.View;
 
 import com.android.internal.util.XmlUtils;
@@ -67,6 +70,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+import java.util.List;
 import java.util.Locale;
 
 /**
@@ -1086,12 +1090,14 @@
     /**
      * Write to a protocol buffer output stream.
      * Protocol buffer message definition at {@link android.content.ConfigurationProto}
+     * Has the option to ignore fields that don't need to be persisted to disk.
      *
      * @param protoOutputStream Stream to write the Configuration object to.
      * @param fieldId           Field Id of the Configuration as defined in the parent message
+     * @param persisted         Note if this proto will be persisted to disk
      * @hide
      */
-    public void writeToProto(ProtoOutputStream protoOutputStream, long fieldId) {
+    public void writeToProto(ProtoOutputStream protoOutputStream, long fieldId, boolean persisted) {
         final long token = protoOutputStream.start(fieldId);
         protoOutputStream.write(FONT_SCALE, fontScale);
         protoOutputStream.write(MCC, mcc);
@@ -1113,13 +1119,137 @@
         protoOutputStream.write(SCREEN_HEIGHT_DP, screenHeightDp);
         protoOutputStream.write(SMALLEST_SCREEN_WIDTH_DP, smallestScreenWidthDp);
         protoOutputStream.write(DENSITY_DPI, densityDpi);
-        if (windowConfiguration != null) {
+        // For persistence, we do not care about window configuration
+        if (!persisted && windowConfiguration != null) {
             windowConfiguration.writeToProto(protoOutputStream, WINDOW_CONFIGURATION);
         }
         protoOutputStream.end(token);
     }
 
     /**
+     * Write to a protocol buffer output stream.
+     * Protocol buffer message definition at {@link android.content.ConfigurationProto}
+     *
+     * @param protoOutputStream Stream to write the Configuration object to.
+     * @param fieldId           Field Id of the Configuration as defined in the parent message
+     * @hide
+     */
+    public void writeToProto(ProtoOutputStream protoOutputStream, long fieldId) {
+        writeToProto(protoOutputStream, fieldId, false);
+    }
+
+    /**
+     * Read from a protocol buffer output stream.
+     * Protocol buffer message definition at {@link android.content.ConfigurationProto}
+     *
+     * @param protoInputStream Stream to read the Configuration object from.
+     * @param fieldId          Field Id of the Configuration as defined in the parent message
+     * @hide
+     */
+    public void readFromProto(ProtoInputStream protoInputStream, long fieldId) throws IOException {
+        final long token = protoInputStream.start(fieldId);
+        final List<Locale> list = new ArrayList();
+        try {
+            while (protoInputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+                switch (protoInputStream.getFieldNumber()) {
+                    case (int) FONT_SCALE:
+                        fontScale = protoInputStream.readFloat(FONT_SCALE);
+                        break;
+                    case (int) MCC:
+                        mcc = protoInputStream.readInt(MCC);
+                        break;
+                    case (int) MNC:
+                        mnc = protoInputStream.readInt(MNC);
+                        break;
+                    case (int) LOCALES:
+                        // Parse the Locale here to handle all the repeated Locales
+                        // The LocaleList will be created when the message is completed
+                        final long localeToken = protoInputStream.start(LOCALES);
+                        String language = "";
+                        String country = "";
+                        String variant = "";
+                        try {
+                            while (protoInputStream.nextField()
+                                    != ProtoInputStream.NO_MORE_FIELDS) {
+                                switch (protoInputStream.getFieldNumber()) {
+                                    case (int) LocaleProto.LANGUAGE:
+                                        language = protoInputStream.readString(
+                                                LocaleProto.LANGUAGE);
+                                        break;
+                                    case (int) LocaleProto.COUNTRY:
+                                        country = protoInputStream.readString(LocaleProto.COUNTRY);
+                                        break;
+                                    case (int) LocaleProto.VARIANT:
+                                        variant = protoInputStream.readString(LocaleProto.VARIANT);
+                                        break;
+                                }
+                            }
+                        } catch (WireTypeMismatchException wtme) {
+                            // rethrow for caller deal with
+                            throw wtme;
+                        } finally {
+                            protoInputStream.end(localeToken);
+                            list.add(new Locale(language, country, variant));
+                        }
+                        break;
+                    case (int) SCREEN_LAYOUT:
+                        screenLayout = protoInputStream.readInt(SCREEN_LAYOUT);
+                        break;
+                    case (int) COLOR_MODE:
+                        colorMode = protoInputStream.readInt(COLOR_MODE);
+                        break;
+                    case (int) TOUCHSCREEN:
+                        touchscreen = protoInputStream.readInt(TOUCHSCREEN);
+                        break;
+                    case (int) KEYBOARD:
+                        keyboard = protoInputStream.readInt(KEYBOARD);
+                        break;
+                    case (int) KEYBOARD_HIDDEN:
+                        keyboardHidden = protoInputStream.readInt(KEYBOARD_HIDDEN);
+                        break;
+                    case (int) HARD_KEYBOARD_HIDDEN:
+                        hardKeyboardHidden = protoInputStream.readInt(HARD_KEYBOARD_HIDDEN);
+                        break;
+                    case (int) NAVIGATION:
+                        navigation = protoInputStream.readInt(NAVIGATION);
+                        break;
+                    case (int) NAVIGATION_HIDDEN:
+                        navigationHidden = protoInputStream.readInt(NAVIGATION_HIDDEN);
+                        break;
+                    case (int) ORIENTATION:
+                        orientation = protoInputStream.readInt(ORIENTATION);
+                        break;
+                    case (int) UI_MODE:
+                        uiMode = protoInputStream.readInt(UI_MODE);
+                        break;
+                    case (int) SCREEN_WIDTH_DP:
+                        screenWidthDp = protoInputStream.readInt(SCREEN_WIDTH_DP);
+                        break;
+                    case (int) SCREEN_HEIGHT_DP:
+                        screenHeightDp = protoInputStream.readInt(SCREEN_HEIGHT_DP);
+                        break;
+                    case (int) SMALLEST_SCREEN_WIDTH_DP:
+                        smallestScreenWidthDp = protoInputStream.readInt(SMALLEST_SCREEN_WIDTH_DP);
+                        break;
+                    case (int) DENSITY_DPI:
+                        densityDpi = protoInputStream.readInt(DENSITY_DPI);
+                        break;
+                    case (int) WINDOW_CONFIGURATION:
+                        windowConfiguration.readFromProto(protoInputStream, WINDOW_CONFIGURATION);
+                        break;
+                }
+            }
+        } finally {
+            // Let caller handle any exceptions
+            if (list.size() > 0) {
+                //Create the LocaleList from the collected Locales
+                setLocales(new LocaleList(list.toArray(new Locale[list.size()])));
+            }
+            protoInputStream.end(token);
+        }
+    }
+
+    /**
      * Write full {@link android.content.ResourcesConfigurationProto} to protocol buffer output
      * stream.
      *
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 01557c5..eb5c720 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -649,7 +649,7 @@
      * successful so far. Do not call setTransactionSuccessful before calling this. When this
      * returns a new transaction will have been created but not marked as successful.
      * @return true if the transaction was yielded
-     * @deprecated if the db is locked more than once (becuase of nested transactions) then the lock
+     * @deprecated if the db is locked more than once (because of nested transactions) then the lock
      *   will not be yielded. Use yieldIfContendedSafely instead.
      */
     @Deprecated
diff --git a/core/java/android/hardware/GeomagneticField.java b/core/java/android/hardware/GeomagneticField.java
index 94f2ac0..0d7b695 100644
--- a/core/java/android/hardware/GeomagneticField.java
+++ b/core/java/android/hardware/GeomagneticField.java
@@ -31,7 +31,7 @@
  * Android may use a newer version of the model.
  */
 public class GeomagneticField {
-    // The magnetic field at a given point, in nonoteslas in geodetic
+    // The magnetic field at a given point, in nanoteslas in geodetic
     // coordinates.
     private float mX;
     private float mY;
@@ -278,7 +278,7 @@
     }
 
     /**
-     * @return  Horizontal component of the field strength in nonoteslas.
+     * @return  Horizontal component of the field strength in nanoteslas.
      */
     public float getHorizontalStrength() {
         return (float) Math.hypot(mX, mY);
diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java
index 36e978b..eea5f9b 100644
--- a/core/java/android/hardware/biometrics/BiometricManager.java
+++ b/core/java/android/hardware/biometrics/BiometricManager.java
@@ -48,7 +48,7 @@
     @RequiresPermission(USE_BIOMETRIC)
     public boolean hasEnrolledBiometrics() {
         try {
-            return mService.hasEnrolledBiometrics();
+            return mService.hasEnrolledBiometrics(mContext.getOpPackageName());
         } catch (RemoteException e) {
             return false;
         }
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index 92a814c..83998cc 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -348,7 +348,6 @@
          * @hide
          */
         public AuthenticationResult(CryptoObject crypto) {
-            // For compatibility, this extends from common base class as FingerprintManager does.
             // Identifier and userId is not used for BiometricPrompt.
             super(crypto, null /* identifier */, 0 /* userId */);
         }
@@ -410,8 +409,8 @@
     }
 
     /**
-     * This call warms up the fingerprint hardware, displays a system-provided dialog, and starts
-     * scanning for a fingerprint. It terminates when {@link
+     * 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
      * AuthenticationCallback#onAuthenticationSucceeded( AuthenticationResult)}, or when the user
      * dismisses the system-provided dialog, at which point the crypto object becomes invalid. This
@@ -453,8 +452,8 @@
     }
 
     /**
-     * This call warms up the fingerprint hardware, displays a system-provided dialog, and starts
-     * scanning for a fingerprint. It terminates when {@link
+     * 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
      * AuthenticationCallback#onAuthenticationSucceeded( AuthenticationResult)} is called, or when
      * the user dismisses the system-provided dialog.  This operation can be canceled by using the
diff --git a/core/java/android/hardware/biometrics/IBiometricService.aidl b/core/java/android/hardware/biometrics/IBiometricService.aidl
index bfd6941..fd9d572 100644
--- a/core/java/android/hardware/biometrics/IBiometricService.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricService.aidl
@@ -38,5 +38,5 @@
     void cancelAuthentication(IBinder token, String opPackageName);
 
     // Returns true if the user has at least one enrolled biometric.
-    boolean hasEnrolledBiometrics();
+    boolean hasEnrolledBiometrics(String opPackageName);
 }
\ No newline at end of file
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index d967fba..7810e6c 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -1889,7 +1889,7 @@
             final long ident = Binder.clearCallingIdentity();
             try {
                 CameraDeviceImpl.this.mDeviceExecutor.execute(obtainRunnable(
-                            CameraDeviceCallbacks::notifyError, this, code));
+                            CameraDeviceCallbacks::notifyError, this, code).recycleOnUse());
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index 66613ea..873a24a 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -244,17 +244,17 @@
     }
 
     /**
-     * Requests a pre-enrollment auth token to tie enrollment to the confirmation of
+     * Requests an auth token to tie sensitive operations to the confirmation of
      * existing device credentials (e.g. pin/pattern/password).
      *
      * @hide
      */
     @RequiresPermission(MANAGE_BIOMETRIC)
-    public long preEnroll() {
+    public long generateChallenge() {
         long result = 0;
         if (mService != null) {
             try {
-                result = mService.preEnroll(mToken);
+                result = mService.generateChallenge(mToken);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -263,16 +263,46 @@
     }
 
     /**
-     * Finishes enrollment and cancels the current auth token.
+     * Invalidates the current auth token.
      *
      * @hide
      */
     @RequiresPermission(MANAGE_BIOMETRIC)
-    public int postEnroll() {
+    public int revokeChallenge() {
         int result = 0;
         if (mService != null) {
             try {
-                result = mService.postEnroll(mToken);
+                result = mService.revokeChallenge(mToken);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+        return result;
+    }
+
+    /**
+     * @hide
+     */
+    @RequiresPermission(MANAGE_BIOMETRIC)
+    public void setRequireAttention(boolean requireAttention, byte[] token) {
+        if (mService != null) {
+            try {
+                mService.setRequireAttention(requireAttention, token);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
+     * @hide
+     */
+    @RequiresPermission(MANAGE_BIOMETRIC)
+    public boolean getRequireAttention(byte[] token) {
+        boolean result = true;
+        if (mService != null) {
+            try {
+                mService.getRequireAttention(token);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl
index 50d0744..6681bd7 100644
--- a/core/java/android/hardware/face/IFaceService.aidl
+++ b/core/java/android/hardware/face/IFaceService.aidl
@@ -66,10 +66,10 @@
     boolean isHardwareDetected(long deviceId, String opPackageName);
 
     // Get a pre-enrollment authentication token
-    long preEnroll(IBinder token);
+    long generateChallenge(IBinder token);
 
     // Finish an enrollment sequence and invalidate the authentication token
-    int postEnroll(IBinder token);
+    int revokeChallenge(IBinder token);
 
     // Determine if a user has at least one enrolled face
     boolean hasEnrolledFaces(int userId, String opPackageName);
@@ -94,4 +94,8 @@
 
     // Enumerate all faces
     void enumerate(IBinder token, int userId, IFaceServiceReceiver receiver);
+
+    int setRequireAttention(boolean requireAttention, in byte [] token);
+
+    boolean getRequireAttention(in byte [] token);
 }
diff --git a/core/java/android/hardware/location/ContextHubBroadcastReceiver.java b/core/java/android/hardware/location/ContextHubBroadcastReceiver.java
new file mode 100644
index 0000000..e0cc8b7
--- /dev/null
+++ b/core/java/android/hardware/location/ContextHubBroadcastReceiver.java
@@ -0,0 +1,102 @@
+/*
+ * 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.hardware.location;
+
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+
+/**
+ * A BroadcastReceiver that can be used with the Context Hub Service notifications.
+ *
+ * @hide
+ */
+public class ContextHubBroadcastReceiver extends BroadcastReceiver {
+    // The context at which this receiver operates in
+    private Context mContext;
+
+    // The handler to post callbacks to when receiving Context Hub Service intents
+    private Handler mHandler;
+
+    // The callback to be invoked when receiving Context Hub Service intents
+    private ContextHubClientCallback mCallback;
+
+    // The string to use as the broadcast action for this receiver
+    private String mAction;
+
+    // True when this receiver is registered to receive Intents, false otherwise
+    private boolean mRegistered = false;
+
+    public ContextHubBroadcastReceiver(Context context, Handler handler,
+                                       ContextHubClientCallback callback, String tag) {
+        mContext = context;
+        mHandler = handler;
+        mCallback = callback;
+        mAction = tag;
+    }
+
+    /**
+     * Registers this receiver to receive Intents from the Context Hub Service. This method must
+     * only be invoked when the receiver is not registered.
+     *
+     * @throws IllegalStateException if the receiver is already registered
+     */
+    public void register() throws IllegalStateException {
+        if (mRegistered) {
+            throw new IllegalStateException(
+                "Cannot register ContextHubBroadcastReceiver multiple times");
+        }
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(mAction);
+        mContext.registerReceiver(this, intentFilter, null /* broadcastPermission */, mHandler);
+        mRegistered = true;
+    }
+
+    /**
+     * Unregisters this receiver. This method must only be invoked if {@link #register()} is
+     * previously invoked.
+     *
+     * @throws IllegalStateException if the receiver is not yet registered
+     */
+    public void unregister() throws IllegalStateException {
+        if (!mRegistered) {
+            throw new IllegalStateException(
+                "Cannot unregister ContextHubBroadcastReceiver when not registered");
+        }
+        mContext.unregisterReceiver(this);
+        mRegistered = false;
+    }
+
+    /**
+     * Creates a new PendingIntent associated with this receiver.
+     *
+     * @param flags the flags {@link PendingIntent.Flags} to use for the PendingIntent
+     *
+     * @return a PendingIntent to receive notifications for this receiver
+     */
+    public PendingIntent getPendingIntent(@PendingIntent.Flags int flags) {
+        return PendingIntent.getBroadcast(
+            mContext, 0 /* requestCode */, new Intent(mAction), flags);
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        // TODO: Implement this
+    }
+}
diff --git a/core/java/android/hardware/location/ContextHubClient.java b/core/java/android/hardware/location/ContextHubClient.java
index 2335203..917644d 100644
--- a/core/java/android/hardware/location/ContextHubClient.java
+++ b/core/java/android/hardware/location/ContextHubClient.java
@@ -18,6 +18,7 @@
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.app.PendingIntent;
 import android.os.RemoteException;
 
 import com.android.internal.util.Preconditions;
@@ -100,6 +101,57 @@
     }
 
     /**
+     * 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). 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 #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.
+     *
+     * 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.
+     *
+     * See {@link ContextHubBroadcastReceiver} for a helper class to generate the
+     * {@link PendingIntent} through a {@link BroadcastReceiver}, and maps an {@link Intent} to a
+     * {@link ContextHubClientCallback}.
+     *
+     * @param intent    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
+     */
+    public boolean registerIntent(@NonNull PendingIntent intent, long nanoAppId) {
+        // TODO: Implement this
+        return false;
+    }
+
+    /**
+     * Unregisters an intent previously registered via {@link #registerIntent(PendingIntent, long)}.
+     * If this intent has not been registered for this client, this method returns false.
+     *
+     * @return true on success, false otherwise
+     *
+     * @hide
+     */
+    public boolean unregisterIntent(@NonNull PendingIntent intent) {
+        // TODO: Implement this
+        return false;
+    }
+
+    /**
      * Sends a message to a nanoapp through the Context Hub Service.
      *
      * This function returns RESULT_SUCCESS if the message has reached the HAL, but
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index 12d0531..36f3586 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -16,12 +16,14 @@
 package android.hardware.location;
 
 import android.annotation.CallbackExecutor;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.app.PendingIntent;
 import android.content.Context;
 import android.os.Handler;
 import android.os.HandlerExecutor;
@@ -33,6 +35,8 @@
 
 import com.android.internal.util.Preconditions;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.List;
 import java.util.concurrent.Executor;
 
@@ -49,6 +53,111 @@
 public final class ContextHubManager {
     private static final String TAG = "ContextHubManager";
 
+    /**
+     * An extra of type {@link ContextHubInfo} describing the source of the event.
+     *
+     * @hide
+     */
+    public static final String EXTRA_CONTEXT_HUB_INFO =
+            "android.hardware.location.extra.CONTEXT_HUB_INFO";
+
+    /**
+     * An extra of type {@link ContextHubManager.Event} describing the event type.
+     *
+     * @hide
+     */
+    public static final String EXTRA_EVENT_TYPE = "android.hardware.location.extra.EVENT_TYPE";
+
+    /**
+     * An extra of type long describing the ID of the nanoapp an event is for.
+     *
+     * @hide
+     */
+    public static final String EXTRA_NANOAPP_ID = "android.location.hardware.extra.NANOAPP_ID";
+
+    /**
+     * An extra of type int describing the nanoapp-specific abort code.
+     *
+     * @hide
+     */
+    public static final String EXTRA_NANOAPP_ABORT_CODE =
+            "android.location.hardware.extra.NANOAPP_ABORT_CODE";
+
+    /**
+     * An extra of type {@link NanoAppMessage} describing contents of a message from a nanoapp.
+     *
+     * @hide
+     */
+    public static final String EXTRA_MESSAGE = "android.location.hardware.extra.MESSAGE";
+
+    /**
+     * Constants describing the type of events from a Context Hub.
+     * {@hide}
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "EVENT_" }, value = {
+        EVENT_NANOAPP_LOADED,
+        EVENT_NANOAPP_UNLOADED,
+        EVENT_NANOAPP_ENABLED,
+        EVENT_NANOAPP_DISABLED,
+        EVENT_NANOAPP_ABORTED,
+        EVENT_NANOAPP_MESSAGE,
+        EVENT_HUB_RESET,
+    })
+    public @interface Event { }
+
+    /**
+     * An event describing that a nanoapp has been loaded. Contains the EXTRA_NANOAPP_ID extra.
+     *
+     * @hide
+     */
+    public static final int EVENT_NANOAPP_LOADED = 0;
+
+    /**
+     * An event describing that a nanoapp has been unloaded. Contains the EXTRA_NANOAPP_ID extra.
+     *
+     * @hide
+     */
+    public static final int EVENT_NANOAPP_UNLOADED = 1;
+
+    /**
+     * An event describing that a nanoapp has been enabled. Contains the EXTRA_NANOAPP_ID extra.
+     *
+     * @hide
+     */
+    public static final int EVENT_NANOAPP_ENABLED = 2;
+
+    /**
+     * An event describing that a nanoapp has been disabled. Contains the EXTRA_NANOAPP_ID extra.
+     *
+     * @hide
+     */
+    public static final int EVENT_NANOAPP_DISABLED = 3;
+
+    /**
+     * An event describing that a nanoapp has aborted. Contains the EXTRA_NANOAPP_ID and
+     * EXTRA_NANOAPP_ABORT_CODE extras.
+     *
+     * @hide
+     */
+    public static final int EVENT_NANOAPP_ABORTED = 4;
+
+    /**
+     * An event containing a message sent from a nanoapp. Contains the EXTRA_NANOAPP_ID and
+     * EXTRA_NANOAPP_MESSAGE extras.
+     *
+     * @hide
+     */
+    public static final int EVENT_NANOAPP_MESSAGE = 5;
+
+    /**
+     * An event describing that the Context Hub has reset.
+     *
+     * @hide
+     */
+    public static final int EVENT_HUB_RESET = 6;
+
+
     private final Looper mMainLooper;
     private final IContextHubService mService;
     private Callback mCallback;
@@ -682,6 +791,57 @@
     }
 
     /**
+     * Creates a ContextHubClient based on an Intent received by the Context Hub Service.
+     *
+     * 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.
+     *
+     * @param intent   the intent that is associated with a client
+     * @param hubInfo  the hub to attach this client to
+     * @param callback the notification callback to register
+     * @param executor the executor to invoke the callback
+     * @return the registered client object
+     *
+     * @throws IllegalArgumentException if hubInfo does not represent a valid hub, or the intent
+     *                                  was not associated with a client
+     * @throws IllegalStateException    if there were too many registered clients at the service
+     * @throws NullPointerException     if intent, hubInfo, callback, or executor is null
+     *
+     * @hide
+     */
+    @NonNull public ContextHubClient createClient(
+            @NonNull PendingIntent intent, @NonNull ContextHubInfo hubInfo,
+            @NonNull ContextHubClientCallback callback,
+            @NonNull @CallbackExecutor Executor executor) {
+        // TODO: Implement this
+        throw new UnsupportedOperationException("Not implemented yet");
+    }
+
+    /**
+     * Equivalent to {@link #createClient(Intent, ContextHubInfo, ContextHubClientCallback,
+     * Executor)} with the executor using the main thread's Looper.
+     *
+     * @param intent   the intent that is associated 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 the intent
+     *                                  was not associated with a client
+     * @throws IllegalStateException    if there were too many registered clients at the service
+     * @throws NullPointerException     if intent, hubInfo, or callback is null
+     *
+     * @hide
+     */
+    @NonNull public ContextHubClient createClient(
+            @NonNull PendingIntent intent, @NonNull ContextHubInfo hubInfo,
+            @NonNull ContextHubClientCallback callback) {
+        return createClient(intent, hubInfo, callback, new HandlerExecutor(Handler.getMain()));
+    }
+
+    /**
      * Unregister a callback for receive messages from the context hub.
      *
      * @see Callback
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index b948402..f7f627e 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -410,14 +410,6 @@
     @GuardedBy("mLock")
     private boolean mNotifyUserActionSent;
 
-    /**
-     * {@code true} when the previous IME had non-empty inset at the bottom of the screen and we
-     * have not shown our own window yet.  In this situation, the previous inset continues to be
-     * shown as an empty region until it is explicitly updated. Basically we can trigger the update
-     * by calling 1) {@code mWindow.show()} or 2) {@link #clearInsetOfPreviousIme()}.
-     */
-    boolean mShouldClearInsetOfPreviousIme;
-
     @UnsupportedAppUsage
     final Insets mTmpInsets = new Insets();
     final int[] mTmpLocation = new int[2];
@@ -581,7 +573,6 @@
             mShowInputFlags = 0;
             mShowInputRequested = false;
             doHideWindow();
-            clearInsetOfPreviousIme();
             if (resultReceiver != null) {
                 resultReceiver.send(wasVis != isInputViewShown()
                         ? InputMethodManager.RESULT_HIDDEN
@@ -601,7 +592,6 @@
             if (dispatchOnShowInputRequested(flags, false)) {
                 showWindow(true);
             }
-            clearInsetOfPreviousIme();
             // If user uses hard keyboard, IME button should always be shown.
             setImeWindowStatus(mapToImeWindowStatus(isInputViewShown()), mBackDisposition);
 
@@ -946,9 +936,6 @@
         super.onCreate();
         mImm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
         mSettingsObserver = SettingsObserver.createAndRegister(this);
-        // If the previous IME has occupied non-empty inset in the screen, we need to decide whether
-        // we continue to use the same size of the inset or update it
-        mShouldClearInsetOfPreviousIme = (mImm.getInputMethodWindowVisibleHeight() > 0);
         // TODO(b/111364446) Need to address context lifecycle issue if need to re-create
         // for update resources & configuration correctly when show soft input
         // in non-default display.
@@ -1882,9 +1869,6 @@
             if (DEBUG) Log.v(TAG, "showWindow: showing!");
             onWindowShown();
             mWindow.show();
-            // Put here rather than in onWindowShown() in case people forget to call
-            // super.onWindowShown().
-            mShouldClearInsetOfPreviousIme = false;
         }
     }
 
@@ -1934,32 +1918,6 @@
     }
 
     /**
-     * Reset the inset occupied the previous IME when and only when
-     * {@link #mShouldClearInsetOfPreviousIme} is {@code true}.
-     */
-    private void clearInsetOfPreviousIme() {
-        if (DEBUG) Log.v(TAG, "clearInsetOfPreviousIme() "
-                + " mShouldClearInsetOfPreviousIme=" + mShouldClearInsetOfPreviousIme);
-        if (!mShouldClearInsetOfPreviousIme) return;
-
-        clearLastInputMethodWindowForTransition();
-        mShouldClearInsetOfPreviousIme = false;
-    }
-
-    /**
-     * Tells the system that the IME decided to not show a window and the system no longer needs to
-     * use the previous IME's inset.
-     *
-     * <p>Caveat: {@link android.inputmethodservice.InputMethodService#clearInsetOfPreviousIme()}
-     * is the only expected caller of this method.  Do not depend on this anywhere else.</p>
-     *
-     * <p>TODO: We probably need to reconsider how IME should be handled.</p>
-     */
-    private void clearLastInputMethodWindowForTransition() {
-        mPrivOps.clearLastInputMethodWindowForTransition();
-    }
-
-    /**
      * Called when a new client has bound to the input method.  This
      * may be followed by a series of {@link #onStartInput(EditorInfo, boolean)}
      * and {@link #onFinishInput()} calls as the user navigates through its
@@ -2845,18 +2803,22 @@
     }
 
     /**
-     * @return The recommended height of the input method window.
-     * An IME author can get the last input method's height as the recommended height
-     * by calling this in
-     * {@link android.inputmethodservice.InputMethodService#onStartInputView(EditorInfo, boolean)}.
-     * If you don't need to use a predefined fixed height, you can avoid the window-resizing of IME
-     * switching by using this value as a visible inset height. It's efficient for the smooth
-     * transition between different IMEs. However, note that this may return 0 (or possibly
-     * unexpectedly low height). You should thus avoid relying on the return value of this method
-     * all the time. Please make sure to use a reasonable height for the IME.
+     * Aimed to return the previous input method's {@link Insets#contentTopInsets}, but its actual
+     * semantics has never been well defined.
+     *
+     * <p>Note that the previous document clearly mentioned that this method could return {@code 0}
+     * at any time for whatever reason.  Now this method is just always returning {@code 0}.</p>
+     *
+     * @return on Android {@link android.os.Build.VERSION_CODES#Q} and later devices this method
+     *         always returns {@code 0}
+     * @deprecated the actual behavior of this method has never been well defined.  You cannot use
+     *             this method in a reliable and predictable way
      */
+    @Deprecated
     public int getInputMethodWindowRecommendedHeight() {
-        return mImm.getInputMethodWindowVisibleHeight();
+        Log.w(TAG, "getInputMethodWindowRecommendedHeight() is deprecated and now always returns 0."
+                + " Do not use this method.");
+        return 0;
     }
 
     /**
@@ -2980,7 +2942,6 @@
                 + " visibleTopInsets=" + mTmpInsets.visibleTopInsets
                 + " touchableInsets=" + mTmpInsets.touchableInsets
                 + " touchableRegion=" + mTmpInsets.touchableRegion);
-        p.println(" mShouldClearInsetOfPreviousIme=" + mShouldClearInsetOfPreviousIme);
         p.println(" mSettingsObserver=" + mSettingsObserver);
     }
 }
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index f2e9078..8333b81 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -26,7 +26,6 @@
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.PackageManager;
 import android.os.Binder;
 import android.os.Build.VERSION_CODES;
 import android.os.Bundle;
@@ -3801,8 +3800,9 @@
 
     private void unsupportedStartingFrom(int version) {
         if (Process.myUid() == Process.SYSTEM_UID) {
-            // The getApplicationInfo() call we make below is not supported in system context, and
-            // we want to allow the system to use these APIs anyway.
+            // The getApplicationInfo() call we make below is not supported in system context. Let
+            // the call through here, and rely on the fact that ConnectivityService will refuse to
+            // allow the system to use these APIs anyway.
             return;
         }
 
@@ -3819,11 +3819,6 @@
     // functions by accessing ConnectivityService directly. However, it should be clear that doing
     // so is unsupported and may break in the future. http://b/22728205
     private void checkLegacyRoutingApiAccess() {
-        if (mContext.checkCallingOrSelfPermission("com.android.permission.INJECT_OMADM_SETTINGS")
-                == PackageManager.PERMISSION_GRANTED) {
-            return;
-        }
-
         unsupportedStartingFrom(VERSION_CODES.M);
     }
 
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 6bd2e76..8681893 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -30,6 +30,8 @@
 
 import dalvik.system.VMRuntime;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -1083,7 +1085,67 @@
         return true;
     }
 
+    /** Build information for a particular device partition. */
+    public static class Partition {
+        /** The name identifying the system partition. */
+        public static final String PARTITION_NAME_SYSTEM = "system";
+
+        private String mName;
+        private String mFingerprint;
+        private long mTimeMs;
+
+        public Partition() {}
+
+        private Partition(String name, String fingerprint, long timeMs) {
+            mName = name;
+            mFingerprint = fingerprint;
+            mTimeMs = timeMs;
+        }
+
+        /** The name of this partition, e.g. "system", or "vendor" */
+        public String getName() {
+            return mName;
+        }
+
+        /** The build fingerprint of this partition, see {@link Build#FINGERPRINT}. */
+        public String getFingerprint() {
+            return mFingerprint;
+        }
+
+        /** The time (ms since epoch), at which this partition was built, see {@link Build#TIME}. */
+        public long getTimeMillis() {
+            return mTimeMs;
+        }
+    }
+
+    /**
+     * Get build information about partitions that have a separate fingerprint defined.
+     *
+     * The list includes partitions that are suitable candidates for over-the-air updates. This is
+     * not an exhaustive list of partitions on the device.
+     */
+    public static List<Partition> getPartitions() {
+        ArrayList<Partition> partitions = new ArrayList();
+
+        String[] names = new String[] {
+            "bootimage", "odm", "product", "product_services", Partition.PARTITION_NAME_SYSTEM,
+            "vendor"
+        };
+        for (String name : names) {
+            String fingerprint = SystemProperties.get("ro." + name + ".build.fingerprint");
+            if (TextUtils.isEmpty(fingerprint)) {
+                continue;
+            }
+            long time = getLong("ro." + name + ".build.date.utc") * 1000;
+            partitions.add(new Partition(name, fingerprint, time));
+        }
+
+        return partitions;
+    }
+
     // The following properties only make sense for internal engineering builds.
+
+    /** The time at which the build was produced, given in milliseconds since the UNIX epoch. */
     public static final long TIME = getLong("ro.build.date.utc") * 1000;
     public static final String USER = getString("ro.build.user");
     public static final String HOST = getString("ro.build.host");
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index f2e0bdd..54be639 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -44,6 +44,8 @@
     private static final boolean DEBUG = false;
     private static final String TAG = "GraphicsEnvironment";
     private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.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 ClassLoader mClassLoader;
     private String mLayerPath;
@@ -54,6 +56,7 @@
      */
     public void setup(Context context) {
         setupGpuLayers(context);
+        setupAngle(context);
         chooseDriver(context);
     }
 
@@ -121,7 +124,6 @@
                     }
                 }
             }
-
         }
 
         // Include the app's lib directory in all cases
@@ -131,6 +133,80 @@
     }
 
     /**
+     * Pass ANGLE details down to trigger enable logic
+     */
+    private static void setupAngle(Context context) {
+
+        String angleEnabledApp =
+                Settings.Global.getString(context.getContentResolver(),
+                                          Settings.Global.ANGLE_ENABLED_APP);
+
+        String packageName = context.getPackageName();
+
+        boolean devOptIn = false;
+        if ((angleEnabledApp != null && packageName != null)
+                && (!angleEnabledApp.isEmpty() && !packageName.isEmpty())
+                && angleEnabledApp.equals(packageName)) {
+
+            if (DEBUG) Log.v(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,
+                PackageManager.MATCH_SYSTEM_ONLY);
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.w(TAG, "ANGLE package '" + ANGLE_PACKAGE_NAME + "' not installed");
+            return;
+        }
+
+        String abi = chooseAbi(angleInfo);
+
+        // Build a path that includes installed native libs and APK
+        StringBuilder sb = new StringBuilder();
+        sb.append(angleInfo.nativeLibraryDir)
+            .append(File.pathSeparator)
+            .append(angleInfo.sourceDir)
+            .append("!/lib/")
+            .append(abi);
+        String paths = sb.toString();
+
+        if (DEBUG) Log.v(TAG, "ANGLE package libs: " + paths);
+
+        // Further opt-in logic is handled in native, so pass relevant info down
+        setAngleInfo(paths, packageName, appPref, devOptIn);
+    }
+
+    /**
      * Choose whether the current process should use the builtin or an updated driver.
      */
     private static void chooseDriver(Context context) {
@@ -218,4 +294,6 @@
     private static native void setLayerPaths(ClassLoader classLoader, String layerPaths);
     private static native void setDebugLayers(String layers);
     private static native void setDriverPath(String path);
+    private static native void setAngleInfo(String path, String appPackage, String appPref,
+                                            boolean devOptIn);
 }
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 6fab3c4..0f64c45 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -483,6 +483,8 @@
      * @param appDataDir null-ok the data directory of the app.
      * @param invokeWith null-ok the command to invoke with.
      * @param packageName null-ok the name of the package this process belongs to.
+     * @param packagesForUid null-ok all the packages with the same uid as this process.
+     * @param visibleVols null-ok storage volumes that can be accessed by this process.
      * @param zygoteArgs Additional arguments to supply to the zygote process.
      * 
      * @return An object that describes the result of the attempt to start the process.
@@ -501,10 +503,13 @@
                                   @Nullable String appDataDir,
                                   @Nullable String invokeWith,
                                   @Nullable String packageName,
+                                  @Nullable String[] packagesForUid,
+                                  @Nullable String[] visibleVols,
                                   @Nullable String[] zygoteArgs) {
         return zygoteProcess.start(processClass, niceName, uid, gid, gids,
                     runtimeFlags, mountExternal, targetSdkVersion, seInfo,
-                    abi, instructionSet, appDataDir, invokeWith, packageName, zygoteArgs);
+                    abi, instructionSet, appDataDir, invokeWith, packageName,
+                    packagesForUid, visibleVols, zygoteArgs);
     }
 
     /** @hide */
@@ -519,10 +524,13 @@
                                   @Nullable String appDataDir,
                                   @Nullable String invokeWith,
                                   @Nullable String packageName,
+                                  @Nullable String[] packagesForUid,
+                                  @Nullable String[] visibleVols,
                                   @Nullable String[] zygoteArgs) {
         return WebViewZygote.getProcess().start(processClass, niceName, uid, gid, gids,
                     runtimeFlags, mountExternal, targetSdkVersion, seInfo,
-                    abi, instructionSet, appDataDir, invokeWith, packageName, zygoteArgs);
+                    abi, instructionSet, appDataDir, invokeWith, packageName,
+                    packagesForUid, visibleVols, zygoteArgs);
     }
 
     /**
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index b0891050..1282170 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -256,6 +256,7 @@
     /**
      * Specifies if a user is disallowed from enabling the
      * "Unknown Sources" setting, that allows installation of apps from unknown sources.
+     * Unknown sources exclude adb and special apps such as trusted app stores.
      * The default value is <code>false</code>.
      *
      * <p>Key for user restrictions.
@@ -267,6 +268,22 @@
     public static final String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources";
 
     /**
+     * This restriction is a device-wide version of {@link DISALLOW_INSTALL_UNKNOWN_SOURCES}.
+     *
+     * Specifies if all users on the device are disallowed from enabling the
+     * "Unknown Sources" setting, that allows installation of apps from unknown sources.
+     * The default value is <code>false</code>.
+     *
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
+     * @see #getUserRestrictions()
+     */
+    public static final String DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY =
+            "no_install_unknown_sources_globally";
+
+    /**
      * Specifies if a user is disallowed from configuring bluetooth.
      * This does <em>not</em> restrict the user from turning bluetooth on or off.
      * The default value is <code>false</code>.
@@ -1669,8 +1686,9 @@
      /**
      * @hide
      * Returns whether the given user has been disallowed from performing certain actions
-     * or setting certain settings through UserManager. This method disregards restrictions
-     * set by device policy.
+     * or setting certain settings through UserManager (e.g. this type of restriction would prevent
+     * the guest user from doing certain things, such as making calls). This method disregards
+     * restrictions set by device policy.
      * @param restrictionKey the string key representing the restriction
      * @param userHandle the UserHandle of the user for whom to retrieve the restrictions.
      */
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index 99181ac..7fd0a4b 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -215,6 +215,8 @@
      * @param appDataDir null-ok the data directory of the app.
      * @param invokeWith null-ok the command to invoke with.
      * @param packageName null-ok the name of the package this process belongs to.
+     * @param packagesForUid null-ok all the packages with the same uid as this process.
+     * @param visibleVols null-ok storage volumes that can be accessed by this process.
      * @param zygoteArgs Additional arguments to supply to the zygote process.
      *
      * @return An object that describes the result of the attempt to start the process.
@@ -231,12 +233,14 @@
                                                   @Nullable String appDataDir,
                                                   @Nullable String invokeWith,
                                                   @Nullable String packageName,
+                                                  @Nullable String[] packagesForUid,
+                                                  @Nullable String[] visibleVols,
                                                   @Nullable String[] zygoteArgs) {
         try {
             return startViaZygote(processClass, niceName, uid, gid, gids,
                     runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                     abi, instructionSet, appDataDir, invokeWith, false /* startChildZygote */,
-                    packageName, zygoteArgs);
+                    packageName, packagesForUid, visibleVols, zygoteArgs);
         } catch (ZygoteStartFailedEx ex) {
             Log.e(LOG_TAG,
                     "Starting VM process through Zygote failed");
@@ -355,6 +359,8 @@
      * @param startChildZygote Start a sub-zygote. This creates a new zygote process
      * that has its state cloned from this zygote process.
      * @param packageName null-ok the name of the package this process belongs to.
+     * @param packagesForUid null-ok all the packages with the same uid as this process.
+     * @param visibleVols null-ok storage volumes that can be accessed by this process.
      * @param extraArgs Additional arguments to supply to the zygote process.
      * @return An object that describes the result of the attempt to start the process.
      * @throws ZygoteStartFailedEx if process start failed for any reason
@@ -372,6 +378,8 @@
                                                       @Nullable String invokeWith,
                                                       boolean startChildZygote,
                                                       @Nullable String packageName,
+                                                      @Nullable String[] packagesForUid,
+                                                      @Nullable String[] visibleVols,
                                                       @Nullable String[] extraArgs)
                                                       throws ZygoteStartFailedEx {
         ArrayList<String> argsForZygote = new ArrayList<String>();
@@ -439,6 +447,32 @@
             argsForZygote.add("--package-name=" + packageName);
         }
 
+        if (packagesForUid != null && packagesForUid.length > 0) {
+            final StringBuilder sb = new StringBuilder();
+            sb.append("--packages-for-uid=");
+
+            for (int i = 0; i < packagesForUid.length; ++i) {
+                if (i != 0) {
+                    sb.append(',');
+                }
+                sb.append(packagesForUid[i]);
+            }
+            argsForZygote.add(sb.toString());
+        }
+
+        if (visibleVols != null && visibleVols.length > 0) {
+            final StringBuilder sb = new StringBuilder();
+            sb.append("--visible-vols=");
+
+            for (int i = 0; i < visibleVols.length; ++i) {
+                if (i != 0) {
+                    sb.append(',');
+                }
+                sb.append(visibleVols[i]);
+            }
+            argsForZygote.add(sb.toString());
+        }
+
         argsForZygote.add(processClass);
 
         if (extraArgs != null) {
@@ -746,7 +780,8 @@
             result = startViaZygote(processClass, niceName, uid, gid,
                     gids, runtimeFlags, 0 /* mountExternal */, 0 /* targetSdkVersion */, seInfo,
                     abi, instructionSet, null /* appDataDir */, null /* invokeWith */,
-                    true /* startChildZygote */, null /* packageName */, extraArgs);
+                    true /* startChildZygote */, null /* packageName */,
+                    null /* packagesForUid */, null /* visibleVolumes */, extraArgs);
         } catch (ZygoteStartFailedEx ex) {
             throw new RuntimeException("Starting child-zygote through Zygote failed", ex);
         }
diff --git a/core/java/android/os/storage/StorageManagerInternal.java b/core/java/android/os/storage/StorageManagerInternal.java
index d850e27..1f54ea5 100644
--- a/core/java/android/os/storage/StorageManagerInternal.java
+++ b/core/java/android/os/storage/StorageManagerInternal.java
@@ -89,8 +89,13 @@
      * @param appId The appId for the given package.
      * @param sharedUserId The sharedUserId for given package if it specified
      *      {@code android:sharedUserId} in the manifest, otherwise {@code null}
-     * @param userId
+     * @param userId The userId in which the storage needs to be mounted.
      */
     public abstract void mountExternalStorageForApp(String packageName, int appId,
             String sharedUserId, int userId);
+
+    /**
+     * @return Labels of storage volumes that are visible to the given userId.
+     */
+    public abstract String[] getVisibleVolumesForUser(int userId);
 }
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index afd38369..e55afb6 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -157,7 +157,7 @@
     public final DiskInfo disk;
     public final String partGuid;
     public int mountFlags = 0;
-    public int mountUserId = -1;
+    public int mountUserId = UserHandle.USER_NULL;
     @UnsupportedAppUsage
     public int state = STATE_UNMOUNTED;
     public String fsType;
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
new file mode 100644
index 0000000..aa44eb7
--- /dev/null
+++ b/core/java/android/permission/PermissionManager.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 android.permission;
+
+import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.content.Context;
+
+import com.android.internal.annotations.Immutable;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * System level service for accessing the permission capabilities of the platform.
+ *
+ * @hide
+ */
+@SystemApi
+@SystemService(Context.PERMISSION_SERVICE)
+public final class PermissionManager {
+    /**
+     * {@link android.content.pm.PackageParser} needs access without having a {@link Context}.
+     *
+     * @hide
+     */
+    public static final SplitPermissionInfo[] SPLIT_PERMISSIONS = new SplitPermissionInfo[]{
+            // READ_EXTERNAL_STORAGE is always required when an app requests
+            // WRITE_EXTERNAL_STORAGE, because we can't have an app that has
+            // write access without read access.  The hack here with the target
+            // target SDK version ensures that this grant is always done.
+            new SplitPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
+                    new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE},
+                    android.os.Build.VERSION_CODES.CUR_DEVELOPMENT + 1),
+            new SplitPermissionInfo(android.Manifest.permission.READ_CONTACTS,
+                    new String[]{android.Manifest.permission.READ_CALL_LOG},
+                    android.os.Build.VERSION_CODES.JELLY_BEAN),
+            new SplitPermissionInfo(android.Manifest.permission.WRITE_CONTACTS,
+                    new String[]{android.Manifest.permission.WRITE_CALL_LOG},
+                    android.os.Build.VERSION_CODES.JELLY_BEAN),
+            new SplitPermissionInfo(Manifest.permission.ACCESS_FINE_LOCATION,
+                    new String[]{android.Manifest.permission.ACCESS_BACKGROUND_LOCATION},
+                    android.os.Build.VERSION_CODES.P0),
+            new SplitPermissionInfo(Manifest.permission.ACCESS_COARSE_LOCATION,
+                    new String[]{android.Manifest.permission.ACCESS_BACKGROUND_LOCATION},
+                    android.os.Build.VERSION_CODES.P0)};
+
+    private final @NonNull Context mContext;
+
+    /**
+     * Creates a new instance.
+     *
+     * @param context The current context in which to operate.
+     * @hide
+     */
+    public PermissionManager(@NonNull Context context) {
+        mContext = context;
+    }
+
+    /**
+     * Get list of permissions that have been split into more granular or dependent permissions.
+     *
+     * <p>E.g. before {@link android.os.Build.VERSION_CODES#P0} an app that was granted
+     * {@link Manifest.permission#ACCESS_COARSE_LOCATION} could access he location while it was in
+     * foreground and background. On platforms after {@link android.os.Build.VERSION_CODES#P0}
+     * the location permission only grants location access while the app is in foreground. This
+     * would break apps that target before {@link android.os.Build.VERSION_CODES#P0}. Hence whenever
+     * such an old app asks for a location permission (i.e. the
+     * {@link SplitPermissionInfo#getRootPermission()}), then the
+     * {@link Manifest.permission#ACCESS_BACKGROUND_LOCATION} permission (inside
+     * {@{@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() {
+        return Arrays.asList(SPLIT_PERMISSIONS);
+    }
+
+    /**
+     * A permission that was added in a previous API level might have split into several
+     * permissions. This object describes one such split.
+     */
+    @Immutable
+    public static final class SplitPermissionInfo {
+        private final @NonNull String mRootPerm;
+        private final @NonNull String[] mNewPerms;
+        private final int mTargetSdk;
+
+        /**
+         * Get the permission that is split.
+         */
+        public @NonNull String getRootPermission() {
+            return mRootPerm;
+        }
+
+        /**
+         * Get the permissions that are added.
+         */
+        public @NonNull String[] getNewPermissions() {
+            return mNewPerms;
+        }
+
+        /**
+         * Get the target API level when the permission was split.
+         */
+        public int getTargetSdk() {
+            return mTargetSdk;
+        }
+
+        private SplitPermissionInfo(@NonNull String rootPerm, @NonNull String[] newPerms,
+                int targetSdk) {
+            mRootPerm = rootPerm;
+            mNewPerms = newPerms;
+            mTargetSdk = targetSdk;
+        }
+    }
+}
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index ee64ca2..8c40e0e 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -942,13 +942,26 @@
         return false;
     }
 
-    /** {@hide} */
+    /**
+     * Test if the given URI represents roots backed by {@link DocumentsProvider}.
+     *
+     * @see #buildRootsUri(String)
+     *
+     * {@hide}
+     */
+    public static boolean isRootsUri(Context context, @Nullable Uri uri) {
+        return isRootUri(context, uri, 1 /* pathSize */);
+    }
+
+    /**
+     * Test if the given URI represents specific root backed by {@link DocumentsProvider}.
+     *
+     * @see #buildRootUri(String, String)
+     *
+     * {@hide}
+     */
     public static boolean isRootUri(Context context, @Nullable Uri uri) {
-        if (isContentUri(uri) && isDocumentsProvider(context, uri.getAuthority())) {
-            final List<String> paths = uri.getPathSegments();
-            return (paths.size() == 2 && PATH_ROOT.equals(paths.get(0)));
-        }
-        return false;
+        return isRootUri(context, uri, 2 /* pathSize */);
     }
 
     /** {@hide} */
@@ -967,6 +980,14 @@
         return (paths.size() >= 2 && PATH_TREE.equals(paths.get(0)));
     }
 
+    private static boolean isRootUri(Context context, @Nullable Uri uri, int pathSize) {
+        if (isContentUri(uri) && isDocumentsProvider(context, uri.getAuthority())) {
+            final List<String> paths = uri.getPathSegments();
+            return (paths.size() == pathSize && PATH_ROOT.equals(paths.get(0)));
+        }
+        return false;
+    }
+
     private static boolean isDocumentsProvider(Context context, String authority) {
         final Intent intent = new Intent(PROVIDER_INTERFACE);
         final List<ResolveInfo> infos = context.getPackageManager()
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 82459b1..828fd73 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -1318,18 +1318,6 @@
         }
 
         public static final class Media implements AudioColumns {
-
-            private static final String[] EXTERNAL_PATHS;
-
-            static {
-                String secondary_storage = System.getenv("SECONDARY_STORAGE");
-                if (secondary_storage != null) {
-                    EXTERNAL_PATHS = secondary_storage.split(":");
-                } else {
-                    EXTERNAL_PATHS = new String[0];
-                }
-            }
-
             /**
              * Get the content:// style URI for the audio media table on the
              * given volume.
@@ -1343,14 +1331,9 @@
             }
 
             public static Uri getContentUriForPath(String path) {
-                for (String ep : EXTERNAL_PATHS) {
-                    if (path.startsWith(ep)) {
-                        return EXTERNAL_CONTENT_URI;
-                    }
-                }
-
-                return (path.startsWith(Environment.getExternalStorageDirectory().getPath()) ?
-                        EXTERNAL_CONTENT_URI : INTERNAL_CONTENT_URI);
+                return (path.startsWith(
+                        Environment.getStorageDirectory().getAbsolutePath() + "/")
+                        ? EXTERNAL_CONTENT_URI : INTERNAL_CONTENT_URI);
             }
 
             /**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index aa178fb..1d3cf19 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7267,12 +7267,12 @@
         private static final Validator DOZE_DOUBLE_TAP_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
-         * Whether the device should pulse on reach gesture.
+         * Gesture that wakes up the lock screen.
          * @hide
          */
-        public static final String DOZE_REACH_GESTURE = "doze_reach_gesture";
+        public static final String DOZE_WAKE_LOCK_SCREEN_GESTURE = "doze_wake_lock_screen_gesture";
 
-        private static final Validator DOZE_REACH_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR;
+        private static final Validator DOZE_WAKE_LOCK_SCREEN_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * Gesture that wakes up the display, showing the ambient version of the status bar.
@@ -7689,6 +7689,15 @@
                 BOOLEAN_VALIDATOR;
 
         /**
+         * Whether or not face unlock is allowed for apps (through BiometricPrompt).
+         * @hide
+         */
+        public static final String FACE_UNLOCK_APP_ENABLED = "face_unlock_app_enabled";
+
+        private static final Validator FACE_UNLOCK_APP_ENABLED_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
+        /**
          * Whether the assist gesture should be enabled.
          *
          * @hide
@@ -8184,11 +8193,12 @@
             DOZE_ALWAYS_ON,
             DOZE_PICK_UP_GESTURE,
             DOZE_DOUBLE_TAP_GESTURE,
-            DOZE_REACH_GESTURE,
+            DOZE_WAKE_LOCK_SCREEN_GESTURE,
             DOZE_WAKE_SCREEN_GESTURE,
             NFC_PAYMENT_DEFAULT_COMPONENT,
             AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
             FACE_UNLOCK_KEYGUARD_ENABLED,
+            FACE_UNLOCK_APP_ENABLED,
             ASSIST_GESTURE_ENABLED,
             ASSIST_GESTURE_SILENCE_ALERTS_ENABLED,
             ASSIST_GESTURE_WAKE_ENABLED,
@@ -8331,12 +8341,13 @@
             VALIDATORS.put(DOZE_ALWAYS_ON, DOZE_ALWAYS_ON_VALIDATOR);
             VALIDATORS.put(DOZE_PICK_UP_GESTURE, DOZE_PICK_UP_GESTURE_VALIDATOR);
             VALIDATORS.put(DOZE_DOUBLE_TAP_GESTURE, DOZE_DOUBLE_TAP_GESTURE_VALIDATOR);
-            VALIDATORS.put(DOZE_REACH_GESTURE, DOZE_REACH_GESTURE_VALIDATOR);
+            VALIDATORS.put(DOZE_WAKE_LOCK_SCREEN_GESTURE, DOZE_WAKE_LOCK_SCREEN_GESTURE_VALIDATOR);
             VALIDATORS.put(DOZE_WAKE_SCREEN_GESTURE, DOZE_WAKE_SCREEN_GESTURE_VALIDATOR);
             VALIDATORS.put(NFC_PAYMENT_DEFAULT_COMPONENT, NFC_PAYMENT_DEFAULT_COMPONENT_VALIDATOR);
             VALIDATORS.put(AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
                     AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN_VALIDATOR);
             VALIDATORS.put(FACE_UNLOCK_KEYGUARD_ENABLED, FACE_UNLOCK_KEYGUARD_ENABLED_VALIDATOR);
+            VALIDATORS.put(FACE_UNLOCK_APP_ENABLED, FACE_UNLOCK_APP_ENABLED_VALIDATOR);
             VALIDATORS.put(ASSIST_GESTURE_ENABLED, ASSIST_GESTURE_ENABLED_VALIDATOR);
             VALIDATORS.put(ASSIST_GESTURE_SILENCE_ALERTS_ENABLED,
                     ASSIST_GESTURE_SILENCE_ALERTS_ENABLED_VALIDATOR);
@@ -9593,8 +9604,7 @@
          * Use the old dnsmasq DHCP server for tethering instead of the framework implementation.
          *
          * Integer values are interpreted as boolean, and the absence of an explicit setting
-         * is interpreted as |true|.
-         * TODO: make the default |false|
+         * is interpreted as |false|.
          * @hide
          */
         public static final String TETHER_ENABLE_LEGACY_DHCP_SERVER =
@@ -11570,6 +11580,12 @@
         public static final String GPU_DEBUG_APP = "gpu_debug_app";
 
         /**
+         * App should try to use ANGLE
+         * @hide
+         */
+        public static final String ANGLE_ENABLED_APP = "angle_enabled_app";
+
+        /**
          * Ordered GPU debug layer list
          * i.e. <layer1>:<layer2>:...:<layerN>
          * @hide
diff --git a/core/java/android/security/net/config/DirectoryCertificateSource.java b/core/java/android/security/net/config/DirectoryCertificateSource.java
index 119f5d0..4f4d62a 100644
--- a/core/java/android/security/net/config/DirectoryCertificateSource.java
+++ b/core/java/android/security/net/config/DirectoryCertificateSource.java
@@ -16,26 +16,23 @@
 
 package android.security.net.config;
 
-import android.os.Environment;
-import android.os.UserHandle;
 import android.util.ArraySet;
 import android.util.Log;
-import android.util.Pair;
+
+import libcore.io.IoUtils;
+
 import java.io.BufferedInputStream;
 import java.io.File;
 import java.io.FileInputStream;
-import java.io.InputStream;
 import java.io.IOException;
-import java.security.cert.Certificate;
+import java.io.InputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
 import java.util.Collections;
 import java.util.Set;
-import libcore.io.IoUtils;
-
-import com.android.org.conscrypt.Hex;
-import com.android.org.conscrypt.NativeCrypto;
 
 import javax.security.auth.x500.X500Principal;
 
@@ -192,8 +189,36 @@
     }
 
     private String getHash(X500Principal name) {
-        int hash = NativeCrypto.X509_NAME_hash_old(name);
-        return Hex.intToHexString(hash, 8);
+        int hash = hashName(name);
+        return intToHexString(hash, 8);
+    }
+
+    private static final char[] DIGITS = {
+            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+
+    private static String intToHexString(int i, int minWidth) {
+        int bufLen = 8;  // Max number of hex digits in an int
+        char[] buf = new char[bufLen];
+        int cursor = bufLen;
+
+        do {
+            buf[--cursor] = DIGITS[i & 0xf];
+        } while ((i >>>= 4) != 0 || (bufLen - cursor < minWidth));
+
+        return new String(buf, cursor, bufLen - cursor);
+    }
+
+    // This code matches the code in X509_NAME_hash_old() in Conscrypt, which in turn matches
+    // the names of certificate files.  It must be kept in sync.
+    private static int hashName(X500Principal principal) {
+        try {
+            byte[] digest = MessageDigest.getInstance("MD5").digest(principal.getEncoded());
+            int offset = 0;
+            return (((digest[offset++] & 0xff) << 0) | ((digest[offset++] & 0xff) << 8)
+                    | ((digest[offset++] & 0xff) << 16) | ((digest[offset] & 0xff) << 24));
+        } catch (NoSuchAlgorithmException e) {
+            throw new AssertionError(e);
+        }
     }
 
     private X509Certificate readCertificate(String file) {
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index 6c18b45..573d577 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -651,14 +651,11 @@
     /**
      * Called when the user requests the service to save the contents of a screen.
      *
-     * <p>Service must call one of the {@link SaveCallback} methods (like
-     * {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)})
-     * to notify the Android System of the result of the request.
-     *
      * <p>If the service could not handle the request right away&mdash;for example, because it must
      * launch an activity asking the user to authenticate first or because the network is
      * down&mdash;the service could keep the {@link SaveRequest request} and reuse it later,
-     * but the service must call {@link SaveCallback#onSuccess()} right away.
+     * but the service <b>must always</b> call {@link SaveCallback#onSuccess()} or
+     * {@link SaveCallback#onSuccess(android.content.IntentSender)} right away.
      *
      * <p><b>Note:</b> To retrieve the actual value of fields input by the user, the service
      * should call
diff --git a/core/java/android/service/autofill/FillCallback.java b/core/java/android/service/autofill/FillCallback.java
index 3893f2a..06e2896 100644
--- a/core/java/android/service/autofill/FillCallback.java
+++ b/core/java/android/service/autofill/FillCallback.java
@@ -83,19 +83,24 @@
      * fulfill the request; in this case, the service should call {@link #onSuccess(FillResponse)
      * onSuccess(null)} instead.
      *
-     * <p><b>Note: </b>on Android versions up to {@link android.os.Build.VERSION_CODES#P}, this
-     * method is not working as intended, and the service should call
+     * <p><b>Note: </b>prior to {@link android.os.Build.VERSION_CODES#Q}, this
+     * method was not working as intended and the service should always call
      * {@link #onSuccess(FillResponse) onSuccess(null)} instead.
      *
-     * @param message error message to be displayed to the user. <b>Note: </b> this message is
-     * displayed on {@code logcat} logs and should not contain PII (Personally Identifiable
-     * Information, such as username or email address).
+     * <p><b>Note: </b>for apps targeting {@link android.os.Build.VERSION_CODES#Q} or higher, this
+     * method just logs the message on {@code logcat}; for apps targetting older SDKs, it also
+     * displays the message to user using a {@link android.widget.Toast}. Generally speaking, you
+     * should not display an error to the user if the request failed, unless the request had the
+     * {@link FillRequest#FLAG_MANUAL_REQUEST} flag.
+     *
+     * @param message error message. <b>Note: </b> this message should <b>not</b> contain PII
+     * (Personally Identifiable Information, such as username or email address).
      *
      * @throws IllegalStateException if this method or {@link #onSuccess(FillResponse)} was already
      * called.
      */
     public void onFailure(@Nullable CharSequence message) {
-        Log.w(TAG, "onFailure(): " + (message == null ? null : message.length() + "_chars"));
+        Log.w(TAG, "onFailure(): " + message);
         assertNotCalled();
         mCalled = true;
         try {
diff --git a/core/java/android/service/autofill/SaveCallback.java b/core/java/android/service/autofill/SaveCallback.java
index 0625095..1753ecf 100644
--- a/core/java/android/service/autofill/SaveCallback.java
+++ b/core/java/android/service/autofill/SaveCallback.java
@@ -83,28 +83,30 @@
         }
     }
 
+
+
+
     /**
      * Notifies the Android System that an
      * {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)} could not be handled
      * by the service.
      *
-     * <p>This method should only be called when the service could not handle the request right away
-     * and could not recover or retry it. If the service could retry or recover, it could keep
-     * the {@link SaveRequest} and call {@link #onSuccess()} instead.
+     * <p>This method is just used for logging purposes, the Android System won't call the service
+     * again in case of failures&mdash;if you need to recover from the failure, just save the
+     * {@link SaveRequest} and try again later.
      *
-     * <p><b>Note:</b> The Android System displays an UI with the supplied error message; if
-     * you prefer to show your own message, call {@link #onSuccess()} or
-     * {@link #onSuccess(IntentSender)} instead.
+     * <p><b>Note: </b>for apps targeting {@link android.os.Build.VERSION_CODES#Q} or higher, this
+     * method just logs the message on {@code logcat}; for apps targetting older SDKs, it also
+     * displays the message to user using a {@link android.widget.Toast}.
      *
-     * @param message error message to be displayed to the user. <b>Note: </b> this message is
-     * displayed on {@code logcat} logs and should not contain PII (Personally Identifiable
-     * Information, such as username or email address).
+     * @param message error message. <b>Note: </b> this message should <b>not</b> contain PII
+     * (Personally Identifiable Information, such as username or email address).
      *
      * @throws IllegalStateException if this method, {@link #onSuccess()},
      * or {@link #onSuccess(IntentSender)} was already called.
      */
     public void onFailure(CharSequence message) {
-        Log.w(TAG, "onFailure(): " + (message == null ? null : message.length() + "_chars"));
+        Log.w(TAG, "onFailure(): " + message);
         assertNotCalled();
         mCalled = true;
         try {
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index 26223f7..163e3d5 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -115,6 +115,12 @@
      */
     public static final int SHOW_SOURCE_PUSH_TO_TALK = 1 << 5;
 
+    /**
+     * Flag for use with {@link #onShow}: indicates that the voice interaction service was invoked
+     * from a notification.
+     */
+    public static final int SHOW_SOURCE_NOTIFICATION = 1 << 6;
+
     final Context mContext;
     final HandlerCaller mHandlerCaller;
 
diff --git a/core/java/android/text/NativeLineBreaker.java b/core/java/android/text/NativeLineBreaker.java
index 2bcfa5f..94e10e8 100644
--- a/core/java/android/text/NativeLineBreaker.java
+++ b/core/java/android/text/NativeLineBreaker.java
@@ -21,6 +21,7 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.Px;
 
 import dalvik.annotation.optimization.CriticalNative;
 import dalvik.annotation.optimization.FastNative;
@@ -258,16 +259,91 @@
     /**
      * A result object of a line breaking
      */
-    public static class LineBreaks {
-        public int breakCount;
-        private static final int INITIAL_SIZE = 16;
-        public int[] breaks = new int[INITIAL_SIZE];
-        public float[] widths = new float[INITIAL_SIZE];
-        public float[] ascents = new float[INITIAL_SIZE];
-        public float[] descents = new float[INITIAL_SIZE];
-        // TODO: Introduce Hyphenator for explaining the meaning of flags.
-        public int[] flags = new int[INITIAL_SIZE];
-        // breaks, widths, and flags should all have the same length
+    public static class Result {
+        // Following two contstant must be synced with minikin's line breaker.
+        private static final int TAB_MASK = 0x20000000;
+        private static final int HYPHEN_MASK = 0xFF;
+
+        private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
+                Result.class.getClassLoader(), nGetReleaseResultFunc(), 32);
+        private final long mPtr;
+
+        private Result(long ptr) {
+            mPtr = ptr;
+            sRegistry.registerNativeAllocation(this, mPtr);
+        }
+
+        /**
+         * Returns a number of line count.
+         *
+         * @return number of lines
+         */
+        public @IntRange(from = 0) int getLineCount() {
+            return nGetLineCount(mPtr);
+        }
+
+        /**
+         * Returns a break offset of the line.
+         *
+         * @param lineIndex an index of the line.
+         * @return the break offset.
+         */
+        public @IntRange(from = 0) int getLineBreakOffset(@IntRange(from = 0) int lineIndex) {
+            return nGetLineBreakOffset(mPtr, lineIndex);
+        }
+
+        /**
+         * Returns a width of the line in pixels.
+         *
+         * @param lineIndex an index of the line.
+         * @return a width of the line in pixexls
+         */
+        public @Px float getLineWidth(@IntRange(from = 0) int lineIndex) {
+            return nGetLineWidth(mPtr, lineIndex);
+        }
+
+        /**
+         * Returns an entier font ascent of the line in pixels.
+         *
+         * @param lineIndex an index of the line.
+         * @return an entier font ascent of the line in pixels.
+         */
+        public @Px float getLineAscent(@IntRange(from = 0) int lineIndex) {
+            return nGetLineAscent(mPtr, lineIndex);
+        }
+
+        /**
+         * Returns an entier font descent of the line in pixels.
+         *
+         * @param lineIndex an index of the line.
+         * @return an entier font descent of the line in pixels.
+         */
+        public @Px float getLineDescent(@IntRange(from = 0) int lineIndex) {
+            return nGetLineDescent(mPtr, lineIndex);
+        }
+
+        /**
+         * Returns true if the line has a TAB character.
+         *
+         * @param lineIndex an index of the line.
+         * @return true if the line has a TAB character
+         */
+        public boolean hasLineTab(int lineIndex) {
+            return (nGetLineFlag(mPtr, lineIndex) & TAB_MASK) != 0;
+        }
+
+        /**
+         * Returns a packed packed hyphen edit for the line.
+         *
+         * @param lineIndex an index of the line.
+         * @return a packed hyphen edit for the line.
+         * @see android.text.Hyphenator#unpackStartHyphenEdit(int)
+         * @see android.text.Hyphenator#unpackEndHyphenEdit(int)
+         * @see android.text.Hyphenator#packHyphenEdit(int,int)
+         */
+        public int getLineHyphenEdit(int lineIndex) {
+            return (nGetLineFlag(mPtr, lineIndex) & HYPHEN_MASK);
+        }
     }
 
     private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
@@ -294,14 +370,12 @@
      * @param measuredPara a result of the text measurement
      * @param constraints for a single paragraph
      * @param lineNumber a line number of this paragraph
-     * @param out object to set line break information for the given paragraph
      */
-    public void computeLineBreaks(
+    public Result computeLineBreaks(
             @NonNull NativeMeasuredParagraph measuredPara,
             @NonNull ParagraphConstraints constraints,
-            @IntRange(from = 0) int lineNumber,
-            @NonNull LineBreaks out) {
-        out.breakCount = nComputeLineBreaks(
+            @IntRange(from = 0) int lineNumber) {
+        return new Result(nComputeLineBreaks(
                 mNativePtr,
 
                 // Inputs
@@ -313,17 +387,7 @@
                 constraints.mWidth,
                 constraints.mVariableTabStops,
                 constraints.mDefaultTabStop,
-                lineNumber,
-
-                // Outputs
-                out,
-                out.breaks.length,
-                out.breaks,
-                out.widths,
-                out.ascents,
-                out.descents,
-                out.flags);
-
+                lineNumber));
     }
 
     @FastNative
@@ -341,7 +405,7 @@
     // arrays do not have to be resized
     // The individual character widths will be returned in charWidths. The length of
     // charWidths must be at least the length of the text.
-    private static native int nComputeLineBreaks(
+    private static native long nComputeLineBreaks(
             /* non zero */ long nativePtr,
 
             // Inputs
@@ -353,14 +417,21 @@
             @FloatRange(from = 0.0f) float restWidth,
             @Nullable int[] variableTabStops,
             int defaultTabStop,
-            @IntRange(from = 0) int indentsOffset,
+            @IntRange(from = 0) int indentsOffset);
 
-            // Outputs
-            @NonNull LineBreaks recycle,
-            @IntRange(from  = 0) int recycleLength,
-            @NonNull int[] recycleBreaks,
-            @NonNull float[] recycleWidths,
-            @NonNull float[] recycleAscents,
-            @NonNull float[] recycleDescents,
-            @NonNull int[] recycleFlags);
+    // Result accessors
+    @CriticalNative
+    private static native int nGetLineCount(long ptr);
+    @CriticalNative
+    private static native int nGetLineBreakOffset(long ptr, int idx);
+    @CriticalNative
+    private static native float nGetLineWidth(long ptr, int idx);
+    @CriticalNative
+    private static native float nGetLineAscent(long ptr, int idx);
+    @CriticalNative
+    private static native float nGetLineDescent(long ptr, int idx);
+    @CriticalNative
+    private static native int nGetLineFlag(long ptr, int idx);
+    @CriticalNative
+    private static native long nGetReleaseResultFunc();
 }
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index c5fabaf..0d29da0 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -1610,13 +1610,14 @@
     public boolean equals(Object o) {
         if (o instanceof Spanned &&
                 toString().equals(o.toString())) {
-            Spanned other = (Spanned) o;
+            final Spanned other = (Spanned) o;
             // Check span data
-            Object[] otherSpans = other.getSpans(0, other.length(), Object.class);
+            final Object[] otherSpans = other.getSpans(0, other.length(), Object.class);
+            final Object[] thisSpans = getSpans(0, length(), Object.class);
             if (mSpanCount == otherSpans.length) {
                 for (int i = 0; i < mSpanCount; ++i) {
-                    Object thisSpan = mSpans[i];
-                    Object otherSpan = otherSpans[i];
+                    final Object thisSpan = thisSpans[i];
+                    final Object otherSpan = otherSpans[i];
                     if (thisSpan == this) {
                         if (other != otherSpan ||
                                 getSpanStart(thisSpan) != other.getSpanStart(otherSpan) ||
diff --git a/core/java/android/text/SpannableStringInternal.java b/core/java/android/text/SpannableStringInternal.java
index 7acd539..a986633 100644
--- a/core/java/android/text/SpannableStringInternal.java
+++ b/core/java/android/text/SpannableStringInternal.java
@@ -16,12 +16,13 @@
 
 package android.text;
 
+import android.annotation.UnsupportedAppUsage;
+
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.GrowingArrayUtils;
 
 import libcore.util.EmptyArray;
 
-import android.annotation.UnsupportedAppUsage;
 import java.lang.reflect.Array;
 
 /* package */ abstract class SpannableStringInternal
@@ -502,13 +503,14 @@
     public boolean equals(Object o) {
         if (o instanceof Spanned &&
                 toString().equals(o.toString())) {
-            Spanned other = (Spanned) o;
+            final Spanned other = (Spanned) o;
             // Check span data
-            Object[] otherSpans = other.getSpans(0, other.length(), Object.class);
+            final Object[] otherSpans = other.getSpans(0, other.length(), Object.class);
+            final Object[] thisSpans = getSpans(0, length(), Object.class);
             if (mSpanCount == otherSpans.length) {
                 for (int i = 0; i < mSpanCount; ++i) {
-                    Object thisSpan = mSpans[i];
-                    Object otherSpan = otherSpans[i];
+                    final Object thisSpan = thisSpans[i];
+                    final Object otherSpan = otherSpans[i];
                     if (thisSpan == this) {
                         if (other != otherSpan ||
                                 getSpanStart(thisSpan) != other.getSpanStart(otherSpan) ||
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index e1ffef0..d2f0853 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -599,7 +599,14 @@
         float ellipsizedWidth = b.mEllipsizedWidth;
         TextUtils.TruncateAt ellipsize = b.mEllipsize;
         final boolean addLastLineSpacing = b.mAddLastLineLineSpacing;
-        NativeLineBreaker.LineBreaks lineBreaks = new NativeLineBreaker.LineBreaks();
+
+        int lineBreakCapacity = 0;
+        int[] breaks = null;
+        float[] lineWidths = null;
+        float[] ascents = null;
+        float[] descents = null;
+        boolean[] hasTabs = null;
+        int[] hyphenEdits = null;
 
         mLineCount = 0;
         mEllipsized = false;
@@ -732,14 +739,27 @@
             constraints.setIndent(firstWidth, firstWidthLineCount);
             constraints.setTabStops(variableTabStops, TAB_INCREMENT);
 
-            lineBreaker.computeLineBreaks(measuredPara.getNativeMeasuredParagraph(),
-                    constraints, mLineCount, lineBreaks);
-            int breakCount = lineBreaks.breakCount;
-            final int[] breaks = lineBreaks.breaks;
-            final float[] lineWidths = lineBreaks.widths;
-            final float[] ascents = lineBreaks.ascents;
-            final float[] descents = lineBreaks.descents;
-            final int[] flags = lineBreaks.flags;
+            NativeLineBreaker.Result res = lineBreaker.computeLineBreaks(
+                    measuredPara.getNativeMeasuredParagraph(), constraints, mLineCount);
+            int breakCount = res.getLineCount();
+            if (lineBreakCapacity < breakCount) {
+                lineBreakCapacity = breakCount;
+                breaks = new int[lineBreakCapacity];
+                lineWidths = new float[lineBreakCapacity];
+                ascents = new float[lineBreakCapacity];
+                descents = new float[lineBreakCapacity];
+                hasTabs = new boolean[lineBreakCapacity];
+                hyphenEdits = new int[lineBreakCapacity];
+            }
+
+            for (int i = 0; i < breakCount; ++i) {
+                breaks[i] = res.getLineBreakOffset(i);
+                lineWidths[i] = res.getLineWidth(i);
+                ascents[i] = res.getLineAscent(i);
+                descents[i] = res.getLineDescent(i);
+                hasTabs[i] = res.hasLineTab(i);
+                hyphenEdits[i] = res.getLineHyphenEdit(i);
+            }
 
             final int remainingLineCount = mMaximumVisibleLineCount - mLineCount;
             final boolean ellipsisMayBeApplied = ellipsize != null
@@ -750,7 +770,7 @@
                     && ellipsisMayBeApplied) {
                 // Calculate width
                 float width = 0;
-                int flag = 0;  // XXX May need to also have starting hyphen edit
+                boolean hasTab = false;  // XXX May need to also have starting hyphen edit
                 for (int i = remainingLineCount - 1; i < breakCount; i++) {
                     if (i == breakCount - 1) {
                         width += lineWidths[i];
@@ -759,12 +779,12 @@
                             width += measuredPara.getCharWidthAt(j - paraStart);
                         }
                     }
-                    flag |= flags[i] & TAB_MASK;
+                    hasTab |= hasTabs[i];
                 }
                 // Treat the last line and overflowed lines as a single line.
                 breaks[remainingLineCount - 1] = breaks[breakCount - 1];
                 lineWidths[remainingLineCount - 1] = width;
-                flags[remainingLineCount - 1] = flag;
+                hasTabs[remainingLineCount - 1] = hasTab;
 
                 breakCount = remainingLineCount;
             }
@@ -821,8 +841,8 @@
                     v = out(source, here, endPos,
                             ascent, descent, fmTop, fmBottom,
                             v, spacingmult, spacingadd, chooseHt, chooseHtv, fm,
-                            flags[breakIndex], needMultiply, measuredPara, bufEnd,
-                            includepad, trackpad, addLastLineSpacing, chs,
+                            hasTabs[breakIndex], hyphenEdits[breakIndex], needMultiply,
+                            measuredPara, bufEnd, includepad, trackpad, addLastLineSpacing, chs,
                             paraStart, ellipsize, ellipsizedWidth, lineWidths[breakIndex],
                             paint, moreChars);
 
@@ -860,7 +880,7 @@
                     fm.top, fm.bottom,
                     v,
                     spacingmult, spacingadd, null,
-                    null, fm, 0,
+                    null, fm, false, 0,
                     needMultiply, measuredPara, bufEnd,
                     includepad, trackpad, addLastLineSpacing, null,
                     bufStart, ellipsize,
@@ -871,7 +891,8 @@
     private int out(final CharSequence text, final int start, final int end, int above, int below,
             int top, int bottom, int v, final float spacingmult, final float spacingadd,
             final LineHeightSpan[] chooseHt, final int[] chooseHtv, final Paint.FontMetricsInt fm,
-            final int flags, final boolean needMultiply, @NonNull final MeasuredParagraph measured,
+            final boolean hasTab, final int hyphenEdit, final boolean needMultiply,
+            @NonNull final MeasuredParagraph measured,
             final int bufEnd, final boolean includePad, final boolean trackPad,
             final boolean addLastLineLineSpacing, final char[] chs,
             final int widthStart, final TextUtils.TruncateAt ellipsize, final float ellipsisWidth,
@@ -1005,8 +1026,8 @@
 
         // TODO: could move TAB to share same column as HYPHEN, simplifying this code and gaining
         // one bit for start field
-        lines[off + TAB] |= flags & TAB_MASK;
-        lines[off + HYPHEN] = flags;
+        lines[off + TAB] |= hasTab ? TAB_MASK : 0;
+        lines[off + HYPHEN] = hyphenEdit;
         lines[off + DIR] |= dir << DIR_SHIFT;
         mLineDirections[j] = measured.getDirections(start - widthStart, end - widthStart);
 
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index b49a949..44dfd11 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -1230,7 +1230,7 @@
                     // with the next chunk. So we just save the TextPaint for future comparisons
                     // and use.
                     activePaint.set(wp);
-                } else if (!wp.hasEqualAttributes(activePaint)) {
+                } else if (!equalAttributes(wp, activePaint)) {
                     // The style of the present chunk of text is substantially different from the
                     // style of the previous chunk. We need to handle the active piece of text
                     // and restart with the present chunk.
@@ -1335,4 +1335,42 @@
     }
 
     private static final int TAB_INCREMENT = 20;
+
+    private static boolean equalAttributes(@NonNull TextPaint lp, @NonNull TextPaint rp) {
+        return lp.getColorFilter() == rp.getColorFilter()
+                && lp.getMaskFilter() == rp.getMaskFilter()
+                && lp.getShader() == rp.getShader()
+                && lp.getTypeface() == rp.getTypeface()
+                && lp.getXfermode() == rp.getXfermode()
+                && lp.getTextLocales().equals(rp.getTextLocales())
+                && TextUtils.equals(lp.getFontFeatureSettings(), rp.getFontFeatureSettings())
+                && TextUtils.equals(lp.getFontVariationSettings(), rp.getFontVariationSettings())
+                && lp.getShadowLayerRadius() == rp.getShadowLayerRadius()
+                && lp.getShadowLayerDx() == rp.getShadowLayerDx()
+                && lp.getShadowLayerDy() == rp.getShadowLayerDy()
+                && lp.getShadowLayerColor() == rp.getShadowLayerColor()
+                && lp.getFlags() == rp.getFlags()
+                && lp.getHinting() == rp.getHinting()
+                && lp.getStyle() == rp.getStyle()
+                && lp.getColor() == rp.getColor()
+                && lp.getStrokeWidth() == rp.getStrokeWidth()
+                && lp.getStrokeMiter() == rp.getStrokeMiter()
+                && lp.getStrokeCap() == rp.getStrokeCap()
+                && lp.getStrokeJoin() == rp.getStrokeJoin()
+                && lp.getTextAlign() == rp.getTextAlign()
+                && lp.isElegantTextHeight() == rp.isElegantTextHeight()
+                && lp.getTextSize() == rp.getTextSize()
+                && lp.getTextScaleX() == rp.getTextScaleX()
+                && lp.getTextSkewX() == rp.getTextSkewX()
+                && lp.getLetterSpacing() == rp.getLetterSpacing()
+                && lp.getWordSpacing() == rp.getWordSpacing()
+                && lp.getHyphenEdit() == rp.getHyphenEdit()
+                && lp.bgColor == rp.bgColor
+                && lp.baselineShift == rp.baselineShift
+                && lp.linkColor == rp.linkColor
+                && lp.drawableState == rp.drawableState
+                && lp.density == rp.density
+                && lp.underlineColor == rp.underlineColor
+                && lp.underlineThickness == rp.underlineThickness;
+    }
 }
diff --git a/core/java/android/text/TextPaint.java b/core/java/android/text/TextPaint.java
index 7bcc685..d5aad33 100644
--- a/core/java/android/text/TextPaint.java
+++ b/core/java/android/text/TextPaint.java
@@ -17,7 +17,7 @@
 package android.text;
 
 import android.annotation.ColorInt;
-import android.annotation.NonNull;
+import android.annotation.Px;
 import android.annotation.UnsupportedAppUsage;
 import android.graphics.Paint;
 
@@ -37,17 +37,14 @@
     public float density = 1.0f;
     /**
      * Special value 0 means no custom underline
-     * @hide
      */
     @ColorInt
-    @UnsupportedAppUsage
     public int underlineColor = 0;
+
     /**
      * Thickness of the underline, in pixels.
-     * @hide
      */
-    @UnsupportedAppUsage
-    public float underlineThickness;
+    public @Px float underlineThickness;
 
     public TextPaint() {
         super();
@@ -78,24 +75,6 @@
     }
 
     /**
-     * Returns true if all attributes, including the attributes inherited from Paint, are equal.
-     *
-     * The caller is expected to have checked the trivial cases, like the pointers being equal,
-     * the objects having different classes, or the parameter being null.
-     * @hide
-     */
-    public boolean hasEqualAttributes(@NonNull TextPaint other) {
-        return bgColor == other.bgColor
-                && baselineShift == other.baselineShift
-                && linkColor == other.linkColor
-                && drawableState == other.drawableState
-                && density == other.density
-                && underlineColor == other.underlineColor
-                && underlineThickness == other.underlineThickness
-                && super.hasEqualAttributes((Paint) other);
-    }
-
-    /**
      * Defines a custom underline for this Paint.
      * @param color underline solid color
      * @param thickness underline thickness
diff --git a/core/java/android/text/style/TextAppearanceSpan.java b/core/java/android/text/style/TextAppearanceSpan.java
index c17cfd5..2dc4f60 100644
--- a/core/java/android/text/style/TextAppearanceSpan.java
+++ b/core/java/android/text/style/TextAppearanceSpan.java
@@ -16,11 +16,13 @@
 
 package android.text.style;
 
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
 import android.graphics.LeakyTypefaceStorage;
 import android.graphics.Typeface;
+import android.graphics.fonts.Font;
 import android.os.Parcel;
 import android.text.ParcelableSpan;
 import android.text.TextPaint;
@@ -38,6 +40,21 @@
     private final ColorStateList mTextColorLink;
     private final Typeface mTypeface;
 
+    private final int mTextFontWeight;
+
+    private final float mShadowRadius;
+    private final float mShadowDx;
+    private final float mShadowDy;
+    private final int mShadowColor;
+
+    private final boolean mHasElegantTextHeight;
+    private final boolean mElegantTextHeight;
+    private final boolean mHasLetterSpacing;
+    private final float mLetterSpacing;
+
+    private final String mFontFeatureSettings;
+    private final String mFontVariationSettings;
+
     /**
      * Uses the specified TextAppearance resource to determine the
      * text appearance.  The <code>appearance</code> should be, for example,
@@ -104,6 +121,34 @@
             }
         }
 
+        mTextFontWeight = a.getInt(com.android.internal.R.styleable
+                .TextAppearance_textFontWeight, -1);
+
+        mShadowRadius = a.getFloat(com.android.internal.R.styleable
+                .TextAppearance_shadowRadius, 0.0f);
+        mShadowDx = a.getFloat(com.android.internal.R.styleable
+                .TextAppearance_shadowDx, 0.0f);
+        mShadowDy = a.getFloat(com.android.internal.R.styleable
+                .TextAppearance_shadowDy, 0.0f);
+        mShadowColor = a.getInt(com.android.internal.R.styleable
+                .TextAppearance_shadowColor, 0);
+
+        mHasElegantTextHeight = a.hasValue(com.android.internal.R.styleable
+                .TextAppearance_elegantTextHeight);
+        mElegantTextHeight = a.getBoolean(com.android.internal.R.styleable
+                .TextAppearance_elegantTextHeight, false);
+
+        mHasLetterSpacing = a.hasValue(com.android.internal.R.styleable
+                .TextAppearance_letterSpacing);
+        mLetterSpacing = a.getFloat(com.android.internal.R.styleable
+                .TextAppearance_letterSpacing, 0.0f);
+
+        mFontFeatureSettings = a.getString(com.android.internal.R.styleable
+                .TextAppearance_fontFeatureSettings);
+
+        mFontVariationSettings = a.getString(com.android.internal.R.styleable
+                .TextAppearance_fontVariationSettings);
+
         a.recycle();
 
         if (colorList >= 0) {
@@ -129,6 +174,21 @@
         mTextColor = color;
         mTextColorLink = linkColor;
         mTypeface = null;
+
+        mTextFontWeight = -1;
+
+        mShadowRadius = 0.0f;
+        mShadowDx = 0.0f;
+        mShadowDy = 0.0f;
+        mShadowColor = 0;
+
+        mHasElegantTextHeight = false;
+        mElegantTextHeight = false;
+        mHasLetterSpacing = false;
+        mLetterSpacing = 0.0f;
+
+        mFontFeatureSettings = null;
+        mFontVariationSettings = null;
     }
 
     public TextAppearanceSpan(Parcel src) {
@@ -146,6 +206,21 @@
             mTextColorLink = null;
         }
         mTypeface = LeakyTypefaceStorage.readTypefaceFromParcel(src);
+
+        mTextFontWeight = src.readInt();
+
+        mShadowRadius = src.readFloat();
+        mShadowDx = src.readFloat();
+        mShadowDy = src.readFloat();
+        mShadowColor = src.readInt();
+
+        mHasElegantTextHeight = src.readBoolean();
+        mElegantTextHeight = src.readBoolean();
+        mHasLetterSpacing = src.readBoolean();
+        mLetterSpacing = src.readFloat();
+
+        mFontFeatureSettings = src.readString();
+        mFontVariationSettings = src.readString();
     }
 
     public int getSpanTypeId() {
@@ -183,6 +258,21 @@
             dest.writeInt(0);
         }
         LeakyTypefaceStorage.writeTypefaceToParcel(mTypeface, dest);
+
+        dest.writeInt(mTextFontWeight);
+
+        dest.writeFloat(mShadowRadius);
+        dest.writeFloat(mShadowDx);
+        dest.writeFloat(mShadowDy);
+        dest.writeInt(mShadowColor);
+
+        dest.writeBoolean(mHasElegantTextHeight);
+        dest.writeBoolean(mElegantTextHeight);
+        dest.writeBoolean(mHasLetterSpacing);
+        dest.writeFloat(mLetterSpacing);
+
+        dest.writeString(mFontFeatureSettings);
+        dest.writeString(mFontVariationSettings);
     }
 
     /**
@@ -225,6 +315,81 @@
         return mStyle;
     }
 
+    /**
+     * Returns the text font weight specified by this span, or <code>-1</code>
+     * if it does not specify one.
+     */
+    public int getTextFontWeight() {
+        return mTextFontWeight;
+    }
+
+    /**
+     * Returns the typeface specified by this span, or <code>null</code>
+     * if it does not specify one.
+     */
+    @Nullable
+    public Typeface getTypeface() {
+        return mTypeface;
+    }
+
+    /**
+     * Returns the color of the text shadow specified by this span, or <code>0</code>
+     * if it does not specify one.
+     */
+    public int getShadowColor() {
+        return mShadowColor;
+    }
+
+    /**
+     * Returns the horizontal offset of the text shadow specified by this span, or <code>0.0f</code>
+     * if it does not specify one.
+     */
+    public float getShadowDx() {
+        return mShadowDx;
+    }
+
+    /**
+     * Returns the vertical offset of the text shadow specified by this span, or <code>0.0f</code>
+     * if it does not specify one.
+     */
+    public float getShadowDy() {
+        return mShadowDy;
+    }
+
+    /**
+     * Returns the blur radius of the text shadow specified by this span, or <code>0.0f</code>
+     * if it does not specify one.
+     */
+    public float getShadowRadius() {
+        return mShadowRadius;
+    }
+
+    /**
+     * Returns the font feature settings specified by this span, or <code>null</code>
+     * if it does not specify one.
+     */
+    @Nullable
+    public String getFontFeatureSettings() {
+        return mFontFeatureSettings;
+    }
+
+    /**
+     * Returns the font variation settings specified by this span, or <code>null</code>
+     * if it does not specify one.
+     */
+    @Nullable
+    public String getFontVariationSettings() {
+        return mFontVariationSettings;
+    }
+
+    /**
+     * Returns the value of elegant height metrics flag specified by this span,
+     * or <code>false</code> if it does not specify one.
+     */
+    public boolean isElegantTextHeight() {
+        return mElegantTextHeight;
+    }
+
     @Override
     public void updateDrawState(TextPaint ds) {
         updateMeasureState(ds);
@@ -236,6 +401,10 @@
         if (mTextColorLink != null) {
             ds.linkColor = mTextColorLink.getColorForState(ds.drawableState, 0);
         }
+
+        if (mShadowColor != 0) {
+            ds.setShadowLayer(mShadowRadius, mShadowDx, mShadowDy, mShadowColor);
+        }
     }
 
     @Override
@@ -267,7 +436,16 @@
         }
 
         if (styledTypeface != null) {
-            int fake = style & ~styledTypeface.getStyle();
+            final Typeface readyTypeface;
+            if (mTextFontWeight >= 0) {
+                final int weight = Math.min(Font.FONT_WEIGHT_MAX, mTextFontWeight);
+                final boolean italic = (style & Typeface.ITALIC) != 0;
+                readyTypeface = ds.setTypeface(Typeface.create(styledTypeface, weight, italic));
+            } else {
+                readyTypeface = styledTypeface;
+            }
+
+            int fake = style & ~readyTypeface.getStyle();
 
             if ((fake & Typeface.BOLD) != 0) {
                 ds.setFakeBoldText(true);
@@ -277,11 +455,27 @@
                 ds.setTextSkewX(-0.25f);
             }
 
-            ds.setTypeface(styledTypeface);
+            ds.setTypeface(readyTypeface);
         }
 
         if (mTextSize > 0) {
             ds.setTextSize(mTextSize);
         }
+
+        if (mHasElegantTextHeight) {
+            ds.setElegantTextHeight(mElegantTextHeight);
+        }
+
+        if (mHasLetterSpacing) {
+            ds.setLetterSpacing(mLetterSpacing);
+        }
+
+        if (mFontFeatureSettings != null) {
+            ds.setFontFeatureSettings(mFontFeatureSettings);
+        }
+
+        if (mFontVariationSettings != null) {
+            ds.setFontVariationSettings(mFontVariationSettings);
+        }
     }
 }
diff --git a/core/java/android/transition/ChangeImageTransform.java b/core/java/android/transition/ChangeImageTransform.java
index d7a9120..9fa9961 100644
--- a/core/java/android/transition/ChangeImageTransform.java
+++ b/core/java/android/transition/ChangeImageTransform.java
@@ -97,22 +97,13 @@
         values.put(PROPNAME_BOUNDS, bounds);
         Matrix matrix;
         ImageView.ScaleType scaleType = imageView.getScaleType();
-        if (scaleType == ImageView.ScaleType.FIT_XY) {
-            matrix = imageView.getImageMatrix();
-            if (!matrix.isIdentity()) {
-                matrix = new Matrix(matrix);
-            } else {
-                int drawableWidth = drawable.getIntrinsicWidth();
-                int drawableHeight = drawable.getIntrinsicHeight();
-                if (drawableWidth > 0 && drawableHeight > 0) {
-                    float scaleX = ((float) bounds.width()) / drawableWidth;
-                    float scaleY = ((float) bounds.height()) / drawableHeight;
-                    matrix = new Matrix();
-                    matrix.setScale(scaleX, scaleY);
-                } else {
-                    matrix = null;
-                }
-            }
+        int drawableWidth = drawable.getIntrinsicWidth();
+        int drawableHeight = drawable.getIntrinsicHeight();
+        if (scaleType == ImageView.ScaleType.FIT_XY && drawableWidth > 0 && drawableHeight > 0) {
+            float scaleX = ((float) bounds.width()) / drawableWidth;
+            float scaleY = ((float) bounds.height()) / drawableHeight;
+            matrix = new Matrix();
+            matrix.setScale(scaleX, scaleY);
         } else {
             matrix = new Matrix(imageView.getImageMatrix());
         }
@@ -152,17 +143,13 @@
         }
         Rect startBounds = (Rect) startValues.values.get(PROPNAME_BOUNDS);
         Rect endBounds = (Rect) endValues.values.get(PROPNAME_BOUNDS);
-        if (startBounds == null || endBounds == null) {
+        Matrix startMatrix = (Matrix) startValues.values.get(PROPNAME_MATRIX);
+        Matrix endMatrix = (Matrix) endValues.values.get(PROPNAME_MATRIX);
+        if (startBounds == null || endBounds == null || startMatrix == null || endMatrix == null) {
             return null;
         }
 
-        Matrix startMatrix = (Matrix) startValues.values.get(PROPNAME_MATRIX);
-        Matrix endMatrix = (Matrix) endValues.values.get(PROPNAME_MATRIX);
-
-        boolean matricesEqual = (startMatrix == null && endMatrix == null) ||
-                (startMatrix != null && startMatrix.equals(endMatrix));
-
-        if (startBounds.equals(endBounds) && matricesEqual) {
+        if (startBounds.equals(endBounds) && startMatrix.equals(endMatrix)) {
             return null;
         }
 
@@ -172,15 +159,9 @@
         int drawableHeight = drawable.getIntrinsicHeight();
 
         ObjectAnimator animator;
-        if (drawableWidth == 0 || drawableHeight == 0) {
+        if (drawableWidth <= 0 || drawableHeight <= 0) {
             animator = createNullAnimator(imageView);
         } else {
-            if (startMatrix == null) {
-                startMatrix = Matrix.IDENTITY_MATRIX;
-            }
-            if (endMatrix == null) {
-                endMatrix = Matrix.IDENTITY_MATRIX;
-            }
             ANIMATED_TRANSFORM_PROPERTY.set(imageView, startMatrix);
             animator = createMatrixAnimator(imageView, startMatrix, endMatrix);
         }
@@ -189,7 +170,7 @@
 
     private ObjectAnimator createNullAnimator(ImageView imageView) {
         return ObjectAnimator.ofObject(imageView, ANIMATED_TRANSFORM_PROPERTY,
-                NULL_MATRIX_EVALUATOR, null, null);
+                NULL_MATRIX_EVALUATOR, Matrix.IDENTITY_MATRIX, Matrix.IDENTITY_MATRIX);
     }
 
     private ObjectAnimator createMatrixAnimator(final ImageView imageView, Matrix startMatrix,
diff --git a/core/java/android/transition/TransitionManager.java b/core/java/android/transition/TransitionManager.java
index f8e8762..4608e20 100644
--- a/core/java/android/transition/TransitionManager.java
+++ b/core/java/android/transition/TransitionManager.java
@@ -188,7 +188,13 @@
 
         final ViewGroup sceneRoot = scene.getSceneRoot();
         if (!sPendingTransitions.contains(sceneRoot)) {
+            Scene oldScene = Scene.getCurrentScene(sceneRoot);
             if (transition == null) {
+                // Notify old scene that it is being exited
+                if (oldScene != null) {
+                    oldScene.exit();
+                }
+
                 scene.enter();
             } else {
                 sPendingTransitions.add(sceneRoot);
@@ -196,7 +202,6 @@
                 Transition transitionClone = transition.clone();
                 transitionClone.setSceneRoot(sceneRoot);
 
-                Scene oldScene = Scene.getCurrentScene(sceneRoot);
                 if (oldScene != null && oldScene.isCreatedFromLayoutResource()) {
                     transitionClone.setCanRemoveViews(true);
                 }
diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java
index 5108a79..294a179 100644
--- a/core/java/android/util/ArrayMap.java
+++ b/core/java/android/util/ArrayMap.java
@@ -71,19 +71,19 @@
     /**
      * Maximum number of entries to have in array caches.
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Allocations are an implementation detail.
     private static final int CACHE_SIZE = 10;
 
     /**
      * Special hash array value that indicates the container is immutable.
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Allocations are an implementation detail.
     static final int[] EMPTY_IMMUTABLE_INTS = new int[0];
 
     /**
      * @hide Special immutable empty ArrayMap.
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Use your own singleton empty map.
     public static final ArrayMap EMPTY = new ArrayMap<>(-1);
 
     /**
@@ -92,21 +92,21 @@
      * The first entry in the array is a pointer to the next array in the
      * list; the second entry is a pointer to the int[] hash code array for it.
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Allocations are an implementation detail.
     static Object[] mBaseCache;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Allocations are an implementation detail.
     static int mBaseCacheSize;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Allocations are an implementation detail.
     static Object[] mTwiceBaseCache;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Allocations are an implementation detail.
     static int mTwiceBaseCacheSize;
 
     final boolean mIdentityHashCode;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Hashes are an implementation detail. Use public key/value API.
     int[] mHashes;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Storage is an implementation detail. Use public key/value API.
     Object[] mArray;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Use size()
     int mSize;
     MapCollections<K, V> mCollections;
 
@@ -122,7 +122,7 @@
         }
     }
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Hashes are an implementation detail. Use indexOfKey(Object).
     int indexOf(Object key, int hash) {
         final int N = mSize;
 
@@ -161,7 +161,7 @@
         return ~end;
     }
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Use indexOf(null)
     int indexOfNull() {
         final int N = mSize;
 
@@ -200,7 +200,7 @@
         return ~end;
     }
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Allocations are an implementation detail.
     private void allocArrays(final int size) {
         if (mHashes == EMPTY_IMMUTABLE_INTS) {
             throw new UnsupportedOperationException("ArrayMap is immutable");
@@ -239,7 +239,7 @@
         mArray = new Object[size<<1];
     }
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Allocations are an implementation detail.
     private static void freeArrays(final int[] hashes, final Object[] array, final int size) {
         if (hashes.length == (BASE_SIZE*2)) {
             synchronized (ArrayMap.class) {
@@ -393,8 +393,15 @@
                 : indexOf(key, mIdentityHashCode ? System.identityHashCode(key) : key.hashCode());
     }
 
-    @UnsupportedAppUsage
-    int indexOfValue(Object value) {
+    /**
+     * Returns an index for which {@link #valueAt} would return the
+     * specified value, or a negative number if no keys map to the
+     * specified value.
+     * Beware that this is a linear search, unlike lookups by key,
+     * and that multiple keys can map to the same value and this will
+     * find only one of them.
+     */
+    public int indexOfValue(Object value) {
         final int N = mSize*2;
         final Object[] array = mArray;
         if (value == null) {
@@ -551,7 +558,7 @@
      * The array must already be large enough to contain the item.
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Storage is an implementation detail. Use put(K, V).
     public void append(K key, V value) {
         int index = mSize;
         final int hash = key == null ? 0
diff --git a/core/java/android/util/ArraySet.java b/core/java/android/util/ArraySet.java
index 526a950..d74a0fe 100644
--- a/core/java/android/util/ArraySet.java
+++ b/core/java/android/util/ArraySet.java
@@ -71,15 +71,15 @@
     static int sTwiceBaseCacheSize;
 
     final boolean mIdentityHashCode;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Hashes are an implementation detail. Use public API.
     int[] mHashes;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Storage is an implementation detail. Use public API.
     Object[] mArray;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Use size()
     int mSize;
     MapCollections<E, E> mCollections;
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Hashes are an implementation detail. Use indexOfKey(Object).
     private int indexOf(Object key, int hash) {
         final int N = mSize;
 
@@ -118,7 +118,7 @@
         return ~end;
     }
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Use indexOf(null)
     private int indexOfNull() {
         final int N = mSize;
 
@@ -157,7 +157,7 @@
         return ~end;
     }
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Allocations are an implementation detail.
     private void allocArrays(final int size) {
         if (size == (BASE_SIZE * 2)) {
             synchronized (ArraySet.class) {
@@ -215,7 +215,7 @@
         mArray = new Object[size];
     }
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Allocations are an implementation detail.
     private static void freeArrays(final int[] hashes, final Object[] array, final int size) {
         if (hashes.length == (BASE_SIZE * 2)) {
             synchronized (ArraySet.class) {
@@ -289,9 +289,10 @@
         }
     }
 
-    /** {@hide} */
-    @UnsupportedAppUsage
-    public ArraySet(Collection<E> set) {
+    /**
+     * Create a new ArraySet with items from the given collection.
+     */
+    public ArraySet(Collection<? extends E> set) {
         this();
         if (set != null) {
             addAll(set);
diff --git a/core/java/android/util/LongSparseLongArray.java b/core/java/android/util/LongSparseLongArray.java
index d5af922..af163ac 100644
--- a/core/java/android/util/LongSparseLongArray.java
+++ b/core/java/android/util/LongSparseLongArray.java
@@ -46,11 +46,11 @@
  * @hide
  */
 public class LongSparseLongArray implements Cloneable {
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // The type isn't even public.
     private long[] mKeys;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // The type isn't even public.
     private long[] mValues;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // The type isn't even public.
     private int mSize;
 
     /**
diff --git a/core/java/android/util/SparseArray.java b/core/java/android/util/SparseArray.java
index aa5ca35..89ea2d3 100644
--- a/core/java/android/util/SparseArray.java
+++ b/core/java/android/util/SparseArray.java
@@ -56,11 +56,11 @@
     private static final Object DELETED = new Object();
     private boolean mGarbage = false;
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Use keyAt(int)
     private int[] mKeys;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Use valueAt(int), setValueAt(int, E)
     private Object[] mValues;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Use size()
     private int mSize;
 
     /**
diff --git a/core/java/android/util/SparseBooleanArray.java b/core/java/android/util/SparseBooleanArray.java
index 9c6b969..d4c4095 100644
--- a/core/java/android/util/SparseBooleanArray.java
+++ b/core/java/android/util/SparseBooleanArray.java
@@ -185,7 +185,9 @@
         return mValues[index];
     }
 
-    /** @hide */
+    /**
+     * Directly set the value at a particular index.
+     */
     public void setValueAt(int index, boolean value) {
         mValues[index] = value;
     }
@@ -304,10 +306,10 @@
         return buffer.toString();
     }
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Use keyAt(int)
     private int[] mKeys;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Use valueAt(int), setValueAt(int, boolean)
     private boolean[] mValues;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Use size()
     private int mSize;
 }
diff --git a/core/java/android/util/SparseIntArray.java b/core/java/android/util/SparseIntArray.java
index 1954753..9e6bad1 100644
--- a/core/java/android/util/SparseIntArray.java
+++ b/core/java/android/util/SparseIntArray.java
@@ -46,11 +46,11 @@
  * order in the case of <code>valueAt(int)</code>.</p>
  */
 public class SparseIntArray implements Cloneable {
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Use keyAt(int)
     private int[] mKeys;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Use valueAt(int), setValueAt(int, int)
     private int[] mValues;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 28) // Use size()
     private int mSize;
 
     /**
@@ -191,7 +191,6 @@
 
     /**
      * Directly set the value at a particular index.
-     * @hide
      */
     public void setValueAt(int index, int value) {
         mValues[index] = value;
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
index 1203541..1bbef8e 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
@@ -410,7 +410,7 @@
                    NoSuchAlgorithmException {
         try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) {
             SignatureInfo signatureInfo = findSignature(apk);
-            return ApkVerityBuilder.generateApkVerity(apkPath, bufferFactory, signatureInfo);
+            return VerityBuilder.generateApkVerity(apkPath, bufferFactory, signatureInfo);
         }
     }
 
@@ -423,7 +423,7 @@
             if (vSigner.verityRootHash == null) {
                 return null;
             }
-            return ApkVerityBuilder.generateApkVerityRootHash(
+            return VerityBuilder.generateApkVerityRootHash(
                     apk, ByteBuffer.wrap(vSigner.verityRootHash), signatureInfo);
         }
     }
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
index 939522d..1471870 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
@@ -534,7 +534,7 @@
                    NoSuchAlgorithmException {
         try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) {
             SignatureInfo signatureInfo = findSignature(apk);
-            return ApkVerityBuilder.generateApkVerity(apkPath, bufferFactory, signatureInfo);
+            return VerityBuilder.generateApkVerity(apkPath, bufferFactory, signatureInfo);
         }
     }
 
@@ -547,7 +547,7 @@
             if (vSigner.verityRootHash == null) {
                 return null;
             }
-            return ApkVerityBuilder.generateApkVerityRootHash(
+            return VerityBuilder.generateApkVerityRootHash(
                     apk, ByteBuffer.wrap(vSigner.verityRootHash), signatureInfo);
         }
     }
diff --git a/core/java/android/util/apk/ApkSigningBlockUtils.java b/core/java/android/util/apk/ApkSigningBlockUtils.java
index 081033a..87af5364 100644
--- a/core/java/android/util/apk/ApkSigningBlockUtils.java
+++ b/core/java/android/util/apk/ApkSigningBlockUtils.java
@@ -332,7 +332,7 @@
         try {
             byte[] expectedRootHash = parseVerityDigestAndVerifySourceLength(expectedDigest,
                     apk.length(), signatureInfo);
-            ApkVerityBuilder.ApkVerityResult verity = ApkVerityBuilder.generateApkVerityTree(apk,
+            VerityBuilder.VerityResult verity = VerityBuilder.generateApkVerityTree(apk,
                     signatureInfo, new ByteBufferFactory() {
                         @Override
                         public ByteBuffer create(int capacity) {
diff --git a/core/java/android/util/apk/ApkVerityBuilder.java b/core/java/android/util/apk/VerityBuilder.java
similarity index 78%
rename from core/java/android/util/apk/ApkVerityBuilder.java
rename to core/java/android/util/apk/VerityBuilder.java
index 553511d..443bbd8 100644
--- a/core/java/android/util/apk/ApkVerityBuilder.java
+++ b/core/java/android/util/apk/VerityBuilder.java
@@ -29,19 +29,18 @@
 import java.util.ArrayList;
 
 /**
- * ApkVerityBuilder builds the APK verity tree and the verity header.  The generated tree format can
- * be stored on disk for apk-verity setup and used by kernel.  Note that since the current
- * implementation is different from the upstream, we call this implementation apk-verity instead of
- * fs-verity.
+ * VerityBuilder builds the verity Merkle tree and other metadata.  The generated tree format can
+ * be stored on disk for fs-verity setup and used by kernel.  The builder support standard
+ * fs-verity, and Android specific apk-verity that requires additional kernel patches.
  *
- * <p>Unlike a regular Merkle tree, APK verity tree does not cover the content fully. Due to
- * the existing APK format, it has to skip APK Signing Block and also has some special treatment for
- * the "Central Directory offset" field of ZIP End of Central Directory.
+ * <p>Unlike a regular Merkle tree of fs-verity, the apk-verity tree does not cover the file content
+ * fully, and has to skip APK Signing Block with some special treatment for the "Central Directory
+ * offset" field of ZIP End of Central Directory.
  *
  * @hide
  */
-abstract class ApkVerityBuilder {
-    private ApkVerityBuilder() {}
+public abstract class VerityBuilder {
+    private VerityBuilder() {}
 
     private static final int CHUNK_SIZE_BYTES = 4096;  // Typical Linux block size
     private static final int DIGEST_SIZE_BYTES = 32;  // SHA-256 size
@@ -51,12 +50,18 @@
     private static final String JCA_DIGEST_ALGORITHM = "SHA-256";
     private static final byte[] DEFAULT_SALT = new byte[8];
 
-    static class ApkVerityResult {
+    /** Result generated by the builder. */
+    public static class VerityResult {
+        /** Raw fs-verity metadata and Merkle tree ready to be deployed on disk. */
         public final ByteBuffer verityData;
+
+        /** Size of the Merkle tree in {@code verityData}. */
         public final int merkleTreeSize;
+
+        /** Root hash of the Merkle tree. */
         public final byte[] rootHash;
 
-        ApkVerityResult(ByteBuffer verityData, int merkleTreeSize, byte[] rootHash) {
+        private VerityResult(ByteBuffer verityData, int merkleTreeSize, byte[] rootHash) {
             this.verityData = verityData;
             this.merkleTreeSize = merkleTreeSize;
             this.rootHash = rootHash;
@@ -65,19 +70,48 @@
 
     /**
      * Generates the 4k, SHA-256 based Merkle tree for the given APK and stores in the {@link
-     * ByteBuffer} created by the {@link ByteBufferFactory}.  The Merkle tree is suitable to be used
-     * as the on-disk format for apk-verity.
+     * ByteBuffer} created by the {@link ByteBufferFactory}.  The output is suitable to be used as
+     * the on-disk format for fs-verity to use.
      *
-     * @return ApkVerityResult containing a buffer with the generated Merkle tree stored at the
+     * @return VerityResult containing a buffer with the generated Merkle tree stored at the
      *         front, the tree size, and the calculated root hash.
      */
     @NonNull
-    static ApkVerityResult generateApkVerityTree(@NonNull RandomAccessFile apk,
+    public static VerityResult generateFsVerityTree(@NonNull RandomAccessFile apk,
+            @NonNull ByteBufferFactory bufferFactory)
+            throws IOException, SecurityException, NoSuchAlgorithmException, DigestException {
+        return generateVerityTreeInternal(apk, bufferFactory, null /* signatureInfo */,
+                false /* skipSigningBlock */);
+    }
+
+    /**
+     * Generates the 4k, SHA-256 based Merkle tree for the given APK and stores in the {@link
+     * ByteBuffer} created by the {@link ByteBufferFactory}.  The Merkle tree does not cover Signing
+     * Block specificed in {@code signatureInfo}.  The output is suitable to be used as the on-disk
+     * format for fs-verity to use (with elide and patch extensions).
+     *
+     * @return VerityResult containing a buffer with the generated Merkle tree stored at the
+     *         front, the tree size, and the calculated root hash.
+     */
+    @NonNull
+    public static VerityResult generateApkVerityTree(@NonNull RandomAccessFile apk,
             @Nullable SignatureInfo signatureInfo, @NonNull ByteBufferFactory bufferFactory)
             throws IOException, SecurityException, NoSuchAlgorithmException, DigestException {
-        long signingBlockSize =
-                signatureInfo.centralDirOffset - signatureInfo.apkSigningBlockOffset;
-        long dataSize = apk.length() - signingBlockSize;
+        return generateVerityTreeInternal(apk, bufferFactory, signatureInfo,
+                true /* skipSigningBlock */);
+    }
+
+    @NonNull
+    private static VerityResult generateVerityTreeInternal(@NonNull RandomAccessFile apk,
+            @NonNull ByteBufferFactory bufferFactory, @Nullable SignatureInfo signatureInfo,
+            boolean skipSigningBlock)
+            throws IOException, SecurityException, NoSuchAlgorithmException, DigestException {
+        long dataSize = apk.length();
+        if (skipSigningBlock) {
+            long signingBlockSize =
+                    signatureInfo.centralDirOffset - signatureInfo.apkSigningBlockOffset;
+            dataSize -= signingBlockSize;
+        }
         int[] levelOffset = calculateVerityLevelOffset(dataSize);
         int merkleTreeSize = levelOffset[levelOffset.length - 1];
 
@@ -85,11 +119,12 @@
                 merkleTreeSize
                 + CHUNK_SIZE_BYTES);  // maximum size of apk-verity metadata
         output.order(ByteOrder.LITTLE_ENDIAN);
-
         ByteBuffer tree = slice(output, 0, merkleTreeSize);
-        byte[] apkRootHash = generateApkVerityTreeInternal(apk, signatureInfo, DEFAULT_SALT,
-                levelOffset, tree);
-        return new ApkVerityResult(output, merkleTreeSize, apkRootHash);
+        // Only use default salt in legacy case.
+        byte[] salt = skipSigningBlock ? DEFAULT_SALT : null;
+        byte[] apkRootHash = generateVerityTreeInternal(apk, signatureInfo, salt, levelOffset,
+                tree, skipSigningBlock);
+        return new VerityResult(output, merkleTreeSize, apkRootHash);
     }
 
     static void generateApkVerityFooter(@NonNull RandomAccessFile apk,
@@ -138,7 +173,8 @@
             throws IOException, SignatureNotFoundException, SecurityException, DigestException,
                    NoSuchAlgorithmException {
         try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) {
-            ApkVerityResult result = generateApkVerityTree(apk, signatureInfo, bufferFactory);
+            VerityResult result = generateVerityTreeInternal(apk, bufferFactory, signatureInfo,
+                    true /* skipSigningBlock */);
             ByteBuffer footer = slice(result.verityData, result.merkleTreeSize,
                     result.verityData.limit());
             generateApkVerityFooter(apk, signatureInfo, footer);
@@ -170,11 +206,14 @@
         private final byte[] mDigestBuffer = new byte[DIGEST_SIZE_BYTES];
         private final byte[] mSalt;
 
-        private BufferedDigester(byte[] salt, ByteBuffer output) throws NoSuchAlgorithmException {
+        private BufferedDigester(@Nullable byte[] salt, @NonNull ByteBuffer output)
+                throws NoSuchAlgorithmException {
             mSalt = salt;
             mOutput = output.slice();
             mMd = MessageDigest.getInstance(JCA_DIGEST_ALGORITHM);
-            mMd.update(mSalt);
+            if (mSalt != null) {
+                mMd.update(mSalt);
+            }
             mBytesDigestedSinceReset = 0;
         }
 
@@ -201,7 +240,9 @@
                     mMd.digest(mDigestBuffer, 0, mDigestBuffer.length);
                     mOutput.put(mDigestBuffer);
                     // After digest, MessageDigest resets automatically, so no need to reset again.
-                    mMd.update(mSalt);
+                    if (mSalt != null) {
+                        mMd.update(mSalt);
+                    }
                     mBytesDigestedSinceReset = 0;
                 }
             }
@@ -242,6 +283,26 @@
     // thus the syscall overhead is not too big.
     private static final int MMAP_REGION_SIZE_BYTES = 1024 * 1024;
 
+    private static void generateFsVerityDigestAtLeafLevel(RandomAccessFile file, ByteBuffer output)
+            throws IOException, NoSuchAlgorithmException, DigestException {
+        BufferedDigester digester = new BufferedDigester(null /* salt */, output);
+
+        // 1. Digest the whole file by chunks.
+        consumeByChunk(digester,
+                new MemoryMappedFileDataSource(file.getFD(), 0, file.length()),
+                MMAP_REGION_SIZE_BYTES);
+
+        // 2. Pad 0s up to the nearest 4096-byte block before hashing.
+        int lastIncompleteChunkSize = (int) (file.length() % CHUNK_SIZE_BYTES);
+        if (lastIncompleteChunkSize != 0) {
+            digester.consume(ByteBuffer.allocate(CHUNK_SIZE_BYTES - lastIncompleteChunkSize));
+        }
+        digester.assertEmptyBuffer();
+
+        // 3. Fill up the rest of buffer with 0s.
+        digester.fillUpLastOutputChunk();
+    }
+
     private static void generateApkVerityDigestAtLeafLevel(RandomAccessFile apk,
             SignatureInfo signatureInfo, byte[] salt, ByteBuffer output)
             throws IOException, NoSuchAlgorithmException, DigestException {
@@ -288,15 +349,19 @@
     }
 
     @NonNull
-    private static byte[] generateApkVerityTreeInternal(@NonNull RandomAccessFile apk,
-            @Nullable SignatureInfo signatureInfo, @NonNull byte[] salt,
-            @NonNull int[] levelOffset, @NonNull ByteBuffer output)
+    private static byte[] generateVerityTreeInternal(@NonNull RandomAccessFile apk,
+            @Nullable SignatureInfo signatureInfo, @Nullable byte[] salt,
+            @NonNull int[] levelOffset, @NonNull ByteBuffer output, boolean skipSigningBlock)
             throws IOException, NoSuchAlgorithmException, DigestException {
-        assertSigningBlockAlignedAndHasFullPages(signatureInfo);
-
         // 1. Digest the apk to generate the leaf level hashes.
-        generateApkVerityDigestAtLeafLevel(apk, signatureInfo, salt, slice(output,
-                    levelOffset[levelOffset.length - 2], levelOffset[levelOffset.length - 1]));
+        if (skipSigningBlock) {
+            assertSigningBlockAlignedAndHasFullPages(signatureInfo);
+            generateApkVerityDigestAtLeafLevel(apk, signatureInfo, salt, slice(output,
+                        levelOffset[levelOffset.length - 2], levelOffset[levelOffset.length - 1]));
+        } else {
+            generateFsVerityDigestAtLeafLevel(apk, slice(output,
+                        levelOffset[levelOffset.length - 2], levelOffset[levelOffset.length - 1]));
+        }
 
         // 2. Digest the lower level hashes bottom up.
         for (int level = levelOffset.length - 3; level >= 0; level--) {
@@ -434,10 +499,11 @@
         return levelOffset;
     }
 
-    private static void assertSigningBlockAlignedAndHasFullPages(SignatureInfo signatureInfo) {
+    private static void assertSigningBlockAlignedAndHasFullPages(
+            @NonNull SignatureInfo signatureInfo) {
         if (signatureInfo.apkSigningBlockOffset % CHUNK_SIZE_BYTES != 0) {
             throw new IllegalArgumentException(
-                    "APK Signing Block does not start at the page  boundary: "
+                    "APK Signing Block does not start at the page boundary: "
                     + signatureInfo.apkSigningBlockOffset);
         }
 
diff --git a/core/java/android/view/DisplayListCanvas.java b/core/java/android/view/DisplayListCanvas.java
index 4b946d7..667fab5 100644
--- a/core/java/android/view/DisplayListCanvas.java
+++ b/core/java/android/view/DisplayListCanvas.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
+import android.graphics.BaseRecordingCanvas;
 import android.graphics.Bitmap;
 import android.graphics.CanvasProperty;
 import android.graphics.Paint;
@@ -35,7 +36,7 @@
  *
  * @hide
  */
-public final class DisplayListCanvas extends RecordingCanvas {
+public final class DisplayListCanvas extends BaseRecordingCanvas {
     // 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;
diff --git a/core/java/android/view/NativeVectorDrawableAnimator.java b/core/java/android/view/NativeVectorDrawableAnimator.java
new file mode 100644
index 0000000..b0556a3
--- /dev/null
+++ b/core/java/android/view/NativeVectorDrawableAnimator.java
@@ -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 android.view;
+
+/**
+ * Exists just to allow for android.graphics & android.view package separation
+ *
+ * TODO: Get off of this coupling more cleanly somehow
+ *
+ * @hide
+ */
+public interface NativeVectorDrawableAnimator {
+    /** @hide */
+    long getAnimatorNativePtr();
+}
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index fcea0c3..8ae9127 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -24,7 +24,6 @@
 import android.graphics.Outline;
 import android.graphics.Paint;
 import android.graphics.Rect;
-import android.graphics.drawable.AnimatedVectorDrawable;
 
 import dalvik.annotation.optimization.CriticalNative;
 import dalvik.annotation.optimization.FastNative;
@@ -148,12 +147,12 @@
      * @hide
      */
     final long mNativeRenderNode;
-    private final View mOwningView;
+    private final AnimationHost mAnimationHost;
 
-    private RenderNode(String name, View owningView) {
+    private RenderNode(String name, AnimationHost animationHost) {
         mNativeRenderNode = nCreate(name);
         NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativeRenderNode);
-        mOwningView = owningView;
+        mAnimationHost = animationHost;
     }
 
     /**
@@ -162,7 +161,7 @@
     private RenderNode(long nativePtr) {
         mNativeRenderNode = nativePtr;
         NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativeRenderNode);
-        mOwningView = null;
+        mAnimationHost = null;
     }
 
     /**
@@ -174,8 +173,8 @@
      * @return A new RenderNode.
      */
     @UnsupportedAppUsage
-    public static RenderNode create(String name, @Nullable View owningView) {
-        return new RenderNode(name, owningView);
+    public static RenderNode create(String name, @Nullable AnimationHost animationHost) {
+        return new RenderNode(name, animationHost);
     }
 
     /**
@@ -189,10 +188,37 @@
     }
 
     /**
+     * Listens for RenderNode position updates for synchronous window movement.
+     *
+     * This is not suitable for generic position listening, it is only designed & intended
+     * for use by things which require external position events like SurfaceView, PopupWindow, etc..
+     *
+     * @hide
+     */
+    interface PositionUpdateListener {
+
+        /**
+         * Called by native by a Rendering Worker thread to update window position
+         *
+         * @hide
+         */
+        void positionChanged(long frameNumber, int left, int top, int right, int bottom);
+
+        /**
+         * Called by native on RenderThread to notify that the view is no longer in the
+         * draw tree. UI thread is blocked at this point.
+         *
+         * @hide
+         */
+        void positionLost(long frameNumber);
+
+    }
+
+    /**
      * Enable callbacks for position changes.
      */
-    public void requestPositionUpdates(SurfaceView view) {
-        nRequestPositionUpdates(mNativeRenderNode, view);
+    public void requestPositionUpdates(PositionUpdateListener listener) {
+        nRequestPositionUpdates(mNativeRenderNode, listener);
     }
 
 
@@ -843,30 +869,72 @@
         return nGetDebugSize(mNativeRenderNode);
     }
 
+    /**
+     * Sets whether or not to allow force dark to apply to this RenderNode.
+     *
+     * Setting this to false will disable the auto-dark feature on everything this RenderNode
+     * draws, including any descendants.
+     *
+     * Setting this to true will allow this RenderNode to be automatically made dark, however
+     * a value of 'true' will not override any 'false' value in its parent chain nor will
+     * it prevent any 'false' in any of its children.
+     *
+     * @param allow Whether or not to allow force dark.
+     * @return true If the value has changed, false otherwise.
+     */
+    public boolean setAllowForceDark(boolean allow) {
+        return nSetAllowForceDark(mNativeRenderNode, allow);
+    }
+
+    /**
+     * See {@link #setAllowForceDark(boolean)}
+     *
+     * @return true if force dark is allowed (default), false if it is disabled
+     */
+    public boolean getAllowForceDark() {
+        return nGetAllowForceDark(mNativeRenderNode);
+    }
+
     ///////////////////////////////////////////////////////////////////////////
     // Animations
     ///////////////////////////////////////////////////////////////////////////
 
+    /**
+     * TODO: Figure out if this can be eliminated/refactored away
+     *
+     * For now this interface exists to de-couple RenderNode from anything View-specific in a
+     * bit of a kludge.
+     *
+     * @hide */
+    interface AnimationHost {
+        void registerAnimatingRenderNode(RenderNode animator);
+        void registerVectorDrawableAnimator(NativeVectorDrawableAnimator animator);
+        boolean isAttached();
+    }
+
+    /** @hide */
     public void addAnimator(RenderNodeAnimator animator) {
-        if (mOwningView == null || mOwningView.mAttachInfo == null) {
+        if (!isAttached()) {
             throw new IllegalStateException("Cannot start this animator on a detached view!");
         }
         nAddAnimator(mNativeRenderNode, animator.getNativeAnimator());
-        mOwningView.mAttachInfo.mViewRootImpl.registerAnimatingRenderNode(this);
+        mAnimationHost.registerAnimatingRenderNode(this);
     }
 
+    /** @hide */
     public boolean isAttached() {
-        return mOwningView != null && mOwningView.mAttachInfo != null;
+        return mAnimationHost != null && mAnimationHost.isAttached();
     }
 
-    public void registerVectorDrawableAnimator(
-            AnimatedVectorDrawable.VectorDrawableAnimatorRT animatorSet) {
-        if (mOwningView == null || mOwningView.mAttachInfo == null) {
+    /** @hide */
+    public void registerVectorDrawableAnimator(NativeVectorDrawableAnimator animatorSet) {
+        if (!isAttached()) {
             throw new IllegalStateException("Cannot start this animator on a detached view!");
         }
-        mOwningView.mAttachInfo.mViewRootImpl.registerVectorDrawableAnimator(animatorSet);
+        mAnimationHost.registerVectorDrawableAnimator(animatorSet);
     }
 
+    /** @hide */
     public void endAllAnimators() {
         nEndAllAnimators(mNativeRenderNode);
     }
@@ -880,7 +948,8 @@
     private static native long nGetNativeFinalizer();
     private static native void nOutput(long renderNode);
     private static native int nGetDebugSize(long renderNode);
-    private static native void nRequestPositionUpdates(long renderNode, SurfaceView callback);
+    private static native void nRequestPositionUpdates(long renderNode,
+            PositionUpdateListener callback);
 
     // Animations
 
@@ -1043,4 +1112,8 @@
     private static native int nGetWidth(long renderNode);
     @CriticalNative
     private static native int nGetHeight(long renderNode);
+    @CriticalNative
+    private static native boolean nSetAllowForceDark(long renderNode, boolean allowForceDark);
+    @CriticalNative
+    private static native boolean nGetAllowForceDark(long renderNode);
 }
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 427f570..6fb1bba 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -895,6 +895,7 @@
         HwuiContext(boolean isWideColorGamut) {
             mRenderNode = RenderNode.create("HwuiCanvas", null);
             mRenderNode.setClipToBounds(false);
+            mRenderNode.setAllowForceDark(false);
             mIsWideColorGamut = isWideColorGamut;
             mHwuiRenderer = nHwuiCreate(mRenderNode.mNativeRenderNode, mNativeObject,
                     isWideColorGamut);
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 514a11e..e71182c 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -209,7 +209,7 @@
 
     public SurfaceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
-        mRenderNode.requestPositionUpdates(this);
+        mRenderNode.requestPositionUpdates(mPositionListener);
 
         setWillNotDraw(true);
     }
@@ -826,81 +826,80 @@
 
     private Rect mRTLastReportedPosition = new Rect();
 
-    /**
-     * Called by native by a Rendering Worker thread to update the window position
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public final void updateSurfacePosition_renderWorker(long frameNumber,
-            int left, int top, int right, int bottom) {
-        if (mSurfaceControl == null) {
-            return;
-        }
+    private RenderNode.PositionUpdateListener mPositionListener =
+            new RenderNode.PositionUpdateListener() {
 
-        // TODO: This is teensy bit racey in that a brand new SurfaceView moving on
-        // its 2nd frame if RenderThread is running slowly could potentially see
-        // this as false, enter the branch, get pre-empted, then this comes along
-        // and reports a new position, then the UI thread resumes and reports
-        // its position. This could therefore be de-sync'd in that interval, but
-        // the synchronization would violate the rule that RT must never block
-        // on the UI thread which would open up potential deadlocks. The risk of
-        // a single-frame desync is therefore preferable for now.
-        mRtHandlingPositionUpdates = true;
-        if (mRTLastReportedPosition.left == left
-                && mRTLastReportedPosition.top == top
-                && mRTLastReportedPosition.right == right
-                && mRTLastReportedPosition.bottom == bottom) {
-            return;
-        }
-        try {
-            if (DEBUG) {
-                Log.d(TAG, String.format("%d updateSurfacePosition RenderWorker, frameNr = %d, " +
-                        "postion = [%d, %d, %d, %d]", System.identityHashCode(this),
-                        frameNumber, left, top, right, bottom));
+        @Override
+        public void positionChanged(long frameNumber, int left, int top, int right, int bottom) {
+            if (mSurfaceControl == null) {
+                return;
             }
-            mRTLastReportedPosition.set(left, top, right, bottom);
-            setParentSpaceRectangle(mRTLastReportedPosition, frameNumber);
-            // Now overwrite mRTLastReportedPosition with our values
-        } catch (Exception ex) {
-            Log.e(TAG, "Exception from repositionChild", ex);
-        }
-    }
 
-    /**
-     * Called by native on RenderThread to notify that the view is no longer in the
-     * draw tree. UI thread is blocked at this point.
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public final void surfacePositionLost_uiRtSync(long frameNumber) {
-        if (DEBUG) {
-            Log.d(TAG, String.format("%d windowPositionLost, frameNr = %d",
-                    System.identityHashCode(this), frameNumber));
+            // TODO: This is teensy bit racey in that a brand new SurfaceView moving on
+            // its 2nd frame if RenderThread is running slowly could potentially see
+            // this as false, enter the branch, get pre-empted, then this comes along
+            // and reports a new position, then the UI thread resumes and reports
+            // its position. This could therefore be de-sync'd in that interval, but
+            // the synchronization would violate the rule that RT must never block
+            // on the UI thread which would open up potential deadlocks. The risk of
+            // a single-frame desync is therefore preferable for now.
+            mRtHandlingPositionUpdates = true;
+            if (mRTLastReportedPosition.left == left
+                    && mRTLastReportedPosition.top == top
+                    && mRTLastReportedPosition.right == right
+                    && mRTLastReportedPosition.bottom == bottom) {
+                return;
+            }
+            try {
+                if (DEBUG) {
+                    Log.d(TAG, String.format(
+                            "%d updateSurfacePosition RenderWorker, frameNr = %d, "
+                                    + "postion = [%d, %d, %d, %d]",
+                            System.identityHashCode(this), frameNumber,
+                            left, top, right, bottom));
+                }
+                mRTLastReportedPosition.set(left, top, right, bottom);
+                setParentSpaceRectangle(mRTLastReportedPosition, frameNumber);
+                // Now overwrite mRTLastReportedPosition with our values
+            } catch (Exception ex) {
+                Log.e(TAG, "Exception from repositionChild", ex);
+            }
         }
-        mRTLastReportedPosition.setEmpty();
 
-        if (mSurfaceControl == null) {
-            return;
-        }
-        if (mRtHandlingPositionUpdates) {
-            mRtHandlingPositionUpdates = false;
-            // This callback will happen while the UI thread is blocked, so we can
-            // safely access other member variables at this time.
-            // So do what the UI thread would have done if RT wasn't handling position
-            // updates.
-            if (!mScreenRect.isEmpty() && !mScreenRect.equals(mRTLastReportedPosition)) {
-                try {
-                    if (DEBUG) Log.d(TAG, String.format("%d updateSurfacePosition, " +
-                            "postion = [%d, %d, %d, %d]", System.identityHashCode(this),
-                            mScreenRect.left, mScreenRect.top,
-                            mScreenRect.right, mScreenRect.bottom));
-                    setParentSpaceRectangle(mScreenRect, frameNumber);
-                } catch (Exception ex) {
-                    Log.e(TAG, "Exception configuring surface", ex);
+        @Override
+        public void positionLost(long frameNumber) {
+            if (DEBUG) {
+                Log.d(TAG, String.format("%d windowPositionLost, frameNr = %d",
+                        System.identityHashCode(this), frameNumber));
+            }
+            mRTLastReportedPosition.setEmpty();
+
+            if (mSurfaceControl == null) {
+                return;
+            }
+            if (mRtHandlingPositionUpdates) {
+                mRtHandlingPositionUpdates = false;
+                // This callback will happen while the UI thread is blocked, so we can
+                // safely access other member variables at this time.
+                // So do what the UI thread would have done if RT wasn't handling position
+                // updates.
+                if (!mScreenRect.isEmpty() && !mScreenRect.equals(mRTLastReportedPosition)) {
+                    try {
+                        if (DEBUG) {
+                            Log.d(TAG, String.format("%d updateSurfacePosition, "
+                                            + "postion = [%d, %d, %d, %d]",
+                                    System.identityHashCode(this),
+                                    mScreenRect.left, mScreenRect.top,
+                                    mScreenRect.right, mScreenRect.bottom));
+                        }
+                        setParentSpaceRectangle(mScreenRect, frameNumber);
+                    } catch (Exception ex) {
+                        Log.e(TAG, "Exception configuring surface", ex);
+                    }
                 }
             }
         }
-    }
+    };
 
     private SurfaceHolder.Callback[] getSurfaceCallbacks() {
         SurfaceHolder.Callback callbacks[];
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 6737839..42690ce 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -25,7 +25,6 @@
 import android.graphics.Bitmap;
 import android.graphics.Point;
 import android.graphics.Rect;
-import android.graphics.drawable.AnimatedVectorDrawable;
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
@@ -914,8 +913,7 @@
         nRegisterAnimatingRenderNode(mRootNode.mNativeRenderNode, animator.mNativeRenderNode);
     }
 
-    void registerVectorDrawableAnimator(
-        AnimatedVectorDrawable.VectorDrawableAnimatorRT animator) {
+    void registerVectorDrawableAnimator(NativeVectorDrawableAnimator animator) {
         nRegisterVectorDrawableAnimator(mRootNode.mNativeRenderNode,
                 animator.getAnimatorNativePtr());
     }
@@ -976,6 +974,25 @@
         }
     }
 
+    /** 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.
@@ -1255,4 +1272,5 @@
     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 19e3f7f62..b2944d6 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4864,7 +4864,7 @@
         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
         mUserPaddingStart = UNDEFINED_PADDING;
         mUserPaddingEnd = UNDEFINED_PADDING;
-        mRenderNode = RenderNode.create(getClass().getName(), this);
+        mRenderNode = RenderNode.create(getClass().getName(), new ViewAnimationHostBridge(this));
 
         if (!sCompatibilityDone && context != null) {
             final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
@@ -5732,7 +5732,7 @@
     @UnsupportedAppUsage
     View() {
         mResources = null;
-        mRenderNode = RenderNode.create(getClass().getName(), this);
+        mRenderNode = RenderNode.create(getClass().getName(), new ViewAnimationHostBridge(this));
     }
 
     final boolean debugDraw() {
@@ -15246,6 +15246,44 @@
     }
 
     /**
+     * Sets whether or not to allow force dark to apply to this view.
+     *
+     * Setting this to false will disable the auto-dark feature on everything this view
+     * draws, including any descendants.
+     *
+     * Setting this to true will allow this view to be automatically made dark, however
+     * a value of 'true' will not override any 'false' value in its parent chain nor will
+     * it prevent any 'false' in any of its children.
+     *
+     * The default behavior of force dark is also influenced by the Theme's
+     * {@link android.R.styleable#Theme_isLightTheme isLightTheme} attribute.
+     * If a theme is isLightTheme="false", then force dark is globally disabled for that theme.
+     *
+     * @param allow Whether or not to allow force dark.
+     *
+     * @hide
+     */
+    public void setAllowForceDark(boolean allow) {
+        if (mRenderNode.setAllowForceDark(allow)) {
+            // Currently toggling force-dark requires a new display list push to apply
+            // TODO: Make it not clobber the display list so this is just a damageSelf() instead
+            invalidate();
+        }
+    }
+
+    /**
+     * See {@link #setAllowForceDark(boolean)}
+     *
+     * @return true if force dark is allowed (default), false if it is disabled
+     *
+     * @hide
+     */
+    @ViewDebug.ExportedProperty(category = "drawing")
+    public boolean getAllowForceDark() {
+        return mRenderNode.getAllowForceDark();
+    }
+
+    /**
      * Top position of this view relative to its parent.
      *
      * @return The top of this view, in pixels.
@@ -15598,7 +15636,7 @@
     /**
      * Sets the visual z position of this view, in pixels. This is equivalent to setting the
      * {@link #setTranslationZ(float) translationZ} property to be the difference between
-     * the x value passed in and the current {@link #getElevation() elevation} property.
+     * the z value passed in and the current {@link #getElevation() elevation} property.
      *
      * @param z The visual z position of this view, in pixels.
      */
@@ -20566,7 +20604,8 @@
      */
     private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
         if (renderNode == null) {
-            renderNode = RenderNode.create(drawable.getClass().getName(), this);
+            renderNode = RenderNode.create(drawable.getClass().getName(),
+                    new ViewAnimationHostBridge(this));
             renderNode.setUsageHint(RenderNode.USAGE_BACKGROUND);
         }
 
diff --git a/core/java/android/view/ViewAnimationHostBridge.java b/core/java/android/view/ViewAnimationHostBridge.java
new file mode 100644
index 0000000..58f555d
--- /dev/null
+++ b/core/java/android/view/ViewAnimationHostBridge.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.view;
+
+/**
+ * Maps a View to a RenderNode's AnimationHost
+ *
+ * @hide
+ */
+public class ViewAnimationHostBridge implements RenderNode.AnimationHost {
+    private final View mView;
+
+    /**
+     * @param view the View to bridge to an AnimationHost
+     */
+    public ViewAnimationHostBridge(View view) {
+        mView = view;
+    }
+
+    @Override
+    public void registerAnimatingRenderNode(RenderNode animator) {
+        mView.mAttachInfo.mViewRootImpl.registerAnimatingRenderNode(animator);
+    }
+
+    @Override
+    public void registerVectorDrawableAnimator(NativeVectorDrawableAnimator animator) {
+        mView.mAttachInfo.mViewRootImpl.registerVectorDrawableAnimator(animator);
+    }
+
+    @Override
+    public boolean isAttached() {
+        return mView.mAttachInfo != null;
+    }
+}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 2ee7ab9..bef8e8f 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -43,6 +43,7 @@
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Matrix;
@@ -52,7 +53,6 @@
 import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.graphics.Region;
-import android.graphics.drawable.AnimatedVectorDrawable;
 import android.graphics.drawable.Drawable;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayManager.DisplayListener;
@@ -239,6 +239,12 @@
     final ArrayList<WindowCallbacks> mWindowCallbacks = new ArrayList<>();
     @UnsupportedAppUsage
     final Context mContext;
+    /**
+     * TODO(b/116349163): Check if we can merge this into {@link #mContext}.
+     */
+    @NonNull
+    private Context mDisplayContext;
+
     @UnsupportedAppUsage
     final IWindowSession mWindowSession;
     @NonNull Display mDisplay;
@@ -532,6 +538,7 @@
 
     public ViewRootImpl(Context context, Display display) {
         mContext = context;
+        mDisplayContext = context.createDisplayContext(display);
         mWindowSession = WindowManagerGlobal.getWindowSession();
         mDisplay = display;
         mBasePackageName = context.getBasePackageName();
@@ -984,6 +991,9 @@
         ThreadedRenderer.invokeFunctor(functor, waitForCompletion);
     }
 
+    /**
+     * @param animator animator to register with the hardware renderer
+     */
     public void registerAnimatingRenderNode(RenderNode animator) {
         if (mAttachInfo.mThreadedRenderer != null) {
             mAttachInfo.mThreadedRenderer.registerAnimatingRenderNode(animator);
@@ -995,8 +1005,10 @@
         }
     }
 
-    public void registerVectorDrawableAnimator(
-            AnimatedVectorDrawable.VectorDrawableAnimatorRT animator) {
+    /**
+     * @param animator animator to register with the hardware renderer
+     */
+    public void registerVectorDrawableAnimator(NativeVectorDrawableAnimator animator) {
         if (mAttachInfo.mThreadedRenderer != null) {
             mAttachInfo.mThreadedRenderer.registerVectorDrawableAnimator(animator);
         }
@@ -1066,6 +1078,7 @@
                 mAttachInfo.mThreadedRenderer = ThreadedRenderer.create(mContext, translucent,
                         attrs.getTitle().toString());
                 mAttachInfo.mThreadedRenderer.setWideGamut(wideGamut);
+                updateForceDarkMode();
                 if (mAttachInfo.mThreadedRenderer != null) {
                     mAttachInfo.mHardwareAccelerated =
                             mAttachInfo.mHardwareAccelerationRequested = true;
@@ -1074,6 +1087,27 @@
         }
     }
 
+    private int getNightMode() {
+        return mContext.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
+    }
+
+    private void updateForceDarkMode() {
+        if (mAttachInfo.mThreadedRenderer == null) return;
+
+        boolean nightMode = getNightMode() == Configuration.UI_MODE_NIGHT_YES;
+        TypedArray a = mContext.obtainStyledAttributes(R.styleable.Theme);
+        boolean isLightTheme = a.getBoolean(R.styleable.Theme_isLightTheme, false);
+        a.recycle();
+
+        boolean changed = mAttachInfo.mThreadedRenderer.setForceDark(nightMode);
+        changed |= mAttachInfo.mThreadedRenderer.getRootNode().setAllowForceDark(isLightTheme);
+
+        if (changed) {
+            // TODO: Don't require regenerating all display lists to apply this setting
+            invalidateWorld(mView);
+        }
+    }
+
     @UnsupportedAppUsage
     public View getView() {
         return mView;
@@ -1249,6 +1283,7 @@
         } else {
             mDisplay = preferredDisplay;
         }
+        mDisplayContext = mContext.createDisplayContext(mDisplay);
     }
 
     void pokeDrawLockIfNeeded() {
@@ -2579,7 +2614,7 @@
                     .mayUseInputMethod(mWindowAttributes.flags);
             if (imTarget != mLastWasImTarget) {
                 mLastWasImTarget = imTarget;
-                InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
+                InputMethodManager imm = mDisplayContext.getSystemService(InputMethodManager.class);
                 if (imm != null && imTarget) {
                     imm.onPreWindowFocus(mView, hasWindowFocus);
                     imm.onPostWindowFocus(mView, mView.findFocus(),
@@ -2695,7 +2730,7 @@
             mLastWasImTarget = WindowManager.LayoutParams
                     .mayUseInputMethod(mWindowAttributes.flags);
 
-            InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
+            InputMethodManager imm = mDisplayContext.getSystemService(InputMethodManager.class);
             if (imm != null && mLastWasImTarget && !isInLocalFocusMode()) {
                 imm.onPreWindowFocus(mView, hasWindowFocus);
             }
@@ -4065,6 +4100,8 @@
             mForceNextWindowRelayout = true;
             requestLayout();
         }
+
+        updateForceDarkMode();
     }
 
     /**
@@ -4329,7 +4366,8 @@
                     enqueueInputEvent(event, null, 0, true);
                 } break;
                 case MSG_CHECK_FOCUS: {
-                    InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
+                    InputMethodManager imm =
+                            mDisplayContext.getSystemService(InputMethodManager.class);
                     if (imm != null) {
                         imm.checkFocus();
                     }
@@ -4871,7 +4909,7 @@
         @Override
         protected int onProcess(QueuedInputEvent q) {
             if (mLastWasImTarget && !isInLocalFocusMode()) {
-                InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
+                InputMethodManager imm = mDisplayContext.getSystemService(InputMethodManager.class);
                 if (imm != null) {
                     final InputEvent event = q.mEvent;
                     if (DEBUG_IMF) Log.v(mTag, "Sending input event to IME: " + event);
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 92d145c3..46aea80 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -196,11 +196,10 @@
         synchronized (WindowManagerGlobal.class) {
             if (sWindowSession == null) {
                 try {
-                    if (InputMethodManager.ENABLE_LEGACY_EAGER_INITIALIZATION) {
-                        // Emulate the legacy behavior.  The global instance of InputMethodManager
-                        // was instantiated here.
-                        InputMethodManager.getInstance();
-                    }
+                    // Emulate the legacy behavior.  The global instance of InputMethodManager
+                    // was instantiated here.
+                    // TODO(b/116157766): Remove this hack after cleaning up @UnsupportedAppUsage
+                    InputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary();
                     IWindowManager windowManager = getWindowManagerService();
                     sWindowSession = windowManager.openSession(
                             new IWindowSessionCallback.Stub() {
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index e87048e..7abe19e79 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -301,6 +301,14 @@
      */
     public static final int STATE_UNKNOWN_COMPAT_MODE = 5;
 
+    /**
+     * Same as {@link #STATE_UNKNOWN}, but used on
+     * {@link AutofillManagerClient#setSessionFinished(int)} when the session was finished because
+     * the service failed to fullfil a request.
+     *
+     * @hide
+     */
+    public static final int STATE_UNKNOWN_FAILED = 6;
 
     /**
      * Timeout in ms for calls to the field classification service.
@@ -2023,8 +2031,10 @@
      * @param newState {@link #STATE_FINISHED} (because the autofill service returned a {@code null}
      *  FillResponse), {@link #STATE_UNKNOWN} (because the session was removed),
      *  {@link #STATE_UNKNOWN_COMPAT_MODE} (beucase the session was finished when the URL bar
-     *  changed on compat mode), or {@link #STATE_DISABLED_BY_SERVICE} (because the autofill service
-     *  disabled further autofill requests for the activity).
+     *  changed on compat mode), {@link #STATE_UNKNOWN_FAILED} (because the session was finished
+     *  when the service failed to fullfil the request, or {@link #STATE_DISABLED_BY_SERVICE}
+     *  (because the autofill service or {@link #STATE_DISABLED_BY_SERVICE} (because the autofill
+     *  service disabled further autofill requests for the activity).
      */
     private void setSessionFinished(int newState) {
         synchronized (mLock) {
@@ -2032,7 +2042,7 @@
                 Log.v(TAG, "setSessionFinished(): from " + getStateAsStringLocked() + " to "
                         + getStateAsString(newState));
             }
-            if (newState == STATE_UNKNOWN_COMPAT_MODE) {
+            if (newState == STATE_UNKNOWN_COMPAT_MODE || newState == STATE_UNKNOWN_FAILED) {
                 resetSessionLocked(/* resetEnteredIds= */ true);
                 mState = STATE_UNKNOWN;
             } else {
@@ -2229,6 +2239,8 @@
                 return "DISABLED_BY_SERVICE";
             case STATE_UNKNOWN_COMPAT_MODE:
                 return "UNKNOWN_COMPAT_MODE";
+            case STATE_UNKNOWN_FAILED:
+                return "UNKNOWN_FAILED";
             default:
                 return "INVALID:" + state;
         }
diff --git a/core/java/android/view/inputmethod/InputMethod.java b/core/java/android/view/inputmethod/InputMethod.java
index e1600c4..d09323d 100644
--- a/core/java/android/view/inputmethod/InputMethod.java
+++ b/core/java/android/view/inputmethod/InputMethod.java
@@ -124,7 +124,8 @@
      * @hide
      */
     @MainThread
-    public void updateInputMethodDisplay(int displayId);
+    default void updateInputMethodDisplay(int displayId) {
+    }
 
     /**
      * Bind a new application environment in to the input method, so that it
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 36ede22..ca2ccaf 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -228,12 +228,10 @@
     static final String PENDING_EVENT_COUNTER = "aq:imm";
 
     /**
-     * {@code true} if we want to instantiate {@link InputMethodManager} eagerly in
-     * {@link android.view.WindowManagerGlobal#getWindowSession()}, which is often called in an
-     * early stage of process startup, which is how Android has worked.
+     * Ensures that {@link #sInstance} becomes non-{@code null} for application that have directly
+     * or indirectly relied on {@link #sInstance} via reflection or something like that.
      *
-     * <p>We still have this settings because we know there are possible compatibility concerns if
-     * we stop doing so. Here are scenarios we know and there could be more scenarios we are not
+     * <p>Here are scenarios we know and there could be more scenarios we are not
      * aware of right know.</p>
      *
      * <ul>
@@ -260,13 +258,22 @@
      *     {@link #peekInstance()} to return {@code null} as written in the JavaDoc.</li>
      * </ul>
      *
-     * <p>TODO(Bug 116157766): Check if we can set {@code false} here then remove this settings.</p>
+     * <p>Since this is purely a compatibility hack, this method must be used only from
+     * {@link android.view.WindowManagerGlobal#getWindowSession()} and {@link #getInstance()}.</p>
+     *
+     * <p>TODO(Bug 116157766): Remove this method once we clean up {@link UnsupportedAppUsage}.</p>
      * @hide
      */
-    public static final boolean ENABLE_LEGACY_EAGER_INITIALIZATION = true;
+    public static void ensureDefaultInstanceForDefaultDisplayIfNecessary() {
+        getInstanceInternal();
+    }
 
     private static final Object sLock = new Object();
 
+    /**
+     * @deprecated This cannot be compatible with multi-display. Please do not use this.
+     */
+    @Deprecated
     @GuardedBy("sLock")
     @UnsupportedAppUsage
     static InputMethodManager sInstance;
@@ -735,12 +742,13 @@
     }
 
     /**
-     * Retrieve the global InputMethodManager instance, creating it if it
-     * doesn't already exist.
+     * Retrieve the global {@link InputMethodManager} instance, creating it if it doesn't already
+     * exist.
+     *
+     * @return global {@link InputMethodManager} instance
      * @hide
      */
-    @UnsupportedAppUsage
-    public static InputMethodManager getInstance() {
+    public static InputMethodManager getInstanceInternal() {
         synchronized (sLock) {
             if (sInstance == null) {
                 try {
@@ -756,14 +764,39 @@
     }
 
     /**
-     * Private optimization: retrieve the global InputMethodManager instance, if it exists.
-     * @hide
+     * Deprecated. Do not use.
+     *
+     * @return global {@link InputMethodManager} instance
      * @deprecated Use {@link Context#getSystemService(Class)} instead. This method cannot fully
      *             support multi-display scenario.
+     * @hide
+     */
+    @Deprecated
+    @UnsupportedAppUsage
+    public static InputMethodManager getInstance() {
+        Log.w(TAG, "InputMethodManager.getInstance() is deprecated because it cannot be"
+                        + " compatible with multi-display."
+                        + " Use context.getSystemService(InputMethodManager.class) instead.",
+                new Throwable());
+        ensureDefaultInstanceForDefaultDisplayIfNecessary();
+        return peekInstance();
+    }
+
+    /**
+     * Deprecated. Do not use.
+     *
+     * @return {@link #sInstance}
+     * @deprecated Use {@link Context#getSystemService(Class)} instead. This method cannot fully
+     *             support multi-display scenario.
+     * @hide
      */
     @Deprecated
     @UnsupportedAppUsage
     public static InputMethodManager peekInstance() {
+        Log.w(TAG, "InputMethodManager.peekInstance() is deprecated because it cannot be"
+                        + " compatible with multi-display."
+                        + " Use context.getSystemService(InputMethodManager.class) instead.",
+                new Throwable());
         synchronized (sLock) {
             return sInstance;
         }
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 29339e9..3e240cf 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -44,6 +44,8 @@
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
 
+import com.google.android.textclassifier.AnnotatorModel;
+
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
@@ -92,7 +94,7 @@
     @GuardedBy("mLock") // Do not access outside this lock.
     private ModelFile mModel;
     @GuardedBy("mLock") // Do not access outside this lock.
-    private TextClassifierImplNative mNative;
+    private AnnotatorModel mNative;
 
     private final Object mLoggerLock = new Object();
     @GuardedBy("mLoggerLock") // Do not access outside this lock.
@@ -125,7 +127,7 @@
                     && rangeLength <= mSettings.getSuggestSelectionMaxRangeLength()) {
                 final String localesString = concatenateLocales(request.getDefaultLocales());
                 final ZonedDateTime refTime = ZonedDateTime.now();
-                final TextClassifierImplNative nativeImpl = getNative(request.getDefaultLocales());
+                final AnnotatorModel nativeImpl = getNative(request.getDefaultLocales());
                 final int start;
                 final int end;
                 if (mSettings.isModelDarkLaunchEnabled() && !request.isDarkLaunchAllowed()) {
@@ -134,7 +136,7 @@
                 } else {
                     final int[] startEnd = nativeImpl.suggestSelection(
                             string, request.getStartIndex(), request.getEndIndex(),
-                            new TextClassifierImplNative.SelectionOptions(localesString));
+                            new AnnotatorModel.SelectionOptions(localesString));
                     start = startEnd[0];
                     end = startEnd[1];
                 }
@@ -142,10 +144,10 @@
                         && start >= 0 && end <= string.length()
                         && start <= request.getStartIndex() && end >= request.getEndIndex()) {
                     final TextSelection.Builder tsBuilder = new TextSelection.Builder(start, end);
-                    final TextClassifierImplNative.ClassificationResult[] results =
+                    final AnnotatorModel.ClassificationResult[] results =
                             nativeImpl.classifyText(
                                     string, start, end,
-                                    new TextClassifierImplNative.ClassificationOptions(
+                                    new AnnotatorModel.ClassificationOptions(
                                             refTime.toInstant().toEpochMilli(),
                                             refTime.getZone().getId(),
                                             localesString));
@@ -184,11 +186,11 @@
                 final String localesString = concatenateLocales(request.getDefaultLocales());
                 final ZonedDateTime refTime = request.getReferenceTime() != null
                         ? request.getReferenceTime() : ZonedDateTime.now();
-                final TextClassifierImplNative.ClassificationResult[] results =
+                final AnnotatorModel.ClassificationResult[] results =
                         getNative(request.getDefaultLocales())
                                 .classifyText(
                                         string, request.getStartIndex(), request.getEndIndex(),
-                                        new TextClassifierImplNative.ClassificationOptions(
+                                        new AnnotatorModel.ClassificationOptions(
                                                 refTime.toInstant().toEpochMilli(),
                                                 refTime.getZone().getId(),
                                                 localesString));
@@ -228,17 +230,17 @@
                     ? request.getEntityConfig().resolveEntityListModifications(
                             getEntitiesForHints(request.getEntityConfig().getHints()))
                     : mSettings.getEntityListDefault();
-            final TextClassifierImplNative nativeImpl =
+            final AnnotatorModel nativeImpl =
                     getNative(request.getDefaultLocales());
-            final TextClassifierImplNative.AnnotatedSpan[] annotations =
+            final AnnotatorModel.AnnotatedSpan[] annotations =
                     nativeImpl.annotate(
                         textString,
-                        new TextClassifierImplNative.AnnotationOptions(
+                        new AnnotatorModel.AnnotationOptions(
                                 refTime.toInstant().toEpochMilli(),
                                         refTime.getZone().getId(),
                                 concatenateLocales(request.getDefaultLocales())));
-            for (TextClassifierImplNative.AnnotatedSpan span : annotations) {
-                final TextClassifierImplNative.ClassificationResult[] results =
+            for (AnnotatorModel.AnnotatedSpan span : annotations) {
+                final AnnotatorModel.ClassificationResult[] results =
                         span.getClassification();
                 if (results.length == 0
                         || !entitiesToIdentify.contains(results[0].getCollection())) {
@@ -297,7 +299,7 @@
         }
     }
 
-    private TextClassifierImplNative getNative(LocaleList localeList)
+    private AnnotatorModel getNative(LocaleList localeList)
             throws FileNotFoundException {
         synchronized (mLock) {
             localeList = localeList == null ? LocaleList.getEmptyLocaleList() : localeList;
@@ -310,7 +312,7 @@
                 destroyNativeIfExistsLocked();
                 final ParcelFileDescriptor fd = ParcelFileDescriptor.open(
                         new File(bestModel.getPath()), ParcelFileDescriptor.MODE_READ_ONLY);
-                mNative = new TextClassifierImplNative(fd.getFd());
+                mNative = new AnnotatorModel(fd.getFd());
                 closeAndLogError(fd);
                 mModel = bestModel;
             }
@@ -398,14 +400,14 @@
     }
 
     private TextClassification createClassificationResult(
-            TextClassifierImplNative.ClassificationResult[] classifications,
+            AnnotatorModel.ClassificationResult[] classifications,
             String text, int start, int end, @Nullable Instant referenceTime) {
         final String classifiedText = text.substring(start, end);
         final TextClassification.Builder builder = new TextClassification.Builder()
                 .setText(classifiedText);
 
         final int size = classifications.length;
-        TextClassifierImplNative.ClassificationResult highestScoringResult = null;
+        AnnotatorModel.ClassificationResult highestScoringResult = null;
         float highestScore = Float.MIN_VALUE;
         for (int i = 0; i < size; i++) {
             builder.setEntityType(classifications[i].getCollection(),
@@ -486,9 +488,9 @@
             try {
                 final ParcelFileDescriptor modelFd = ParcelFileDescriptor.open(
                         file, ParcelFileDescriptor.MODE_READ_ONLY);
-                final int version = TextClassifierImplNative.getVersion(modelFd.getFd());
+                final int version = AnnotatorModel.getVersion(modelFd.getFd());
                 final String supportedLocalesStr =
-                        TextClassifierImplNative.getLocales(modelFd.getFd());
+                        AnnotatorModel.getLocales(modelFd.getFd());
                 if (supportedLocalesStr.isEmpty()) {
                     Log.d(DEFAULT_LOG_TAG, "Ignoring " + file.getAbsolutePath());
                     return null;
@@ -676,7 +678,7 @@
         public static List<LabeledIntent> create(
                 Context context,
                 @Nullable Instant referenceTime,
-                TextClassifierImplNative.ClassificationResult classification,
+                AnnotatorModel.ClassificationResult classification,
                 String text) {
             final String type = classification.getCollection().trim().toLowerCase(Locale.ENGLISH);
             text = text.trim();
diff --git a/core/java/android/view/textclassifier/TextClassifierImplNative.java b/core/java/android/view/textclassifier/TextClassifierImplNative.java
deleted file mode 100644
index 3d4c8f2..0000000
--- a/core/java/android/view/textclassifier/TextClassifierImplNative.java
+++ /dev/null
@@ -1,301 +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.view.textclassifier;
-
-import android.content.res.AssetFileDescriptor;
-
-/**
- * Java wrapper for TextClassifier native library interface. This library is used for detecting
- * entities in text.
- */
-final class TextClassifierImplNative {
-
-    static {
-        System.loadLibrary("textclassifier");
-    }
-
-    private final long mModelPtr;
-
-    /**
-     * Creates a new instance of TextClassifierImplNative, using the provided model image, given as
-     * a file descriptor.
-     */
-    TextClassifierImplNative(int fd) {
-        mModelPtr = nativeNew(fd);
-        if (mModelPtr == 0L) {
-            throw new IllegalArgumentException("Couldn't initialize TC from file descriptor.");
-        }
-    }
-
-    /**
-     * Creates a new instance of TextClassifierImplNative, using the provided model image, given as
-     * a file path.
-     */
-    TextClassifierImplNative(String path) {
-        mModelPtr = nativeNewFromPath(path);
-        if (mModelPtr == 0L) {
-            throw new IllegalArgumentException("Couldn't initialize TC from given file.");
-        }
-    }
-
-    /**
-     * Creates a new instance of TextClassifierImplNative, using the provided model image, given as
-     * an AssetFileDescriptor.
-     */
-    TextClassifierImplNative(AssetFileDescriptor afd) {
-        mModelPtr = nativeNewFromAssetFileDescriptor(afd, afd.getStartOffset(), afd.getLength());
-        if (mModelPtr == 0L) {
-            throw new IllegalArgumentException(
-                    "Couldn't initialize TC from given AssetFileDescriptor");
-        }
-    }
-
-    /**
-     * Given a string context and current selection, computes the SmartSelection suggestion.
-     *
-     * <p>The begin and end are character indices into the context UTF8 string. selectionBegin is
-     * the character index where the selection begins, and selectionEnd is the index of one
-     * character past the selection span.
-     *
-     * <p>The return value is an array of two ints: suggested selection beginning and end, with the
-     * same semantics as the input selectionBeginning and selectionEnd.
-     */
-    public int[] suggestSelection(
-            String context, int selectionBegin, int selectionEnd, SelectionOptions options) {
-        return nativeSuggestSelection(mModelPtr, context, selectionBegin, selectionEnd, options);
-    }
-
-    /**
-     * Given a string context and current selection, classifies the type of the selected text.
-     *
-     * <p>The begin and end params are character indices in the context string.
-     *
-     * <p>Returns an array of ClassificationResult objects with the probability scores for different
-     * collections.
-     */
-    public ClassificationResult[] classifyText(
-            String context, int selectionBegin, int selectionEnd, ClassificationOptions options) {
-        return nativeClassifyText(mModelPtr, context, selectionBegin, selectionEnd, options);
-    }
-
-    /**
-     * Annotates given input text. The annotations should cover the whole input context except for
-     * whitespaces, and are sorted by their position in the context string.
-     */
-    public AnnotatedSpan[] annotate(String text, AnnotationOptions options) {
-        return nativeAnnotate(mModelPtr, text, options);
-    }
-
-    /** Frees up the allocated memory. */
-    public void close() {
-        nativeClose(mModelPtr);
-    }
-
-    /** Returns a comma separated list of locales supported by the model as BCP 47 tags. */
-    public static String getLocales(int fd) {
-        return nativeGetLocales(fd);
-    }
-
-    /** Returns the version of the model. */
-    public static int getVersion(int fd) {
-        return nativeGetVersion(fd);
-    }
-
-    /** Represents a datetime parsing result from classifyText calls. */
-    public static final class DatetimeResult {
-        static final int GRANULARITY_YEAR = 0;
-        static final int GRANULARITY_MONTH = 1;
-        static final int GRANULARITY_WEEK = 2;
-        static final int GRANULARITY_DAY = 3;
-        static final int GRANULARITY_HOUR = 4;
-        static final int GRANULARITY_MINUTE = 5;
-        static final int GRANULARITY_SECOND = 6;
-
-        private final long mTimeMsUtc;
-        private final int mGranularity;
-
-        DatetimeResult(long timeMsUtc, int granularity) {
-            mGranularity = granularity;
-            mTimeMsUtc = timeMsUtc;
-        }
-
-        public long getTimeMsUtc() {
-            return mTimeMsUtc;
-        }
-
-        public int getGranularity() {
-            return mGranularity;
-        }
-    }
-
-    /** Represents a result of classifyText method call. */
-    public static final class ClassificationResult {
-        private final String mCollection;
-        private final float mScore;
-        private final DatetimeResult mDatetimeResult;
-
-        ClassificationResult(
-                String collection, float score, DatetimeResult datetimeResult) {
-            mCollection = collection;
-            mScore = score;
-            mDatetimeResult = datetimeResult;
-        }
-
-        public String getCollection() {
-            if (mCollection.equals(TextClassifier.TYPE_DATE) && mDatetimeResult != null) {
-                switch (mDatetimeResult.getGranularity()) {
-                    case DatetimeResult.GRANULARITY_HOUR:
-                        // fall through
-                    case DatetimeResult.GRANULARITY_MINUTE:
-                        // fall through
-                    case DatetimeResult.GRANULARITY_SECOND:
-                        return TextClassifier.TYPE_DATE_TIME;
-                    default:
-                        return TextClassifier.TYPE_DATE;
-                }
-            }
-            return mCollection;
-        }
-
-        public float getScore() {
-            return mScore;
-        }
-
-        public DatetimeResult getDatetimeResult() {
-            return mDatetimeResult;
-        }
-    }
-
-    /** Represents a result of Annotate call. */
-    public static final class AnnotatedSpan {
-        private final int mStartIndex;
-        private final int mEndIndex;
-        private final ClassificationResult[] mClassification;
-
-        AnnotatedSpan(
-                int startIndex, int endIndex, ClassificationResult[] classification) {
-            mStartIndex = startIndex;
-            mEndIndex = endIndex;
-            mClassification = classification;
-        }
-
-        public int getStartIndex() {
-            return mStartIndex;
-        }
-
-        public int getEndIndex() {
-            return mEndIndex;
-        }
-
-        public ClassificationResult[] getClassification() {
-            return mClassification;
-        }
-    }
-
-    /** Represents options for the suggestSelection call. */
-    public static final class SelectionOptions {
-        private final String mLocales;
-
-        SelectionOptions(String locales) {
-            mLocales = locales;
-        }
-
-        public String getLocales() {
-            return mLocales;
-        }
-    }
-
-    /** Represents options for the classifyText call. */
-    public static final class ClassificationOptions {
-        private final long mReferenceTimeMsUtc;
-        private final String mReferenceTimezone;
-        private final String mLocales;
-
-        ClassificationOptions(long referenceTimeMsUtc, String referenceTimezone, String locale) {
-            mReferenceTimeMsUtc = referenceTimeMsUtc;
-            mReferenceTimezone = referenceTimezone;
-            mLocales = locale;
-        }
-
-        public long getReferenceTimeMsUtc() {
-            return mReferenceTimeMsUtc;
-        }
-
-        public String getReferenceTimezone() {
-            return mReferenceTimezone;
-        }
-
-        public String getLocale() {
-            return mLocales;
-        }
-    }
-
-    /** Represents options for the Annotate call. */
-    public static final class AnnotationOptions {
-        private final long mReferenceTimeMsUtc;
-        private final String mReferenceTimezone;
-        private final String mLocales;
-
-        AnnotationOptions(long referenceTimeMsUtc, String referenceTimezone, String locale) {
-            mReferenceTimeMsUtc = referenceTimeMsUtc;
-            mReferenceTimezone = referenceTimezone;
-            mLocales = locale;
-        }
-
-        public long getReferenceTimeMsUtc() {
-            return mReferenceTimeMsUtc;
-        }
-
-        public String getReferenceTimezone() {
-            return mReferenceTimezone;
-        }
-
-        public String getLocale() {
-            return mLocales;
-        }
-    }
-
-    private static native long nativeNew(int fd);
-
-    private static native long nativeNewFromPath(String path);
-
-    private static native long nativeNewFromAssetFileDescriptor(
-            AssetFileDescriptor afd, long offset, long size);
-
-    private static native int[] nativeSuggestSelection(
-            long context,
-            String text,
-            int selectionBegin,
-            int selectionEnd,
-            SelectionOptions options);
-
-    private static native ClassificationResult[] nativeClassifyText(
-            long context,
-            String text,
-            int selectionBegin,
-            int selectionEnd,
-            ClassificationOptions options);
-
-    private static native AnnotatedSpan[] nativeAnnotate(
-            long context, String text, AnnotationOptions options);
-
-    private static native void nativeClose(long context);
-
-    private static native String nativeGetLocales(int fd);
-
-    private static native int nativeGetVersion(int fd);
-}
diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java
index ae6a2fd..23d1237 100644
--- a/core/java/android/webkit/CookieManager.java
+++ b/core/java/android/webkit/CookieManager.java
@@ -25,6 +25,13 @@
  * Cookies are manipulated according to RFC2109.
  */
 public abstract class CookieManager {
+    /**
+     * @deprecated This class should not be constructed by applications, use {@link #getInstance}
+     * instead to fetch the singleton instance.
+     */
+    // TODO(ntfschr): mark this as @SystemApi after a year.
+    @Deprecated
+    public CookieManager() {}
 
     @Override
     protected Object clone() throws CloneNotSupportedException {
diff --git a/core/java/android/webkit/RenderProcessGoneDetail.java b/core/java/android/webkit/RenderProcessGoneDetail.java
index 0843e26..9beeaa5 100644
--- a/core/java/android/webkit/RenderProcessGoneDetail.java
+++ b/core/java/android/webkit/RenderProcessGoneDetail.java
@@ -22,6 +22,13 @@
  **/
 public abstract class RenderProcessGoneDetail {
     /**
+     * @deprecated This class should not be constructed by applications.
+     */
+    // TODO(ntfschr): mark this as @SystemApi after a year.
+    @Deprecated
+    public RenderProcessGoneDetail() {}
+
+    /**
      * Indicates whether the render process was observed to crash, or whether
      * it was killed by the system.
      *
diff --git a/core/java/android/webkit/SafeBrowsingResponse.java b/core/java/android/webkit/SafeBrowsingResponse.java
index 7839a00..ca33a0c 100644
--- a/core/java/android/webkit/SafeBrowsingResponse.java
+++ b/core/java/android/webkit/SafeBrowsingResponse.java
@@ -27,6 +27,12 @@
  * {@link android.webkit.WebView#getSafeBrowsingPrivacyPolicyUrl()}.
  */
 public abstract class SafeBrowsingResponse {
+    /**
+     * @deprecated This class should not be constructed by applications.
+     */
+    // TODO(ntfschr): mark this as @SystemApi after a year.
+    @Deprecated
+    public SafeBrowsingResponse() {}
 
     /**
      * Display the default interstitial.
diff --git a/core/java/android/webkit/ServiceWorkerController.java b/core/java/android/webkit/ServiceWorkerController.java
index 3517c74..d7e0715 100644
--- a/core/java/android/webkit/ServiceWorkerController.java
+++ b/core/java/android/webkit/ServiceWorkerController.java
@@ -38,6 +38,14 @@
 public abstract class ServiceWorkerController {
 
     /**
+     * @deprecated This class should not be constructed by applications, use {@link #getInstance()}
+     * instead to fetch the singleton instance.
+     */
+    // TODO(ntfschr): mark this as @SystemApi after a year.
+    @Deprecated
+    public ServiceWorkerController() {}
+
+    /**
      * Returns the default ServiceWorkerController instance. At present there is
      * only one ServiceWorkerController instance for all WebView instances,
      * however this restriction may be relaxed in the future.
diff --git a/core/java/android/webkit/TracingController.java b/core/java/android/webkit/TracingController.java
index 30f465c..9908182 100644
--- a/core/java/android/webkit/TracingController.java
+++ b/core/java/android/webkit/TracingController.java
@@ -43,6 +43,13 @@
  * </pre></p>
  */
 public abstract class TracingController {
+    /**
+     * @deprecated This class should not be constructed by applications, use {@link #getInstance}
+     * instead to fetch the singleton instance.
+     */
+    // TODO(ntfschr): mark this as @SystemApi after a year.
+    @Deprecated
+    public TracingController() {}
 
     /**
      * Returns the default TracingController instance. At present there is
diff --git a/core/java/android/webkit/WebViewDatabase.java b/core/java/android/webkit/WebViewDatabase.java
index f6166c5..f346c60 100644
--- a/core/java/android/webkit/WebViewDatabase.java
+++ b/core/java/android/webkit/WebViewDatabase.java
@@ -31,6 +31,14 @@
  */
 public abstract class WebViewDatabase {
     /**
+     * @deprecated This class should not be constructed by applications, use {@link
+     * #getInstance(Context)} instead to fetch the singleton instance.
+     */
+    // TODO(ntfschr): mark this as @SystemApi after a year.
+    @Deprecated
+    public WebViewDatabase() {}
+
+    /**
      * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
      */
     protected static final String LOGTAG = "webviewdatabase";
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 8dd30f6..9d74c98 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -388,7 +388,8 @@
                 com.android.internal.R.bool.config_enableHapticTextHandle);
 
         if (FLAG_USE_MAGNIFIER) {
-            mMagnifierAnimator = new MagnifierMotionAnimator(new Magnifier(mTextView));
+            final Magnifier magnifier = new Magnifier.Builder(mTextView).build();
+            mMagnifierAnimator = new MagnifierMotionAnimator(magnifier);
         }
     }
 
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 0fef9a5..12cc54d 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -1338,7 +1338,9 @@
             return;
         }
         if (matrix == null) {
-            mDrawable.setBounds(0, 0, getWidth(), getHeight());
+            final int vwidth = getWidth() - mPaddingLeft - mPaddingRight;
+            final int vheight = getHeight() - mPaddingTop - mPaddingBottom;
+            mDrawable.setBounds(0, 0, vwidth, vheight);
         } else {
             mDrawable.setBounds(0, 0, mDrawableWidth, mDrawableHeight);
             if (mDrawMatrix == null) {
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java
index 8e2786d..16ddd0f 100644
--- a/core/java/android/widget/Magnifier.java
+++ b/core/java/android/widget/Magnifier.java
@@ -119,8 +119,9 @@
      *
      * @param view the view for which this magnifier is attached
      *
-     * @see Builder
+     * @deprecated Please use {@link Builder} instead
      */
+    @Deprecated
     public Magnifier(@NonNull View view) {
         this(new Builder(view));
     }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index bbfac44..f95b3ce 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -321,6 +321,12 @@
  * @attr ref android.R.styleable#TextView_autoSizeMaxTextSize
  * @attr ref android.R.styleable#TextView_autoSizeStepGranularity
  * @attr ref android.R.styleable#TextView_autoSizePresetSizes
+ * @attr ref android.R.styleable#TextView_textCursorDrawable
+ * @attr ref android.R.styleable#TextView_textSelectHandle
+ * @attr ref android.R.styleable#TextView_textSelectHandleLeft
+ * @attr ref android.R.styleable#TextView_textSelectHandleRight
+ * @attr ref android.R.styleable#TextView_allowUndo
+ * @attr ref android.R.styleable#TextView_enabled
  */
 @RemoteView
 public class TextView extends View implements ViewTreeObserver.OnPreDrawListener {
diff --git a/core/java/com/android/internal/app/procstats/IProcessStats.aidl b/core/java/com/android/internal/app/procstats/IProcessStats.aidl
index 44867c7..0c203ab 100644
--- a/core/java/com/android/internal/app/procstats/IProcessStats.aidl
+++ b/core/java/com/android/internal/app/procstats/IProcessStats.aidl
@@ -24,4 +24,14 @@
     byte[] getCurrentStats(out List<ParcelFileDescriptor> historic);
     ParcelFileDescriptor getStatsOverTime(long minTime);
     int getCurrentMemoryState();
+
+    /**
+     * Get stats committed after highWaterMarkMs
+     * @param highWaterMarkMs Report stats committed after this time.
+     * @param section Integer mask to indicate which sections to include in the stats.
+     * @param doAggregate Whether to aggregate the stats or keep them separated.
+     * @param List of Files of individual commits in protobuf binary or one that is merged from them.
+     */
+     long getCommittedStats(long highWaterMarkMs, int section, boolean doAggregate,
+        out List<ParcelFileDescriptor> committedStats);
 }
diff --git a/core/java/com/android/internal/app/procstats/ProcessStats.java b/core/java/com/android/internal/app/procstats/ProcessStats.java
index f6e99ba..e7ac566 100644
--- a/core/java/com/android/internal/app/procstats/ProcessStats.java
+++ b/core/java/com/android/internal/app/procstats/ProcessStats.java
@@ -158,6 +158,25 @@
             STATE_CACHED_ACTIVITY_CLIENT, STATE_CACHED_EMPTY
     };
 
+    // Should report process stats.
+    public static final int REPORT_PROC_STATS = 0x01;
+    // Should report package process stats.
+    public static final int REPORT_PKG_PROC_STATS = 0x02;
+    // Should report package service stats.
+    public static final int REPORT_PKG_SVC_STATS = 0x04;
+    // Should report package association stats.
+    public static final int REPORT_PKG_ASC_STATS = 0x08;
+    // Should report package stats.
+    public static final int REPORT_PKG_STATS = 0x0E;
+    // Should report all stats.
+    public static final int REPORT_ALL = 0x0F;
+
+    public static final int[] OPTIONS =
+            {REPORT_PROC_STATS, REPORT_PKG_PROC_STATS, REPORT_PKG_SVC_STATS, REPORT_PKG_ASC_STATS,
+                    REPORT_PKG_STATS, REPORT_ALL};
+    public static final String[] OPTIONS_STR =
+            {"proc", "pkg-proc", "pkg-svc", "pkg-asc", "pkg-all", "all"};
+
     // Current version of the parcel format.
     private static final int PARCEL_VERSION = 34;
     // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
@@ -1412,7 +1431,7 @@
     }
 
     public void dumpLocked(PrintWriter pw, String reqPackage, long now, boolean dumpSummary,
-            boolean dumpDetails, boolean dumpAll, boolean activeOnly) {
+            boolean dumpDetails, boolean dumpAll, boolean activeOnly, int section) {
         long totalTime = DumpUtils.dumpSingleTime(null, null, mMemFactorDurations, mMemFactor,
                 mStartTime, now);
         boolean sepNeeded = false;
@@ -1421,176 +1440,205 @@
             mSysMemUsage.dump(pw, "  ", ALL_SCREEN_ADJ, ALL_MEM_ADJ);
             sepNeeded = true;
         }
-        ArrayMap<String, SparseArray<LongSparseArray<PackageState>>> pkgMap = mPackages.getMap();
         boolean printedHeader = false;
-        for (int ip=0; ip<pkgMap.size(); ip++) {
-            final String pkgName = pkgMap.keyAt(ip);
-            final SparseArray<LongSparseArray<PackageState>> uids = pkgMap.valueAt(ip);
-            for (int iu=0; iu<uids.size(); iu++) {
-                final int uid = uids.keyAt(iu);
-                final LongSparseArray<PackageState> vpkgs = uids.valueAt(iu);
-                for (int iv=0; iv<vpkgs.size(); iv++) {
-                    final long vers = vpkgs.keyAt(iv);
-                    final PackageState pkgState = vpkgs.valueAt(iv);
-                    final int NPROCS = pkgState.mProcesses.size();
-                    final int NSRVS = pkgState.mServices.size();
-                    final int NASCS = pkgState.mAssociations.size();
-                    final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName);
-                    if (!pkgMatch) {
-                        boolean procMatch = false;
-                        for (int iproc=0; iproc<NPROCS; iproc++) {
-                            ProcessState proc = pkgState.mProcesses.valueAt(iproc);
-                            if (reqPackage.equals(proc.getName())) {
-                                procMatch = true;
-                                break;
+        if ((section & REPORT_PKG_STATS) != 0) {
+            ArrayMap<String, SparseArray<LongSparseArray<PackageState>>> pkgMap =
+                    mPackages.getMap();
+            for (int ip = 0; ip < pkgMap.size(); ip++) {
+                final String pkgName = pkgMap.keyAt(ip);
+                final SparseArray<LongSparseArray<PackageState>> uids = pkgMap.valueAt(ip);
+                for (int iu = 0; iu < uids.size(); iu++) {
+                    final int uid = uids.keyAt(iu);
+                    final LongSparseArray<PackageState> vpkgs = uids.valueAt(iu);
+                    for (int iv = 0; iv < vpkgs.size(); iv++) {
+                        final long vers = vpkgs.keyAt(iv);
+                        final PackageState pkgState = vpkgs.valueAt(iv);
+                        final int NPROCS = pkgState.mProcesses.size();
+                        final int NSRVS = pkgState.mServices.size();
+                        final int NASCS = pkgState.mAssociations.size();
+                        final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName);
+                        if (!pkgMatch) {
+                            boolean procMatch = false;
+                            for (int iproc = 0; iproc < NPROCS; iproc++) {
+                                ProcessState proc = pkgState.mProcesses.valueAt(iproc);
+                                if (reqPackage.equals(proc.getName())) {
+                                    procMatch = true;
+                                    break;
+                                }
                             }
-                        }
-                        if (!procMatch) {
-                            continue;
-                        }
-                    }
-                    if (NPROCS > 0 || NSRVS > 0 || NASCS > 0) {
-                        if (!printedHeader) {
-                            if (sepNeeded) pw.println();
-                            pw.println("Per-Package Stats:");
-                            printedHeader = true;
-                            sepNeeded = true;
-                        }
-                        pw.print("  * "); pw.print(pkgName); pw.print(" / ");
-                                UserHandle.formatUid(pw, uid); pw.print(" / v");
-                                pw.print(vers); pw.println(":");
-                    }
-                    if (!dumpSummary || dumpAll) {
-                        for (int iproc=0; iproc<NPROCS; iproc++) {
-                            ProcessState proc = pkgState.mProcesses.valueAt(iproc);
-                            if (!pkgMatch && !reqPackage.equals(proc.getName())) {
+                            if (!procMatch) {
                                 continue;
                             }
-                            if (activeOnly && !proc.isInUse()) {
-                                pw.print("      (Not active: ");
-                                        pw.print(pkgState.mProcesses.keyAt(iproc)); pw.println(")");
-                                continue;
+                        }
+                        if (NPROCS > 0 || NSRVS > 0 || NASCS > 0) {
+                            if (!printedHeader) {
+                                if (sepNeeded) pw.println();
+                                pw.println("Per-Package Stats:");
+                                printedHeader = true;
+                                sepNeeded = true;
                             }
-                            pw.print("      Process ");
-                            pw.print(pkgState.mProcesses.keyAt(iproc));
-                            if (proc.getCommonProcess().isMultiPackage()) {
-                                pw.print(" (multi, ");
-                            } else {
-                                pw.print(" (unique, ");
-                            }
-                            pw.print(proc.getDurationsBucketCount());
-                            pw.print(" entries)");
+                            pw.print("  * ");
+                            pw.print(pkgName);
+                            pw.print(" / ");
+                            UserHandle.formatUid(pw, uid);
+                            pw.print(" / v");
+                            pw.print(vers);
                             pw.println(":");
-                            proc.dumpProcessState(pw, "        ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
-                                    ALL_PROC_STATES, now);
-                            proc.dumpPss(pw, "        ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
-                                    ALL_PROC_STATES, now);
-                            proc.dumpInternalLocked(pw, "        ", dumpAll);
                         }
-                    } else {
-                        ArrayList<ProcessState> procs = new ArrayList<ProcessState>();
-                        for (int iproc=0; iproc<NPROCS; iproc++) {
-                            ProcessState proc = pkgState.mProcesses.valueAt(iproc);
-                            if (!pkgMatch && !reqPackage.equals(proc.getName())) {
-                                continue;
+                        if ((section & REPORT_PKG_PROC_STATS) != 0) {
+                            if (!dumpSummary || dumpAll) {
+                                for (int iproc = 0; iproc < NPROCS; iproc++) {
+                                    ProcessState proc = pkgState.mProcesses.valueAt(iproc);
+                                    if (!pkgMatch && !reqPackage.equals(proc.getName())) {
+                                        continue;
+                                    }
+                                    if (activeOnly && !proc.isInUse()) {
+                                        pw.print("      (Not active: ");
+                                        pw.print(pkgState.mProcesses.keyAt(iproc));
+                                        pw.println(")");
+                                        continue;
+                                    }
+                                    pw.print("      Process ");
+                                    pw.print(pkgState.mProcesses.keyAt(iproc));
+                                    if (proc.getCommonProcess().isMultiPackage()) {
+                                        pw.print(" (multi, ");
+                                    } else {
+                                        pw.print(" (unique, ");
+                                    }
+                                    pw.print(proc.getDurationsBucketCount());
+                                    pw.print(" entries)");
+                                    pw.println(":");
+                                    proc.dumpProcessState(pw, "        ", ALL_SCREEN_ADJ,
+                                            ALL_MEM_ADJ,
+                                            ALL_PROC_STATES, now);
+                                    proc.dumpPss(pw, "        ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
+                                            ALL_PROC_STATES, now);
+                                    proc.dumpInternalLocked(pw, "        ", dumpAll);
+                                }
+                            } else {
+                                ArrayList<ProcessState> procs = new ArrayList<ProcessState>();
+                                for (int iproc = 0; iproc < NPROCS; iproc++) {
+                                    ProcessState proc = pkgState.mProcesses.valueAt(iproc);
+                                    if (!pkgMatch && !reqPackage.equals(proc.getName())) {
+                                        continue;
+                                    }
+                                    if (activeOnly && !proc.isInUse()) {
+                                        continue;
+                                    }
+                                    procs.add(proc);
+                                }
+                                DumpUtils.dumpProcessSummaryLocked(pw, "      ", "Prc ", procs,
+                                        ALL_SCREEN_ADJ, ALL_MEM_ADJ, NON_CACHED_PROC_STATES,
+                                        now, totalTime);
                             }
-                            if (activeOnly && !proc.isInUse()) {
-                                continue;
+                        }
+                        if ((section & REPORT_PKG_SVC_STATS) != 0) {
+                            for (int isvc = 0; isvc < NSRVS; isvc++) {
+                                ServiceState svc = pkgState.mServices.valueAt(isvc);
+                                if (!pkgMatch && !reqPackage.equals(svc.getProcessName())) {
+                                    continue;
+                                }
+                                if (activeOnly && !svc.isInUse()) {
+                                    pw.print("      (Not active service: ");
+                                    pw.print(pkgState.mServices.keyAt(isvc));
+                                    pw.println(")");
+                                    continue;
+                                }
+                                if (dumpAll) {
+                                    pw.print("      Service ");
+                                } else {
+                                    pw.print("      * Svc ");
+                                }
+                                pw.print(pkgState.mServices.keyAt(isvc));
+                                pw.println(":");
+                                pw.print("        Process: ");
+                                pw.println(svc.getProcessName());
+                                svc.dumpStats(pw, "        ", "          ", "    ",
+                                        now, totalTime, dumpSummary, dumpAll);
                             }
-                            procs.add(proc);
                         }
-                        DumpUtils.dumpProcessSummaryLocked(pw, "      ", "Prc ", procs,
-                                ALL_SCREEN_ADJ, ALL_MEM_ADJ, NON_CACHED_PROC_STATES,
-                                now, totalTime);
-                    }
-                    for (int isvc=0; isvc<NSRVS; isvc++) {
-                        ServiceState svc = pkgState.mServices.valueAt(isvc);
-                        if (!pkgMatch && !reqPackage.equals(svc.getProcessName())) {
-                            continue;
+                        if ((section & REPORT_PKG_ASC_STATS) != 0) {
+                            for (int iasc = 0; iasc < NASCS; iasc++) {
+                                AssociationState asc = pkgState.mAssociations.valueAt(iasc);
+                                if (!pkgMatch && !reqPackage.equals(asc.getProcessName())) {
+                                    continue;
+                                }
+                                if (activeOnly && !asc.isInUse()) {
+                                    pw.print("      (Not active association: ");
+                                    pw.print(pkgState.mAssociations.keyAt(iasc));
+                                    pw.println(")");
+                                    continue;
+                                }
+                                if (dumpAll) {
+                                    pw.print("      Association ");
+                                } else {
+                                    pw.print("      * Asc ");
+                                }
+                                pw.print(pkgState.mAssociations.keyAt(iasc));
+                                pw.println(":");
+                                pw.print("        Process: ");
+                                pw.println(asc.getProcessName());
+                                asc.dumpStats(pw, "        ", "          ", "    ",
+                                        now, totalTime, dumpDetails, dumpAll);
+                            }
                         }
-                        if (activeOnly && !svc.isInUse()) {
-                            pw.print("      (Not active service: ");
-                                    pw.print(pkgState.mServices.keyAt(isvc)); pw.println(")");
-                            continue;
-                        }
-                        if (dumpAll) {
-                            pw.print("      Service ");
-                        } else {
-                            pw.print("      * Svc ");
-                        }
-                        pw.print(pkgState.mServices.keyAt(isvc));
-                        pw.println(":");
-                        pw.print("        Process: "); pw.println(svc.getProcessName());
-                        svc.dumpStats(pw, "        ", "          ", "    ",
-                                now, totalTime, dumpSummary, dumpAll);
-                    }
-                    for (int iasc=0; iasc<NASCS; iasc++) {
-                        AssociationState asc = pkgState.mAssociations.valueAt(iasc);
-                        if (!pkgMatch && !reqPackage.equals(asc.getProcessName())) {
-                            continue;
-                        }
-                        if (activeOnly && !asc.isInUse()) {
-                            pw.print("      (Not active association: ");
-                            pw.print(pkgState.mAssociations.keyAt(iasc)); pw.println(")");
-                            continue;
-                        }
-                        if (dumpAll) {
-                            pw.print("      Association ");
-                        } else {
-                            pw.print("      * Asc ");
-                        }
-                        pw.print(pkgState.mAssociations.keyAt(iasc));
-                        pw.println(":");
-                        pw.print("        Process: "); pw.println(asc.getProcessName());
-                        asc.dumpStats(pw, "        ", "          ", "    ",
-                                now, totalTime, dumpDetails, dumpAll);
                     }
                 }
             }
         }
 
-        ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
-        printedHeader = false;
-        int numShownProcs = 0, numTotalProcs = 0;
-        for (int ip=0; ip<procMap.size(); ip++) {
-            String procName = procMap.keyAt(ip);
-            SparseArray<ProcessState> uids = procMap.valueAt(ip);
-            for (int iu=0; iu<uids.size(); iu++) {
-                int uid = uids.keyAt(iu);
-                numTotalProcs++;
-                final ProcessState proc = uids.valueAt(iu);
-                if (!proc.hasAnyData()) {
-                    continue;
+        if ((section & REPORT_PROC_STATS) != 0) {
+            ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
+            printedHeader = false;
+            int numShownProcs = 0, numTotalProcs = 0;
+            for (int ip = 0; ip < procMap.size(); ip++) {
+                String procName = procMap.keyAt(ip);
+                SparseArray<ProcessState> uids = procMap.valueAt(ip);
+                for (int iu = 0; iu < uids.size(); iu++) {
+                    int uid = uids.keyAt(iu);
+                    numTotalProcs++;
+                    final ProcessState proc = uids.valueAt(iu);
+                    if (!proc.hasAnyData()) {
+                        continue;
+                    }
+                    if (!proc.isMultiPackage()) {
+                        continue;
+                    }
+                    if (reqPackage != null && !reqPackage.equals(procName)
+                            && !reqPackage.equals(proc.getPackage())) {
+                        continue;
+                    }
+                    numShownProcs++;
+                    if (sepNeeded) {
+                        pw.println();
+                    }
+                    sepNeeded = true;
+                    if (!printedHeader) {
+                        pw.println("Multi-Package Common Processes:");
+                        printedHeader = true;
+                    }
+                    if (activeOnly && !proc.isInUse()) {
+                        pw.print("      (Not active: ");
+                        pw.print(procName);
+                        pw.println(")");
+                        continue;
+                    }
+                    pw.print("  * ");
+                    pw.print(procName);
+                    pw.print(" / ");
+                    UserHandle.formatUid(pw, uid);
+                    pw.print(" (");
+                    pw.print(proc.getDurationsBucketCount());
+                    pw.print(" entries)");
+                    pw.println(":");
+                    proc.dumpProcessState(pw, "        ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
+                            ALL_PROC_STATES, now);
+                    proc.dumpPss(pw, "        ", ALL_SCREEN_ADJ, ALL_MEM_ADJ, ALL_PROC_STATES, now);
+                    proc.dumpInternalLocked(pw, "        ", dumpAll);
                 }
-                if (!proc.isMultiPackage()) {
-                    continue;
-                }
-                if (reqPackage != null && !reqPackage.equals(procName)
-                        && !reqPackage.equals(proc.getPackage())) {
-                    continue;
-                }
-                numShownProcs++;
-                if (sepNeeded) {
-                    pw.println();
-                }
-                sepNeeded = true;
-                if (!printedHeader) {
-                    pw.println("Multi-Package Common Processes:");
-                    printedHeader = true;
-                }
-                if (activeOnly && !proc.isInUse()) {
-                    pw.print("      (Not active: "); pw.print(procName); pw.println(")");
-                    continue;
-                }
-                pw.print("  * "); pw.print(procName); pw.print(" / ");
-                        UserHandle.formatUid(pw, uid);
-                        pw.print(" ("); pw.print(proc.getDurationsBucketCount());
-                        pw.print(" entries)"); pw.println(":");
-                proc.dumpProcessState(pw, "        ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
-                        ALL_PROC_STATES, now);
-                proc.dumpPss(pw, "        ", ALL_SCREEN_ADJ, ALL_MEM_ADJ, ALL_PROC_STATES, now);
-                proc.dumpInternalLocked(pw, "        ", dumpAll);
             }
+            pw.print("  Total procs: "); pw.print(numShownProcs);
+            pw.print(" shown of "); pw.print(numTotalProcs); pw.println(" total");
         }
 
         if (dumpAll) {
@@ -1598,8 +1646,7 @@
                 pw.println();
             }
             sepNeeded = true;
-            pw.print("  Total procs: "); pw.print(numShownProcs);
-                    pw.print(" shown of "); pw.print(numTotalProcs); pw.println(" total");
+
             if (mTrackingAssociations.size() > 0) {
                 pw.println();
                 pw.println("Tracking associations:");
@@ -1866,7 +1913,10 @@
         return outProcs;
     }
 
-    public void dumpCheckinLocked(PrintWriter pw, String reqPackage) {
+    /**
+     * Prints checkin style stats dump.
+     */
+    public void dumpCheckinLocked(PrintWriter pw, String reqPackage, int section) {
         final long now = SystemClock.uptimeMillis();
         final ArrayMap<String, SparseArray<LongSparseArray<PackageState>>> pkgMap =
                 mPackages.getMap();
@@ -1895,50 +1945,61 @@
         }
         pw.println();
         pw.print("config,"); pw.println(mRuntime);
-        for (int ip=0; ip<pkgMap.size(); ip++) {
-            final String pkgName = pkgMap.keyAt(ip);
-            if (reqPackage != null && !reqPackage.equals(pkgName)) {
-                continue;
-            }
-            final SparseArray<LongSparseArray<PackageState>> uids = pkgMap.valueAt(ip);
-            for (int iu=0; iu<uids.size(); iu++) {
-                final int uid = uids.keyAt(iu);
-                final LongSparseArray<PackageState> vpkgs = uids.valueAt(iu);
-                for (int iv=0; iv<vpkgs.size(); iv++) {
-                    final long vers = vpkgs.keyAt(iv);
-                    final PackageState pkgState = vpkgs.valueAt(iv);
-                    final int NPROCS = pkgState.mProcesses.size();
-                    final int NSRVS = pkgState.mServices.size();
-                    final int NASCS = pkgState.mAssociations.size();
-                    for (int iproc=0; iproc<NPROCS; iproc++) {
-                        ProcessState proc = pkgState.mProcesses.valueAt(iproc);
-                        proc.dumpPackageProcCheckin(pw, pkgName, uid, vers,
-                                pkgState.mProcesses.keyAt(iproc), now);
-                    }
-                    for (int isvc=0; isvc<NSRVS; isvc++) {
-                        final String serviceName = DumpUtils.collapseString(pkgName,
-                                pkgState.mServices.keyAt(isvc));
-                        final ServiceState svc = pkgState.mServices.valueAt(isvc);
-                        svc.dumpTimesCheckin(pw, pkgName, uid, vers, serviceName, now);
-                    }
-                    for (int iasc=0; iasc<NASCS; iasc++) {
-                        final String associationName = DumpUtils.collapseString(pkgName,
-                                pkgState.mAssociations.keyAt(iasc));
-                        final AssociationState asc = pkgState.mAssociations.valueAt(iasc);
-                        asc.dumpTimesCheckin(pw, pkgName, uid, vers, associationName, now);
+
+        if ((section & REPORT_PKG_STATS) != 0) {
+            for (int ip = 0; ip < pkgMap.size(); ip++) {
+                final String pkgName = pkgMap.keyAt(ip);
+                if (reqPackage != null && !reqPackage.equals(pkgName)) {
+                    continue;
+                }
+                final SparseArray<LongSparseArray<PackageState>> uids = pkgMap.valueAt(ip);
+                for (int iu = 0; iu < uids.size(); iu++) {
+                    final int uid = uids.keyAt(iu);
+                    final LongSparseArray<PackageState> vpkgs = uids.valueAt(iu);
+                    for (int iv = 0; iv < vpkgs.size(); iv++) {
+                        final long vers = vpkgs.keyAt(iv);
+                        final PackageState pkgState = vpkgs.valueAt(iv);
+                        final int NPROCS = pkgState.mProcesses.size();
+                        final int NSRVS = pkgState.mServices.size();
+                        final int NASCS = pkgState.mAssociations.size();
+                        if ((section & REPORT_PKG_PROC_STATS) != 0) {
+                            for (int iproc = 0; iproc < NPROCS; iproc++) {
+                                ProcessState proc = pkgState.mProcesses.valueAt(iproc);
+                                proc.dumpPackageProcCheckin(pw, pkgName, uid, vers,
+                                        pkgState.mProcesses.keyAt(iproc), now);
+                            }
+                        }
+                        if ((section & REPORT_PKG_SVC_STATS) != 0) {
+                            for (int isvc = 0; isvc < NSRVS; isvc++) {
+                                final String serviceName = DumpUtils.collapseString(pkgName,
+                                        pkgState.mServices.keyAt(isvc));
+                                final ServiceState svc = pkgState.mServices.valueAt(isvc);
+                                svc.dumpTimesCheckin(pw, pkgName, uid, vers, serviceName, now);
+                            }
+                        }
+                        if ((section & REPORT_PKG_ASC_STATS) != 0) {
+                            for (int iasc = 0; iasc < NASCS; iasc++) {
+                                final String associationName = DumpUtils.collapseString(pkgName,
+                                        pkgState.mAssociations.keyAt(iasc));
+                                final AssociationState asc = pkgState.mAssociations.valueAt(iasc);
+                                asc.dumpTimesCheckin(pw, pkgName, uid, vers, associationName, now);
+                            }
+                        }
                     }
                 }
             }
         }
 
-        ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
-        for (int ip=0; ip<procMap.size(); ip++) {
-            String procName = procMap.keyAt(ip);
-            SparseArray<ProcessState> uids = procMap.valueAt(ip);
-            for (int iu=0; iu<uids.size(); iu++) {
-                final int uid = uids.keyAt(iu);
-                final ProcessState procState = uids.valueAt(iu);
-                procState.dumpProcCheckin(pw, procName, uid, now);
+        if ((section & REPORT_PROC_STATS) != 0) {
+            ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
+            for (int ip = 0; ip < procMap.size(); ip++) {
+                String procName = procMap.keyAt(ip);
+                SparseArray<ProcessState> uids = procMap.valueAt(ip);
+                for (int iu = 0; iu < uids.size(); iu++) {
+                    final int uid = uids.keyAt(iu);
+                    final ProcessState procState = uids.valueAt(iu);
+                    procState.dumpProcCheckin(pw, procName, uid, now);
+                }
             }
         }
         pw.print("total");
@@ -2013,9 +2074,10 @@
         }
     }
 
-    public void writeToProto(ProtoOutputStream proto, long fieldId, long now) {
-        final long token = proto.start(fieldId);
-
+    /**
+     * Writes to ProtoOutputStream.
+     */
+    public void writeToProto(ProtoOutputStream proto, long now, int section) {
         proto.write(ProcessStatsSectionProto.START_REALTIME_MS, mTimePeriodStartRealtime);
         proto.write(ProcessStatsSectionProto.END_REALTIME_MS,
                 mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime);
@@ -2024,15 +2086,15 @@
         proto.write(ProcessStatsSectionProto.RUNTIME, mRuntime);
         proto.write(ProcessStatsSectionProto.HAS_SWAPPED_PSS, mHasSwappedOutPss);
         boolean partial = true;
-        if ((mFlags&FLAG_SHUTDOWN) != 0) {
+        if ((mFlags & FLAG_SHUTDOWN) != 0) {
             proto.write(ProcessStatsSectionProto.STATUS, ProcessStatsSectionProto.STATUS_SHUTDOWN);
             partial = false;
         }
-        if ((mFlags&FLAG_SYSPROPS) != 0) {
+        if ((mFlags & FLAG_SYSPROPS) != 0) {
             proto.write(ProcessStatsSectionProto.STATUS, ProcessStatsSectionProto.STATUS_SYSPROPS);
             partial = false;
         }
-        if ((mFlags&FLAG_COMPLETE) != 0) {
+        if ((mFlags & FLAG_COMPLETE) != 0) {
             proto.write(ProcessStatsSectionProto.STATUS, ProcessStatsSectionProto.STATUS_COMPLETE);
             partial = false;
         }
@@ -2041,31 +2103,34 @@
         }
 
         final ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
-        for (int ip=0; ip<procMap.size(); ip++) {
-            final String procName = procMap.keyAt(ip);
-            final SparseArray<ProcessState> uids = procMap.valueAt(ip);
-            for (int iu=0; iu<uids.size(); iu++) {
-                final int uid = uids.keyAt(iu);
-                final ProcessState procState = uids.valueAt(iu);
-                procState.writeToProto(proto, ProcessStatsSectionProto.PROCESS_STATS, procName,
-                        uid, now);
-            }
-        }
-
-        final ArrayMap<String, SparseArray<LongSparseArray<PackageState>>> pkgMap =
-                mPackages.getMap();
-        for (int ip = 0; ip < pkgMap.size(); ip++) {
-            final SparseArray<LongSparseArray<PackageState>> uids = pkgMap.valueAt(ip);
-            for (int iu = 0; iu < uids.size(); iu++) {
-                final LongSparseArray<PackageState> vers = uids.valueAt(iu);
-                for (int iv = 0; iv < vers.size(); iv++) {
-                    final PackageState pkgState = vers.valueAt(iv);
-                    pkgState.writeToProto(proto, ProcessStatsSectionProto.PACKAGE_STATS, now);
+        if ((section & REPORT_PROC_STATS) != 0) {
+            for (int ip = 0; ip < procMap.size(); ip++) {
+                final String procName = procMap.keyAt(ip);
+                final SparseArray<ProcessState> uids = procMap.valueAt(ip);
+                for (int iu = 0; iu < uids.size(); iu++) {
+                    final int uid = uids.keyAt(iu);
+                    final ProcessState procState = uids.valueAt(iu);
+                    procState.writeToProto(proto, ProcessStatsSectionProto.PROCESS_STATS, procName,
+                            uid, now);
                 }
             }
         }
 
-        proto.end(token);
+        if ((section & REPORT_PKG_STATS) != 0) {
+            final ArrayMap<String, SparseArray<LongSparseArray<PackageState>>> pkgMap =
+                    mPackages.getMap();
+            for (int ip = 0; ip < pkgMap.size(); ip++) {
+                final SparseArray<LongSparseArray<PackageState>> uids = pkgMap.valueAt(ip);
+                for (int iu = 0; iu < uids.size(); iu++) {
+                    final LongSparseArray<PackageState> vers = uids.valueAt(iu);
+                    for (int iv = 0; iv < vers.size(); iv++) {
+                        final PackageState pkgState = vers.valueAt(iv);
+                        pkgState.writeToProto(proto, ProcessStatsSectionProto.PACKAGE_STATS, now,
+                                section);
+                    }
+                }
+            }
+        }
     }
 
     final public static class ProcessStateHolder {
@@ -2110,30 +2175,39 @@
             return as;
         }
 
-        public void writeToProto(ProtoOutputStream proto, long fieldId, long now) {
+        /**
+         * Writes the containing stats into proto, with options to choose smaller sections.
+         */
+        public void writeToProto(ProtoOutputStream proto, long fieldId, long now, int section) {
             final long token = proto.start(fieldId);
 
             proto.write(ProcessStatsPackageProto.PACKAGE, mPackageName);
             proto.write(ProcessStatsPackageProto.UID, mUid);
             proto.write(ProcessStatsPackageProto.VERSION, mVersionCode);
 
-            for (int ip = 0; ip < mProcesses.size(); ip++) {
-                final String procName = mProcesses.keyAt(ip);
-                final ProcessState procState = mProcesses.valueAt(ip);
-                procState.writeToProto(proto, ProcessStatsPackageProto.PROCESS_STATS, procName,
-                        mUid, now);
+            if ((section & ProcessStats.REPORT_PKG_PROC_STATS) != 0) {
+                for (int ip = 0; ip < mProcesses.size(); ip++) {
+                    final String procName = mProcesses.keyAt(ip);
+                    final ProcessState procState = mProcesses.valueAt(ip);
+                    procState.writeToProto(proto, ProcessStatsPackageProto.PROCESS_STATS, procName,
+                            mUid, now);
+                }
             }
 
-            for (int is = 0; is < mServices.size(); is++) {
-                final ServiceState serviceState = mServices.valueAt(is);
-                serviceState.writeToProto(proto, ProcessStatsPackageProto.SERVICE_STATS,
-                        now);
+            if ((section & ProcessStats.REPORT_PKG_SVC_STATS) != 0) {
+                for (int is = 0; is < mServices.size(); is++) {
+                    final ServiceState serviceState = mServices.valueAt(is);
+                    serviceState.writeToProto(proto, ProcessStatsPackageProto.SERVICE_STATS,
+                            now);
+                }
             }
 
-            for (int ia=0; ia<mAssociations.size(); ia++) {
-                final AssociationState ascState = mAssociations.valueAt(ia);
-                ascState.writeToProto(proto, ProcessStatsPackageProto.ASSOCIATION_STATS,
-                        now);
+            if ((section & ProcessStats.REPORT_PKG_ASC_STATS) != 0) {
+                for (int ia = 0; ia < mAssociations.size(); ia++) {
+                    final AssociationState ascState = mAssociations.valueAt(ia);
+                    ascState.writeToProto(proto, ProcessStatsPackageProto.ASSOCIATION_STATS,
+                            now);
+                }
             }
 
             proto.end(token);
diff --git a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
index cb282b6..0080ace 100644
--- a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
+++ b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
@@ -66,13 +66,13 @@
         return !TextUtils.isEmpty(doubleTapSensorType());
     }
 
-    public boolean reachGestureEnabled(int user) {
-        return boolSettingDefaultOn(Settings.Secure.DOZE_REACH_GESTURE, user)
-                && reachGestureAvailable();
+    public boolean wakeLockScreenGestureEnabled(int user) {
+        return boolSettingDefaultOn(Settings.Secure.DOZE_WAKE_LOCK_SCREEN_GESTURE, user)
+                && wakeLockScreenGestureAvailable();
     }
 
-    public boolean reachGestureAvailable() {
-        return !TextUtils.isEmpty(reachSensorType());
+    public boolean wakeLockScreenGestureAvailable() {
+        return !TextUtils.isEmpty(wakeLockScreenSensorType());
     }
 
     public boolean wakeScreenGestureEnabled(int user) {
@@ -92,8 +92,8 @@
         return mContext.getResources().getString(R.string.config_dozeLongPressSensorType);
     }
 
-    public String reachSensorType() {
-        return mContext.getResources().getString(R.string.config_dozeReachSensorType);
+    public String wakeLockScreenSensorType() {
+        return mContext.getResources().getString(R.string.config_dozeWakeLockScreenSensorType);
     }
 
     public String wakeScreenSensorType() {
diff --git a/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
index c32894d..2671781 100644
--- a/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
+++ b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
@@ -28,7 +28,6 @@
 interface IInputMethodPrivilegedOperations {
     void setImeWindowStatus(int vis, int backDisposition);
     void reportStartInput(in IBinder startInputToken);
-    void clearLastInputMethodWindowForTransition();
     IInputContentUriToken createInputContentUriToken(in Uri contentUri, in String packageName);
     void reportFullscreenMode(boolean fullscreen);
     void setInputMethod(String id);
diff --git a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
index f0e8dc5..cdb986a 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
@@ -135,22 +135,6 @@
     }
 
     /**
-     * Calls {@link IInputMethodPrivilegedOperations#clearLastInputMethodWindowForTransition()}.
-     */
-    @AnyThread
-    public void clearLastInputMethodWindowForTransition() {
-        final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
-        if (ops == null) {
-            return;
-        }
-        try {
-            ops.clearLastInputMethodWindowForTransition();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * Calls {@link IInputMethodPrivilegedOperations#createInputContentUriToken(Uri, String)}.
      *
      * @param contentUri Content URI to which a temporary read permission should be granted
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 31f13c3..33b9ff7 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -337,6 +337,9 @@
 
     private final PlatformIdleStateCallback mPlatformIdleStateCallback;
 
+    /**
+     * This handler is running on {@link BackgroundThread}.
+     */
     final class MyHandler extends Handler {
         public MyHandler(Looper looper) {
             super(looper, null, true);
diff --git a/core/java/com/android/internal/os/StoragedUidIoStatsReader.java b/core/java/com/android/internal/os/StoragedUidIoStatsReader.java
new file mode 100644
index 0000000..9b03469
--- /dev/null
+++ b/core/java/com/android/internal/os/StoragedUidIoStatsReader.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.internal.os;
+
+import android.os.StrictMode;
+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.IOException;
+import java.nio.file.Files;
+
+
+/**
+ * Reads /proc/uid_io/stats which has the line format:
+ *
+ * uid: foreground_read_chars foreground_write_chars foreground_read_bytes foreground_write_bytes
+ * background_read_chars background_write_chars background_read_bytes background_write_bytes
+ * foreground_fsync background_fsync
+ *
+ * This provides the number of bytes/chars read/written in foreground/background for each uid.
+ * The file contains a monotonically increasing count of bytes/chars for a single boot.
+ */
+public class StoragedUidIoStatsReader {
+
+    private static final String TAG = StoragedUidIoStatsReader.class.getSimpleName();
+    private static String sUidIoFile = "/proc/uid_io/stats";
+
+    public StoragedUidIoStatsReader() {
+    }
+
+    @VisibleForTesting
+    public StoragedUidIoStatsReader(String file) {
+        sUidIoFile = file;
+    }
+
+    /**
+     * Notifies when new data is available.
+     */
+    public interface Callback {
+
+        /**
+         * Provides data to the client.
+         *
+         * Note: Bytes are I/O events from a storage device. Chars are data requested by syscalls,
+         *   and can be satisfied by caching.
+         */
+        void onUidStorageStats(int uid, long fgCharsRead, long fgCharsWrite, long fgBytesRead,
+                long fgBytesWrite, long bgCharsRead, long bgCharsWrite, long bgBytesRead,
+                long bgBytesWrite, long fgFsync, long bgFsync);
+    }
+
+    /**
+     * Reads the proc file, calling into the callback with raw absolute value of I/O stats
+     * for each UID.
+     *
+     * @param callback The callback to invoke for each line of the proc file.
+     */
+    public void readAbsolute(Callback callback) {
+        final int oldMask = StrictMode.allowThreadDiskReadsMask();
+        File file = new File(sUidIoFile);
+        try (BufferedReader reader = Files.newBufferedReader(file.toPath())) {
+            String line;
+            while ((line = reader.readLine()) != null) {
+                String[] fields = TextUtils.split(line, " ");
+                if (fields.length != 11) {
+                    Slog.e(TAG, "Malformed entry in " + sUidIoFile + ": " + line);
+                    continue;
+                }
+                try {
+                    final String uidStr = fields[0];
+                    final int uid = Integer.parseInt(fields[0], 10);
+                    final long fgCharsRead = Long.parseLong(fields[1], 10);
+                    final long fgCharsWrite = Long.parseLong(fields[2], 10);
+                    final long fgBytesRead = Long.parseLong(fields[3], 10);
+                    final long fgBytesWrite = Long.parseLong(fields[4], 10);
+                    final long bgCharsRead = Long.parseLong(fields[5], 10);
+                    final long bgCharsWrite = Long.parseLong(fields[6], 10);
+                    final long bgBytesRead = Long.parseLong(fields[7], 10);
+                    final long bgBytesWrite = Long.parseLong(fields[8], 10);
+                    final long fgFsync = Long.parseLong(fields[9], 10);
+                    final long bgFsync = Long.parseLong(fields[10], 10);
+                    callback.onUidStorageStats(uid, fgCharsRead, fgCharsWrite, fgBytesRead,
+                            fgBytesWrite, bgCharsRead, bgCharsWrite, bgBytesRead, bgBytesWrite,
+                            fgFsync, bgFsync);
+                } catch (NumberFormatException e) {
+                    Slog.e(TAG, "Could not parse entry in " + sUidIoFile + ": " + e.getMessage());
+                }
+            }
+        } catch (IOException e) {
+            Slog.e(TAG, "Failed to read " + sUidIoFile + ": " + e.getMessage());
+        } finally {
+            StrictMode.setThreadPolicyMask(oldMask);
+        }
+    }
+}
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 927322e..98b7b5d 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -133,15 +133,16 @@
      * if this is the parent, or -1 on error.
      */
     public static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
-          int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
-          int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
-          String packageName) {
+            int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
+            int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
+            String packageName, String[] packagesForUid, String[] visibleVolIds) {
         VM_HOOKS.preFork();
         // Resets nice priority for zygote process.
         resetNicePriority();
         int pid = nativeForkAndSpecialize(
                   uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
-                  fdsToIgnore, startChildZygote, instructionSet, appDataDir, packageName);
+                  fdsToIgnore, startChildZygote, instructionSet, appDataDir, packageName,
+                  packagesForUid, visibleVolIds);
         // Enable tracing as soon as possible for the child process.
         if (pid == 0) {
             Trace.setTracingEnabled(true, runtimeFlags);
@@ -154,9 +155,9 @@
     }
 
     native private static int nativeForkAndSpecialize(int uid, int gid, int[] gids,int runtimeFlags,
-          int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
-          int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
-          String packageName);
+            int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
+            int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
+            String packageName, String[] packagesForUid, String[] visibleVolIds);
 
     /**
      * Called to do any initialization before starting an application.
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 06c41d8..4a94ec4 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -241,7 +241,8 @@
         pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                 parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                 parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.startChildZygote,
-                parsedArgs.instructionSet, parsedArgs.appDataDir, parsedArgs.packageName);
+                parsedArgs.instructionSet, parsedArgs.appDataDir, parsedArgs.packageName,
+                parsedArgs.packagesForUid, parsedArgs.visibleVolIds);
 
         try {
             if (pid == 0) {
@@ -432,6 +433,12 @@
         /** from --package-name */
         String packageName;
 
+        /** from --packages-for-uid */
+        String[] packagesForUid;
+
+        /** from --visible-vols */
+        String[] visibleVolIds;
+
         /**
          * Any args after and including the first non-option arg
          * (or after a '--')
@@ -687,6 +694,10 @@
                         throw new IllegalArgumentException("Duplicate arg specified");
                     }
                     packageName = arg.substring(arg.indexOf('=') + 1);
+                } else if (arg.startsWith("--packages-for-uid=")) {
+                    packagesForUid = arg.substring(arg.indexOf('=') + 1).split(",");
+                } else if (arg.startsWith("--visible-vols=")) {
+                    visibleVolIds = arg.substring(arg.indexOf('=') + 1).split(",");
                 } else {
                     break;
                 }
diff --git a/core/java/com/android/internal/util/ContrastColorUtil.java b/core/java/com/android/internal/util/ContrastColorUtil.java
index 1038199..a403c06 100644
--- a/core/java/com/android/internal/util/ContrastColorUtil.java
+++ b/core/java/com/android/internal/util/ContrastColorUtil.java
@@ -523,8 +523,9 @@
     }
 
     public static int resolveAmbientColor(Context context, int notificationColor) {
-        final int resolvedColor = resolveColor(context, notificationColor,
-                true /* defaultBackgroundIsDark */);
+        final int resolvedColor = notificationColor == Notification.COLOR_DEFAULT
+                ? context.getColor(com.android.internal.R.color.notification_default_color_dark)
+                : notificationColor;
 
         int color = resolvedColor;
         color = ContrastColorUtil.ensureTextContrastOnBlack(color);
diff --git a/core/jni/android/graphics/pdf/PdfDocument.cpp b/core/jni/android/graphics/pdf/PdfDocument.cpp
index e2dc52b..5f67d30 100644
--- a/core/jni/android/graphics/pdf/PdfDocument.cpp
+++ b/core/jni/android/graphics/pdf/PdfDocument.cpp
@@ -21,11 +21,11 @@
 
 #include "CreateJavaOutputStreamAdaptor.h"
 
-#include "SkDocument.h"
+#include "SkPDFDocument.h"
 #include "SkPicture.h"
 #include "SkPictureRecorder.h"
-#include "SkStream.h"
 #include "SkRect.h"
+#include "SkStream.h"
 
 #include <hwui/Canvas.h>
 
@@ -88,7 +88,7 @@
     }
 
     void write(SkWStream* stream) {
-        sk_sp<SkDocument> document = SkDocument::MakePDF(stream);
+        sk_sp<SkDocument> document = SkPDF::MakeDocument(stream);
         for (unsigned i = 0; i < mPages.size(); i++) {
             PageRecord* page =  mPages[i];
 
diff --git a/core/jni/android/opengl/util.cpp b/core/jni/android/opengl/util.cpp
index b163597..a45b493 100644
--- a/core/jni/android/opengl/util.cpp
+++ b/core/jni/android/opengl/util.cpp
@@ -622,13 +622,17 @@
 
 // ---------------------------------------------------------------------------
 
+// The internal format is no longer the same as pixel format, per Table 2 in
+// https://www.khronos.org/registry/OpenGL-Refpages/es3.1/html/glTexImage2D.xhtml
 static int checkInternalFormat(SkColorType colorType, int internalformat,
     int type)
 {
     switch(colorType) {
         case kN32_SkColorType:
             return (type == GL_UNSIGNED_BYTE &&
-                internalformat == GL_RGBA) ? 0 : -1;
+                    internalformat == GL_RGBA) ||
+                (type == GL_UNSIGNED_BYTE &&
+                 internalformat == GL_SRGB8_ALPHA8) ? 0 : -1;
         case kAlpha_8_SkColorType:
             return (type == GL_UNSIGNED_BYTE &&
                 internalformat == GL_ALPHA) ? 0 : -1;
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index eba4c50..343aef2 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -674,7 +674,7 @@
     int ret = 0;
     ret |= RegisterMethodsOrDie(env, "android/graphics/Canvas", gMethods, NELEM(gMethods));
     ret |= RegisterMethodsOrDie(env, "android/graphics/BaseCanvas", gDrawMethods, NELEM(gDrawMethods));
-    ret |= RegisterMethodsOrDie(env, "android/view/RecordingCanvas", gDrawMethods, NELEM(gDrawMethods));
+    ret |= RegisterMethodsOrDie(env, "android/graphics/BaseRecordingCanvas", gDrawMethods, NELEM(gDrawMethods));
     return ret;
 
 }
diff --git a/core/jni/android_graphics_drawable_VectorDrawable.cpp b/core/jni/android_graphics_drawable_VectorDrawable.cpp
index 6f4a58a..58a2379 100644
--- a/core/jni/android_graphics_drawable_VectorDrawable.cpp
+++ b/core/jni/android_graphics_drawable_VectorDrawable.cpp
@@ -130,7 +130,7 @@
 
 static jfloat getRootAlpha(JNIEnv*, jobject, jlong treePtr) {
     VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(treePtr);
-    return tree->stagingProperties()->getRootAlpha();
+    return tree->stagingProperties().getRootAlpha();
 }
 
 static void updateFullPathPropertiesAndStrokeStyles(JNIEnv*, jobject, jlong fullPathPtr,
diff --git a/core/jni/android_net_LocalSocketImpl.cpp b/core/jni/android_net_LocalSocketImpl.cpp
index 6df23f7..a1f2377 100644
--- a/core/jni/android_net_LocalSocketImpl.cpp
+++ b/core/jni/android_net_LocalSocketImpl.cpp
@@ -58,6 +58,11 @@
     int ret;
     int fd;
 
+    if (name == NULL) {
+        jniThrowNullPointerException(env, NULL);
+        return;
+    }
+
     fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
 
     if (env->ExceptionCheck()) {
diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp
index dfa5de6..b70485d 100644
--- a/core/jni/android_os_GraphicsEnvironment.cpp
+++ b/core/jni/android_os_GraphicsEnvironment.cpp
@@ -28,6 +28,14 @@
     android::GraphicsEnv::getInstance().setDriverPath(pathChars.c_str());
 }
 
+void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring appName, jstring appPref, jboolean devOptIn) {
+    ScopedUtfChars pathChars(env, path);
+    ScopedUtfChars appNameChars(env, appName);
+    ScopedUtfChars appPrefChars(env, appPref);
+    android::GraphicsEnv::getInstance().setAngleInfo(pathChars.c_str(), appNameChars.c_str(),
+            appPrefChars.c_str(), devOptIn);
+}
+
 void setLayerPaths_native(JNIEnv* env, jobject clazz, jobject classLoader, jstring layerPaths) {
     android::NativeLoaderNamespace* appNamespace = android::FindNativeLoaderNamespaceByClassLoader(
         env, classLoader);
@@ -44,6 +52,7 @@
 
 const JNINativeMethod g_methods[] = {
     { "setDriverPath", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDriverPath) },
+    { "setAngleInfo", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)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) },
 };
diff --git a/core/jni/android_text_LineBreaker.cpp b/core/jni/android_text_LineBreaker.cpp
index dac108e..5439107 100644
--- a/core/jni/android_text_LineBreaker.cpp
+++ b/core/jni/android_text_LineBreaker.cpp
@@ -41,17 +41,6 @@
 
 namespace android {
 
-struct JLineBreaksID {
-    jfieldID breaks;
-    jfieldID widths;
-    jfieldID ascents;
-    jfieldID descents;
-    jfieldID flags;
-};
-
-static jclass gLineBreaks_class;
-static JLineBreaksID gLineBreaks_fieldID;
-
 static inline std::vector<float> jintArrayToFloatVector(JNIEnv* env, jintArray javaArray) {
     if (javaArray == nullptr) {
          return std::vector<float>();
@@ -85,34 +74,7 @@
     return reinterpret_cast<jlong>(nFinish);
 }
 
-static void recycleCopy(JNIEnv* env, jobject recycle, jintArray recycleBreaks,
-                        jfloatArray recycleWidths, jfloatArray recycleAscents,
-                        jfloatArray recycleDescents, jintArray recycleFlags,
-                        jint recycleLength, const minikin::LineBreakResult& result) {
-    const size_t nBreaks = result.breakPoints.size();
-    if ((size_t)recycleLength < nBreaks) {
-        // have to reallocate buffers
-        recycleBreaks = env->NewIntArray(nBreaks);
-        recycleWidths = env->NewFloatArray(nBreaks);
-        recycleAscents = env->NewFloatArray(nBreaks);
-        recycleDescents = env->NewFloatArray(nBreaks);
-        recycleFlags = env->NewIntArray(nBreaks);
-
-        env->SetObjectField(recycle, gLineBreaks_fieldID.breaks, recycleBreaks);
-        env->SetObjectField(recycle, gLineBreaks_fieldID.widths, recycleWidths);
-        env->SetObjectField(recycle, gLineBreaks_fieldID.ascents, recycleAscents);
-        env->SetObjectField(recycle, gLineBreaks_fieldID.descents, recycleDescents);
-        env->SetObjectField(recycle, gLineBreaks_fieldID.flags, recycleFlags);
-    }
-    // copy data
-    env->SetIntArrayRegion(recycleBreaks, 0, nBreaks, result.breakPoints.data());
-    env->SetFloatArrayRegion(recycleWidths, 0, nBreaks, result.widths.data());
-    env->SetFloatArrayRegion(recycleAscents, 0, nBreaks, result.ascents.data());
-    env->SetFloatArrayRegion(recycleDescents, 0, nBreaks, result.descents.data());
-    env->SetIntArrayRegion(recycleFlags, 0, nBreaks, result.flags.data());
-}
-
-static jint nComputeLineBreaks(JNIEnv* env, jclass, jlong nativePtr,
+static jlong nComputeLineBreaks(JNIEnv* env, jclass, jlong nativePtr,
         // Inputs
         jcharArray javaText,
         jlong measuredTextPtr,
@@ -122,18 +84,7 @@
         jfloat restWidth,
         jintArray variableTabStops,
         jint defaultTabStop,
-        jint indentsOffset,
-
-        // Outputs
-        jobject recycle,
-        jint recycleLength,
-        jintArray recycleBreaks,
-        jfloatArray recycleWidths,
-        jfloatArray recycleAscents,
-        jfloatArray recycleDescents,
-        jintArray recycleFlags,
-        jfloatArray charWidths) {
-
+        jint indentsOffset) {
     minikin::android::StaticLayoutNative* builder = toNative(nativePtr);
 
     ScopedCharArrayRO text(env, javaText);
@@ -141,14 +92,44 @@
 
     minikin::U16StringPiece u16Text(text.get(), length);
     minikin::MeasuredText* measuredText = reinterpret_cast<minikin::MeasuredText*>(measuredTextPtr);
-    minikin::LineBreakResult result = builder->computeBreaks(
-            u16Text, *measuredText, firstWidth, firstWidthLineCount, restWidth, indentsOffset,
-            tabStops.get(), tabStops.size(), defaultTabStop);
 
-    recycleCopy(env, recycle, recycleBreaks, recycleWidths, recycleAscents, recycleDescents,
-            recycleFlags, recycleLength, result);
+    std::unique_ptr<minikin::LineBreakResult> result =
+          std::make_unique<minikin::LineBreakResult>(builder->computeBreaks(
+                u16Text, *measuredText, firstWidth, firstWidthLineCount, restWidth, indentsOffset,
+                tabStops.get(), tabStops.size(), defaultTabStop));
+    return reinterpret_cast<jlong>(result.release());
+}
 
-    return static_cast<jint>(result.breakPoints.size());
+static jint nGetLineCount(jlong ptr) {
+    return reinterpret_cast<minikin::LineBreakResult*>(ptr)->breakPoints.size();
+}
+
+static jint nGetLineBreakOffset(jlong ptr, jint i) {
+    return reinterpret_cast<minikin::LineBreakResult*>(ptr)->breakPoints[i];
+}
+
+static jfloat nGetLineWidth(jlong ptr, jint i) {
+    return reinterpret_cast<minikin::LineBreakResult*>(ptr)->widths[i];
+}
+
+static jfloat nGetLineAscent(jlong ptr, jint i) {
+    return reinterpret_cast<minikin::LineBreakResult*>(ptr)->ascents[i];
+}
+
+static jfloat nGetLineDescent(jlong ptr, jint i) {
+    return reinterpret_cast<minikin::LineBreakResult*>(ptr)->descents[i];
+}
+
+static jint nGetLineFlag(jlong ptr, jint i) {
+    return reinterpret_cast<minikin::LineBreakResult*>(ptr)->flags[i];
+}
+
+static void nReleaseResult(jlong ptr) {
+    delete reinterpret_cast<minikin::LineBreakResult*>(ptr);
+}
+
+static jlong nGetReleaseResultFunc() {
+    return reinterpret_cast<jlong>(nReleaseResult);
 }
 
 static const JNINativeMethod gMethods[] = {
@@ -166,8 +147,6 @@
     // Regular JNI
     {"nComputeLineBreaks", "("
         "J"  // nativePtr
-
-        // Inputs
         "[C"  // text
         "J"  // MeasuredParagraph ptr.
         "I"  // length
@@ -177,31 +156,20 @@
         "[I"  // variableTabStops
         "I"  // defaultTabStop
         "I"  // indentsOffset
+        ")J", (void*) nComputeLineBreaks},
 
-        // Outputs
-        "Landroid/text/NativeLineBreaker$LineBreaks;"  // recycle
-        "I"  // recycleLength
-        "[I"  // recycleBreaks
-        "[F"  // recycleWidths
-        "[F"  // recycleAscents
-        "[F"  // recycleDescents
-        "[I"  // recycleFlags
-        ")I", (void*) nComputeLineBreaks}
+    // Result accessors, CriticalNatives
+    {"nGetLineCount", "(J)I", (void*)nGetLineCount},
+    {"nGetLineBreakOffset", "(JI)I", (void*)nGetLineBreakOffset},
+    {"nGetLineWidth", "(JI)F", (void*)nGetLineWidth},
+    {"nGetLineAscent", "(JI)F", (void*)nGetLineAscent},
+    {"nGetLineDescent", "(JI)F", (void*)nGetLineDescent},
+    {"nGetLineFlag", "(JI)I", (void*)nGetLineFlag},
+    {"nGetReleaseResultFunc", "()J", (void*)nGetReleaseResultFunc},
 };
 
-int register_android_text_LineBreaker(JNIEnv* env)
-{
-    gLineBreaks_class = MakeGlobalRefOrDie(env,
-            FindClassOrDie(env, "android/text/NativeLineBreaker$LineBreaks"));
-
-    gLineBreaks_fieldID.breaks = GetFieldIDOrDie(env, gLineBreaks_class, "breaks", "[I");
-    gLineBreaks_fieldID.widths = GetFieldIDOrDie(env, gLineBreaks_class, "widths", "[F");
-    gLineBreaks_fieldID.ascents = GetFieldIDOrDie(env, gLineBreaks_class, "ascents", "[F");
-    gLineBreaks_fieldID.descents = GetFieldIDOrDie(env, gLineBreaks_class, "descents", "[F");
-    gLineBreaks_fieldID.flags = GetFieldIDOrDie(env, gLineBreaks_class, "flags", "[I");
-
-    return RegisterMethodsOrDie(env, "android/text/NativeLineBreaker",
-                                gMethods, NELEM(gMethods));
+int register_android_text_LineBreaker(JNIEnv* env) {
+    return RegisterMethodsOrDie(env, "android/text/NativeLineBreaker", gMethods, NELEM(gMethods));
 }
 
 }
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index 46b19bd..63b0046 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -444,6 +444,14 @@
     return reinterpret_cast<RenderNode*>(renderNodePtr)->stagingProperties().getHeight();
 }
 
+static jboolean android_view_RenderNode_setAllowForceDark(jlong renderNodePtr, jboolean allow) {
+    return SET_AND_DIRTY(setAllowForceDark, allow, RenderNode::GENERIC);
+}
+
+static jboolean android_view_RenderNode_getAllowForceDark(jlong renderNodePtr) {
+    return reinterpret_cast<RenderNode*>(renderNodePtr)->stagingProperties().getAllowForceDark();
+}
+
 // ----------------------------------------------------------------------------
 // RenderProperties - Animations
 // ----------------------------------------------------------------------------
@@ -465,8 +473,8 @@
 // SurfaceView position callback
 // ----------------------------------------------------------------------------
 
-jmethodID gSurfaceViewPositionUpdateMethod;
-jmethodID gSurfaceViewPositionLostMethod;
+jmethodID gPositionListener_PositionChangedMethod;
+jmethodID gPositionListener_PositionLostMethod;
 
 static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
         jlong renderNodePtr, jobject surfaceview) {
@@ -523,7 +531,7 @@
                 return;
             }
 
-            env->CallVoidMethod(localref, gSurfaceViewPositionLostMethod,
+            env->CallVoidMethod(localref, gPositionListener_PositionLostMethod,
                     info ? info->canvasContext.getFrameNumber() : 0);
             env->DeleteLocalRef(localref);
         }
@@ -547,7 +555,7 @@
                 env->DeleteWeakGlobalRef(mWeakRef);
                 mWeakRef = nullptr;
             } else {
-                env->CallVoidMethod(localref, gSurfaceViewPositionUpdateMethod,
+                env->CallVoidMethod(localref, gPositionListener_PositionChangedMethod,
                         frameNumber, left, top, right, bottom);
                 env->DeleteLocalRef(localref);
             }
@@ -580,7 +588,7 @@
     { "nGetDebugSize",         "(J)I",    (void*) android_view_RenderNode_getDebugSize },
     { "nAddAnimator",              "(JJ)V", (void*) android_view_RenderNode_addAnimator },
     { "nEndAllAnimators",          "(J)V", (void*) android_view_RenderNode_endAllAnimators },
-    { "nRequestPositionUpdates",   "(JLandroid/view/SurfaceView;)V", (void*) android_view_RenderNode_requestPositionUpdates },
+    { "nRequestPositionUpdates",   "(JLandroid/view/RenderNode$PositionUpdateListener;)V", (void*) android_view_RenderNode_requestPositionUpdates },
     { "nSetDisplayList",       "(JJ)V",   (void*) android_view_RenderNode_setDisplayList },
 
 
@@ -664,14 +672,16 @@
     { "nGetPivotY",                "(J)F",  (void*) android_view_RenderNode_getPivotY },
     { "nGetWidth",                 "(J)I",  (void*) android_view_RenderNode_getWidth },
     { "nGetHeight",                "(J)I",  (void*) android_view_RenderNode_getHeight },
+    { "nSetAllowForceDark",        "(JZ)Z", (void*) android_view_RenderNode_setAllowForceDark },
+    { "nGetAllowForceDark",        "(J)Z",  (void*) android_view_RenderNode_getAllowForceDark },
 };
 
 int register_android_view_RenderNode(JNIEnv* env) {
-    jclass clazz = FindClassOrDie(env, "android/view/SurfaceView");
-    gSurfaceViewPositionUpdateMethod = GetMethodIDOrDie(env, clazz,
-            "updateSurfacePosition_renderWorker", "(JIIII)V");
-    gSurfaceViewPositionLostMethod = GetMethodIDOrDie(env, clazz,
-            "surfacePositionLost_uiRtSync", "(J)V");
+    jclass clazz = FindClassOrDie(env, "android/view/RenderNode$PositionUpdateListener");
+    gPositionListener_PositionChangedMethod = GetMethodIDOrDie(env, clazz,
+            "positionChanged", "(JIIII)V");
+    gPositionListener_PositionLostMethod = GetMethodIDOrDie(env, clazz,
+            "positionLost", "(J)V");
     return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
 }
 
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 3c59bd1..7a5b604 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -1064,6 +1064,12 @@
     proxy->allocateBuffers(surface);
 }
 
+static void android_view_ThreadedRenderer_setForceDark(JNIEnv* env, jobject clazz,
+        jlong proxyPtr, jboolean enable) {
+    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+    proxy->setForceDark(enable);
+}
+
 // ----------------------------------------------------------------------------
 // FrameMetricsObserver
 // ----------------------------------------------------------------------------
@@ -1177,6 +1183,7 @@
     { "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 },
+    { "nSetForceDark", "(JZ)V", (void*)android_view_ThreadedRenderer_setForceDark },
 };
 
 static JavaVM* mJvm = nullptr;
diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
index c15b7ee..109e65c 100644
--- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
+++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
@@ -285,10 +285,6 @@
 static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, jstring path,
                                   jint limitUid, jobjectArray limitIfacesObj, jint limitTag,
                                   jboolean useBpfStats) {
-    ScopedUtfChars path8(env, path);
-    if (path8.c_str() == NULL) {
-        return -1;
-    }
 
     std::vector<std::string> limitIfaces;
     if (limitIfacesObj != NULL && env->GetArrayLength(limitIfacesObj) > 0) {
@@ -308,6 +304,11 @@
         if (parseBpfNetworkStatsDetail(&lines, limitIfaces, limitTag, limitUid) < 0)
             return -1;
     } else {
+        ScopedUtfChars path8(env, path);
+        if (path8.c_str() == NULL) {
+            ALOGE("the qtaguid legacy path is invalid: %s", path8.c_str());
+            return -1;
+        }
         if (legacyReadNetworkStatsDetail(&lines, limitIfaces, limitTag,
                                          limitUid, path8.c_str()) < 0)
             return -1;
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 364393e..1f95862 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -382,11 +382,10 @@
     return 0;
 }
 
-static bool createPkgSandbox(uid_t uid, const char* package_name, std::string& pkg_sandbox_dir,
-        std::string* error_msg) {
+static bool createPkgSandbox(uid_t uid, const std::string& package_name, std::string* error_msg) {
     // Create /mnt/user/0/package/<package-name>
     userid_t user_id = multiuser_get_user_id(uid);
-    StringAppendF(&pkg_sandbox_dir, "/%d", user_id);
+    std::string pkg_sandbox_dir = StringPrintf("/mnt/user/%d", user_id);
     if (fs_prepare_dir(pkg_sandbox_dir.c_str(), 0751, AID_ROOT, AID_ROOT) != 0) {
         *error_msg = CREATE_ERROR("fs_prepare_dir failed on %s", pkg_sandbox_dir.c_str());
         return false;
@@ -396,7 +395,7 @@
         *error_msg = CREATE_ERROR("fs_prepare_dir failed on %s", pkg_sandbox_dir.c_str());
         return false;
     }
-    StringAppendF(&pkg_sandbox_dir, "/%s", package_name);
+    StringAppendF(&pkg_sandbox_dir, "/%s", package_name.c_str());
     if (fs_prepare_dir(pkg_sandbox_dir.c_str(), 0755, uid, uid) != 0) {
         *error_msg = CREATE_ERROR("fs_prepare_dir failed on %s", pkg_sandbox_dir.c_str());
         return false;
@@ -404,10 +403,51 @@
     return true;
 }
 
+static bool mountPkgSpecificDir(const std::string& mntSourceRoot,
+        const std::string& mntTargetRoot, const std::string& packageName,
+        const char* dirName, std::string* error_msg) {
+    std::string mntSourceDir = StringPrintf("%s/Android/%s/%s",
+            mntSourceRoot.c_str(), dirName, packageName.c_str());
+    std::string mntTargetDir = StringPrintf("%s/Android/%s/%s",
+            mntTargetRoot.c_str(), dirName, packageName.c_str());
+    if (TEMP_FAILURE_RETRY(mount(mntSourceDir.c_str(), mntTargetDir.c_str(),
+            nullptr, MS_BIND | MS_REC, nullptr)) == -1) {
+        *error_msg = CREATE_ERROR("Failed to mount %s to %s: %s",
+                mntSourceDir.c_str(), mntTargetDir.c_str(), strerror(errno));
+        return false;
+    }
+    if (TEMP_FAILURE_RETRY(mount(nullptr, mntTargetDir.c_str(),
+            nullptr, MS_SLAVE | MS_REC, nullptr)) == -1) {
+        *error_msg = CREATE_ERROR("Failed to set MS_SLAVE for %s", mntTargetDir.c_str());
+        return false;
+    }
+    return true;
+}
+
+static bool preparePkgSpecificDirs(const std::vector<std::string>& packageNames,
+        const std::vector<std::string>& volumeLabels, userid_t userId, std::string* error_msg) {
+    for (auto& label : volumeLabels) {
+        std::string mntSource = StringPrintf("/mnt/runtime/write/%s", label.c_str());
+        std::string mntTarget = StringPrintf("/storage/%s", label.c_str());
+        if (label == "emulated") {
+            StringAppendF(&mntSource, "/%d", userId);
+            StringAppendF(&mntTarget, "/%d", userId);
+        }
+        for (auto& package : packageNames) {
+            mountPkgSpecificDir(mntSource, mntTarget, package, "data", error_msg);
+            mountPkgSpecificDir(mntSource, mntTarget, package, "media", error_msg);
+            mountPkgSpecificDir(mntSource, mntTarget, package, "obb", error_msg);
+        }
+    }
+    return true;
+}
+
 // Create a private mount namespace and bind mount appropriate emulated
 // storage for the given user.
 static bool MountEmulatedStorage(uid_t uid, jint mount_mode,
-        bool force_mount_namespace, std::string* error_msg, const char* package_name) {
+        bool force_mount_namespace, std::string* error_msg, const std::string& package_name,
+        const std::vector<std::string>& packages_for_uid,
+        const std::vector<std::string>& visible_vol_ids) {
     // See storage config details at http://source.android.com/tech/storage/
 
     String8 storageSource;
@@ -459,12 +499,25 @@
                 return false;
             }
         } else {
-            if (package_name == nullptr) {
+            if (package_name.empty()) {
                 return true;
             }
-            std::string pkgSandboxDir("/mnt/user");
-            if (!createPkgSandbox(uid, package_name, pkgSandboxDir, error_msg)) {
-                return false;
+            userid_t user_id = multiuser_get_user_id(uid);
+            std::string pkgSandboxDir = StringPrintf("/mnt/user/%d/package/%s",
+                    user_id, package_name.c_str());
+            struct stat sb;
+            bool sandboxAlreadyCreated = true;
+            if (TEMP_FAILURE_RETRY(lstat(pkgSandboxDir.c_str(), &sb)) == -1) {
+                if (errno == ENOENT) {
+                    ALOGD("Sandbox not yet created for %s", pkgSandboxDir.c_str());
+                    sandboxAlreadyCreated = false;
+                    if (!createPkgSandbox(uid, package_name, error_msg)) {
+                        return false;
+                    }
+                } else {
+                    ALOGE("Failed to lstat %s", pkgSandboxDir.c_str());
+                    return false;
+                }
             }
             if (TEMP_FAILURE_RETRY(mount(pkgSandboxDir.c_str(), "/storage",
                     nullptr, MS_BIND | MS_REC | MS_SLAVE, nullptr)) == -1) {
@@ -472,6 +525,15 @@
                         pkgSandboxDir.c_str(), strerror(errno));
                 return false;
             }
+            // If the sandbox was already created by vold, only then set up the bind mounts for
+            // pkg specific directories. Otherwise, leave as is and bind mounts will be taken
+            // care of by vold later.
+            if (sandboxAlreadyCreated) {
+                if (!preparePkgSpecificDirs(packages_for_uid, visible_vol_ids,
+                        user_id, error_msg)) {
+                    return false;
+                }
+            }
         }
     } else {
         if (TEMP_FAILURE_RETRY(mount(storageSource.string(), "/storage",
@@ -611,7 +673,8 @@
                              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) {
+                             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)
@@ -661,17 +724,33 @@
     ALOGW("Native bridge will not be used because dataDir == NULL.");
   }
 
-  ScopedUtfChars* package_name = nullptr;
-  const char* package_name_c_str = nullptr;
+  std::string package_name_str("");
   if (packageName != nullptr) {
-    package_name = new ScopedUtfChars(env, packageName);
-    package_name_c_str = package_name->c_str();
+    ScopedUtfChars package(env, packageName);
+    package_name_str = package.c_str();
   } else if (is_system_server) {
-    package_name_c_str = "android";
+    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_c_str);
-  delete package_name;
+      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) {
@@ -936,7 +1015,8 @@
         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) {
+        jstring instructionSet, jstring appDataDir, jstring packageName,
+        jobjectArray packagesForUid, jobjectArray visibleVolIds) {
     jlong capabilities = 0;
 
     // Grant CAP_WAKE_ALARM to the Bluetooth process.
@@ -989,7 +1069,8 @@
       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);
+                       is_child_zygote == JNI_TRUE, instructionSet, appDataDir, packageName,
+                       packagesForUid, visibleVolIds);
     }
     return pid;
 }
@@ -1003,7 +1084,7 @@
       SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
                        permittedCapabilities, effectiveCapabilities,
                        MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true,
-                       false, NULL, NULL, nullptr);
+                       false, NULL, NULL, 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);
@@ -1084,7 +1165,7 @@
     { "nativeSecurityInit", "()V",
       (void *) com_android_internal_os_Zygote_nativeSecurityInit },
     { "nativeForkAndSpecialize",
-      "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
+      "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)I",
       (void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
     { "nativeForkSystemServer", "(II[II[[IJJ)I",
       (void *) com_android_internal_os_Zygote_nativeForkSystemServer },
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index f9f725a..14ed9e6 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -397,6 +397,9 @@
         // Ordered GPU debug layer list
         // i.e. <layer1>:<layer2>:...:<layerN>
         optional SettingProto debug_layers = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+        // App will load ANGLE instead of native GLES drivers.
+        optional SettingProto angle_enabled_app = 3;
     }
     optional Gpu gpu = 59;
 
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index 9d5f0bc..ab50ad1 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -130,6 +130,13 @@
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
     optional bool keyguard_showing = 1;
+    repeated KeyguardOccludedProto keyguard_occluded_states= 2;
+}
+
+message KeyguardOccludedProto {
+    option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional int32 display_id = 1;
     optional bool keyguard_occluded = 2;
 }
 
diff --git a/core/proto/android/server/backup_chunks_metadata.proto b/core/proto/android/server/backup_chunks_metadata.proto
new file mode 100644
index 0000000..a375f02
--- /dev/null
+++ b/core/proto/android/server/backup_chunks_metadata.proto
@@ -0,0 +1,134 @@
+/*
+ * 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";
+package com.android.server.backup.encryption.chunk;
+
+option java_outer_classname = "ChunksMetadataProto";
+
+// Cipher type with which the chunks are encrypted. For now we only support AES/GCM/NoPadding, but
+// this is for backwards-compatibility in case we need to change the default Cipher in the future.
+enum CipherType {
+    UNKNOWN_CIPHER_TYPE = 0;
+    // Chunk is prefixed with a 12-byte nonce. The tag length is 16 bytes.
+    AES_256_GCM = 1;
+}
+
+// Checksum type with which the plaintext is verified.
+enum ChecksumType {
+    UNKNOWN_CHECKSUM_TYPE = 0;
+    SHA_256 = 1;
+}
+
+enum ChunkOrderingType {
+    CHUNK_ORDERING_TYPE_UNSPECIFIED = 0;
+    // The chunk ordering contains a list of the start position of each chunk in the encrypted file,
+    // ordered as in the plaintext file. This allows us to recreate the original plaintext file
+    // during decryption. We use this mode for full backups where the order of the data in the file
+    // is important.
+    EXPLICIT_STARTS = 1;
+    // The chunk ordering does not contain any start positions, and instead each encrypted chunk in
+    // the backup file is prefixed with its length. This allows us to decrypt each chunk but does
+    // not give any information about the order. However, we use this mode for key value backups
+    // where the order does not matter.
+    INLINE_LENGTHS = 2;
+}
+
+// Chunk entry (for local state)
+message Chunk {
+    // SHA-256 MAC of the plaintext of the chunk
+    optional bytes hash = 1;
+    // Number of bytes in encrypted chunk
+    optional int32 length = 2;
+}
+
+// List of the chunks in the blob, along with the length of each chunk. From this is it possible to
+// extract individual chunks. (i.e., start position is equal to the sum of the lengths of all
+// preceding chunks.)
+//
+// This is local state stored on the device. It is never sent to the backup server. See
+// ChunkOrdering for how the device restores the chunks in the correct order.
+// Next tag : 6
+message ChunkListing {
+    repeated Chunk chunks = 1;
+
+    // Cipher algorithm with which the chunks are encrypted.
+    optional CipherType cipher_type = 2;
+
+    // Defines the type of chunk order used to encode the backup file on the server, so that we can
+    // consistently use the same type between backups. If unspecified this backup file was created
+    // before INLINE_LENGTHS was supported, thus assume it is EXPLICIT_STARTS.
+    optional ChunkOrderingType chunk_ordering_type = 5;
+
+    // The document ID returned from Scotty server after uploading the blob associated with this
+    // listing. This needs to be sent when uploading new diff scripts.
+    optional string document_id = 3;
+
+    // Fingerprint mixer salt used for content defined chunking. This is randomly generated for each
+    // package during the initial non-incremental backup and reused for incremental backups.
+    optional bytes fingerprint_mixer_salt = 4;
+}
+
+// Ordering information about plaintext and checksum. This is used on restore to reconstruct the
+// blob in its correct order. (The chunk order is randomized so as to give the server less
+// information about which parts of the backup are changing over time.) This proto is encrypted
+// before being uploaded to the server, with a key unknown to the server.
+message ChunkOrdering {
+    // For backups where ChunksMetadata#chunk_ordering_type = EXPLICIT STARTS:
+    // Ordered start positions of chunks. i.e., the file is the chunk starting at this position,
+    // followed by the chunk starting at this position, followed by ... etc. You can compute the
+    // lengths of the chunks by sorting this list then looking at the start position of the next
+    // chunk after the chunk you care about. This is guaranteed to work as all chunks are
+    // represented in this list.
+    //
+    // For backups where ChunksMetadata#chunk_ordering_type = INLINE_LENGTHS:
+    // This field is unused. See ChunkOrderingType#INLINE_LENGTHS.
+    repeated int32 starts = 1 [packed = true];
+
+    // Checksum of plaintext content. (i.e., in correct order.)
+    //
+    // Each chunk also has a MAC, as generated by GCM, so this is NOT Mac-then-Encrypt, which has
+    // security implications. This is an additional checksum to verify that once the chunks have
+    // been reordered, that the file matches the expected plaintext. This prevents the device
+    // restoring garbage data in case of a mismatch between the ChunkOrdering and the backup blob.
+    optional bytes checksum = 2;
+}
+
+// Additional metadata about a backup blob that needs to be synced to the server. This is used on
+// restore to reconstruct the blob in its correct order. (The chunk order is randomized so as to
+// give the server less information about which parts of the backup are changing over time.) This
+// data structure is only ever uploaded to the server encrypted with a key unknown to the server.
+// Next tag : 6
+message ChunksMetadata {
+    // Cipher algorithm with which the chunk listing and chunks are encrypted.
+    optional CipherType cipher_type = 1;
+
+    // Defines the type of chunk order this metadata contains. If unspecified this backup file was
+    // created before INLINE_LENGTHS was supported, thus assume it is EXPLICIT_STARTS.
+    optional ChunkOrderingType chunk_ordering_type = 5
+    [default = CHUNK_ORDERING_TYPE_UNSPECIFIED];
+
+    // Encrypted bytes of ChunkOrdering
+    optional bytes chunk_ordering = 2;
+
+    // The type of algorithm used for the checksum of the plaintext. (See ChunkOrdering.) This is
+    // for forwards compatibility in case we change the algorithm in the future. For now, always
+    // SHA-256.
+    optional ChecksumType checksum_type = 3;
+
+    // This used to be the plaintext tertiary key. No longer used.
+    reserved 4;
+}
\ No newline at end of file
diff --git a/core/proto/android/server/usagestatsservice.proto b/core/proto/android/server/usagestatsservice.proto
new file mode 100644
index 0000000..941c81f
--- /dev/null
+++ b/core/proto/android/server/usagestatsservice.proto
@@ -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.
+ */
+
+syntax = "proto2";
+package com.android.server.usage;
+import "frameworks/base/core/proto/android/content/configuration.proto";
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
+option java_multiple_files = true;
+
+message IntervalStatsProto {
+  message StringPool {
+    optional int32 size = 1;
+    repeated string strings = 2;
+  }
+
+  message CountAndTime {
+    optional int32 count = 1;
+    optional int64 time_ms = 2;
+  }
+
+  // Stores the relevant information from a UsageStats
+  message UsageStats {
+    message ChooserAction {
+      message CategoryCount {
+        optional string name = 1;
+        optional int32 count = 3;
+      }
+      optional string name = 1;
+      repeated CategoryCount counts = 3;
+    }
+    optional string package = 1;
+    // package_index contains the index + 1 of the package name in the string pool
+    optional int32 package_index = 2;
+    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;
+  }
+
+  // Stores the relevant information an IntervalStats will have about a Configuration
+  message Configuration {
+    optional .android.content.ConfigurationProto config = 1;
+    optional int64 last_time_active_ms = 2;
+    optional int64 total_time_active_ms = 3;
+    optional int32 count = 4;
+    optional bool active = 5;
+  }
+
+  // Stores the relevant information from a UsageEvents.Event
+  message Event {
+    optional string package = 1;
+    // package_index contains the index + 1 of the package name in the string pool
+    optional int32 package_index = 2;
+    optional string class = 3;
+    // class_index contains the index + 1 of the class name in the string pool
+    optional int32 class_index = 4;
+    optional int64 time_ms = 5;
+    optional int32 flags = 6;
+    optional int32 type = 7;
+    optional .android.content.ConfigurationProto config = 8;
+    optional string shortcut_id = 9;
+    optional int32 standby_bucket = 11;
+    optional string notification_channel = 12;
+    // notification_channel_index contains the index + 1 of the channel name in the string pool
+    optional int32 notification_channel_index = 13;
+  }
+
+  // The following fields contain supplemental data used to build IntervalStats, such as a string
+  // pool.
+  optional int64 end_time_ms = 1;
+  // 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;
+
+  // The following fields contain aggregated usage stats data
+  optional CountAndTime interactive = 10;
+  optional CountAndTime non_interactive = 11;
+  optional CountAndTime keyguard_shown = 12;
+  optional CountAndTime keyguard_hidden = 13;
+
+  // The following fields contain listed usage stats data
+  repeated UsageStats packages = 20;
+  repeated Configuration configurations = 21;
+  repeated Event event_log = 22;
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 5a1f2e8..ea92c60 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -941,7 +941,6 @@
          Requesting this by itself is not sufficient to give you
          location access.
          <p>Protection level: dangerous
-         @hide
     -->
     <permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"
         android:permissionGroup="android.permission-group.LOCATION"
@@ -1186,9 +1185,9 @@
         android:priority="700" />
 
     <!-- Required to be able to access the camera device.
-         <p>This will automatically enforce the <a
-         href="{@docRoot}guide/topics/manifest/uses-feature-element.html">
-         <uses-feature>}</a> manifest element for <em>all</em> camera features.
+         <p>This will automatically enforce the
+         <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">
+         uses-feature</a> manifest element for <em>all</em> camera features.
          If you do not require all camera features or can properly operate if a camera
          is not available, then you must modify your manifest as appropriate in order to
          install on devices that don't support all camera features.</p>
@@ -4144,6 +4143,15 @@
     <permission android:name="android.permission.MONITOR_DEFAULT_SMS_PACKAGE"
         android:protectionLevel="signature" />
 
+    <!-- A subclass of {@link android.app.SmsAppService} must be protected with this permission. -->
+    <permission android:name="android.permission.BIND_SMS_APP_SERVICE"
+        android:protectionLevel="signature" />
+
+    <!-- @hide Permission that allows background clipboard access.
+         <p>Not for use by third-party applications. -->
+    <permission android:name="android.permission.READ_CLIPBOARD_IN_BACKGROUND"
+        android:protectionLevel="signature" />
+
     <application android:process="system"
                  android:persistent="true"
                  android:hasCode="false"
@@ -4459,14 +4467,6 @@
             android:permission="android.permission.LOCATION_HARDWARE"
             android:exported="false" />
 
-        <service android:name="com.android.internal.backup.LocalTransportService"
-                android:permission="android.permission.CONFIRM_FULL_BACKUP"
-                android:exported="false">
-            <intent-filter>
-                <action android:name="android.backup.TRANSPORT_HOST" />
-            </intent-filter>
-        </service>
-
         <service android:name="com.android.server.MountServiceIdler"
                  android:exported="true"
                  android:permission="android.permission.BIND_JOB_SERVICE" >
diff --git a/core/res/res/drawable/ic_ab_back_material_settings.xml b/core/res/res/drawable/ic_ab_back_material_settings.xml
index 7325a41..938e36d 100644
--- a/core/res/res/drawable/ic_ab_back_material_settings.xml
+++ b/core/res/res/drawable/ic_ab_back_material_settings.xml
@@ -18,11 +18,12 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="24dp"
         android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
         android:autoMirrored="true"
-        android:tint="?attr/colorControlNormal">
+        android:tint="?attr/colorControlNormal"
+        android:viewportHeight="24"
+        android:viewportWidth="24">
     <path
         android:fillColor="@color/white"
-        android:pathData="M20,11H7.62l4.88,-4.88a0.996,0.996 0,1 0,-1.41 -1.41l-6.94,6.94c-0.2,0.2 -0.2,0.51 0,0.71l6.94,6.94a0.996,0.996 0,1 0,1.41 -1.41L7.62,13H20c0.55,0 1,-0.45 1,-1s-0.45,-1 -1,-1z"/>
+        android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8l8,8l1.41,-1.41L7.83,13H20V11z"/>
 </vector>
+
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 3b124da..5028150 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Nie herken nie"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Vingerafdruk is gestaaf"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Gesig is gestaaf"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Gesig is gestaaf; druk asseblief bevestig"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Vingerafdrukhardeware is nie beskikbaar nie."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Vingerafdruk kan nie gestoor word nie. Verwyder asseblief \'n bestaande vingerafdruk."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Vingerafdrukuittelling is bereik. Probeer weer."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Gesiguittelling is bereik. Probeer weer."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Gesig kan nie geberg word nie."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Gesighandeling is gekanselleer."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Gesigstawing is deur gebruiker gekanselleer."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Te veel pogings. Probeer later weer."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Te veel pogings. Gesigstawingsensor is gedeaktiveer."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Probeer weer."</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 3cd1b50..217d631 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"አልታወቀም"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"የጣት አሻራ ትክክለኛነት ተረጋግጧል"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"ፊት ተረጋግጧል"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"ፊት ተረጋግጧል፣ እባክዎ አረጋግጥን ይጫኑ"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"የጣት አሻራ ሃርድዌር አይገኝም።"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"የጣት አሻራ ሊከማች አይችልም። እባክዎ አሁን ያለውን የጣት አሻራ ያስወግዱ።"</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"የጣት አሻራ ማብቂያ ጊዜ ደርሷል። እንደገና ይሞክሩ።"</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"የፊት ማብቂያ ጊዜ ደርሷል። እንደገና ይሞክሩ።"</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"ፊት ሊከማች አይችልም።"</string>
     <string name="face_error_canceled" msgid="283945501061931023">"የፊት ሥርዓተ ክወና ተሰርዟል።"</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"ፊትን ማረጋገጥ በተጠቃሚ ተሰርዟል።"</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"ከልክ በላይ ብዙ ሙከራዎች። በኋላ ላይ እንደገና ይሞክሩ።"</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"በጣም ብዙ ሙከራዎች። የፊት ማረጋገጫ ተሰናክሏል።"</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"እንደገና ይሞክሩ።"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index cf3b035..c11279a 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -540,10 +540,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"لم يتم التعرف عليها."</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"تم مصادقة بصمة الإصبع"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"تمّت مصادقة الوجه"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"تمّت مصادقة الوجه، يُرجى الضغط على \"تأكيد\"."</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"جهاز بصمة الإصبع غير متاح."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"يتعذر تخزين بصمة الإصبع؛ يرجى إزالة إحدى البصمات المخزنة."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"تم بلوغ مهلة إدخال بصمة الإصبع. أعد المحاولة."</string>
@@ -580,8 +578,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"انتهت مهلة التعرُّف على الوجه. أعِد المحاولة."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"يتعذَّر حفظ الوجه."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"تمّ إلغاء عملية مصادقة الوجه."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"ألغَى المستخدم مصادقة الوجه."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"تمّ إجراء محاولات كثيرة. أعِد المحاولة لاحقًا."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"تمّ إجراء محاولات كثيرة. ميزة مصادقة الوجه متوقفة."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"يُرجى إعادة المحاولة."</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 9974867..5a0a7ec 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -312,7 +312,7 @@
     <string name="permgrouprequest_visual" msgid="6907523945030290376">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ ফট’ আৰু ভিডিঅ’সমূহ এক্সেছ কৰিবলৈ দিবনে?"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"ৱিণ্ড\' সমল বিচাৰি উলিয়াওক"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"আপুনি যোগাযোগ কৰি থকা ৱিণ্ড\'খনৰ সমল পৰীক্ষা কৰক।"</string>
-    <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"স্পৰ্শৰদ্বাৰা অন্বেষণ কৰাৰ সুবিধা অন কৰক"</string>
+    <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"স্পৰ্শৰ দ্বাৰা অন্বেষণ কৰাৰ সুবিধা অন কৰক"</string>
     <string name="capability_desc_canRequestTouchExploration" msgid="7543249041581408313">"টেপ কৰা বস্তুসমূহ ডাঙৰকৈ কোৱা হ\'ব আৰু আঙুলিৰ স্পৰ্শেৰে নিৰ্দেশ দি স্ক্ৰীণ অন্বেষণ কৰিব পাৰিব।"</string>
     <string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"আপুনি লিখা পাঠ নিৰীক্ষণ কৰক"</string>
     <string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"ক্ৰেডিট কাৰ্ডৰ নম্বৰ আৰু পাছৱৰ্ডৰ দৰে ব্যক্তিগত ডেটা অন্তৰ্ভুক্ত হ\'ব পাৰে।"</string>
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"চিনাক্ত কৰিব পৰা নাই"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"ফিংগাৰপ্ৰিণ্টৰ সত্যাপন কৰা হ’ল"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"মুখমণ্ডলৰ বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ কৰা হ\'ল"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"মুখমণ্ডলৰ বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ কৰা হ\'ল, অনুগ্ৰহ কৰি ‘নিশ্চিত কৰক’ বুটামটো টিপক"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ফিংগাৰপ্ৰিণ্ট হাৰ্ডৱেৰ নাই।"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ফিংগাৰপ্ৰিণ্ট সঞ্চয় কৰিব পৰা নগ\'ল। পূর্বে সঞ্চিত ফিংগাৰপ্ৰিণ্ট এটা আঁতৰাওক।"</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ফিংগাৰপ্ৰিণ্ট গ্ৰহণৰ সময়সীমা উকলি গৈছে। আকৌ চেষ্টা কৰক।"</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"মুখমণ্ডল গ্ৰহণৰ সময়সীমা উকলি গৈছে। আকৌ চেষ্টা কৰক।"</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"মুখমণ্ডল সঞ্চয় কৰিব নোৱাৰি।"</string>
     <string name="face_error_canceled" msgid="283945501061931023">"মুখমণ্ডলৰ প্ৰক্ৰিয়া বাতিল কৰা হ’ল।"</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"ব্যৱহাৰকাৰীয়ে মুখমণ্ডলৰ বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ বাতিল কৰিছে।"</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"অত্যধিক ভুল প্ৰয়াস। কিছুসময়ৰ পাছত আকৌ চেষ্টা কৰক।"</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"অত্যধিক প্ৰয়াস। মুখমণ্ডলৰ জৰিয়তে সত্যাপন অক্ষম কৰা হ’ল।"</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"আকৌ চেষ্টা কৰক।"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 3236b52..af65bbb 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Tanınmır"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Barmaq izi doğrulandı"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Üz doğrulandı"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Üz təsdiq edildi, təsdiq düyməsinə basın"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Barmaq izi üçün avadanlıq yoxdur."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Barmaq izi saxlana bilməz. Lütfən, mövcud barmaq izini silin."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Barmaq izinin vaxtı başa çatdı. Yenidən cəhd edin."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Üz proqramı taymerinin vaxtı bitdi. Yenidən cəhd edin."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Üz bərpa edilmədi."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Üz əməliyyatı ləğv edildi."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Üz dorğulaması istifadəçi tərəfindən ləğv edildi."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Həddindən çox cəhd. Sonraya saxlayın."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Həddindən çox cəhd. Üz identifikasiyası deaktiv edildi."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Yenidən cəhd edin."</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 2bbf9b2..805082a 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -531,10 +531,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Nije prepoznato"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Otisak prsta je potvrđen"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Lice je potvrđeno"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Lice je potvrđeno. Pritisnite Potvrdi"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardver za otiske prstiju nije dostupan."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Nije moguće sačuvati otisak prsta. Uklonite neki od postojećih otisaka prstiju."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Vremensko ograničenje za otisak prsta je isteklo. Probajte ponovo."</string>
@@ -571,8 +569,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Isteklo je vreme za proveru lica. Probajte ponovo."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Nije moguće sačuvati lice."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Obrada lica je otkazana."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Korisnik je otkazao potvrdu lica."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Previše pokušaja. Probajte ponovo kasnije."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Više pokušaja. Potvrda identiteta je onemogućena."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Probajte ponovo."</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 0ec976f..7692220 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -534,10 +534,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Не распазнана"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Адбітак пальца распазнаны"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Твар распазнаны"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Твар распазнаны. Націсніце, каб пацвердзіць"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Апаратныя сродкі адбіткаў пальцаў недаступныя."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Адбіткі пальцаў нельга захаваць. Выдаліце існы адбітак."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Час чакання адбіткаў пальцаў выйшаў. Паспрабуйце яшчэ раз."</string>
@@ -574,8 +572,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Час чакання твару выйшаў. Паўтарыце спробу."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Не ўдалося захаваць твар."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Распазнаванне твару скасавана."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Распазнаванне твару скасавана карыстальнікам."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Занадта шмат спроб. Паўтарыце спробу пазней."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Занадта шмат спроб. Аўтэнтыфікацыя твару адключана"</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Паўтарыце спробу."</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 3af930f..33c4898 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Не е разпознато"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Отпечатъкът е удостоверен"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Лицето е удостоверено"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Лицето е удостоверено. Моля, натиснете „Потвърждаване“"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Хардуерът за отпечатъци не е налице."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Отпечатъкът не може да бъде съхранен. Моля, премахнете съществуващ."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Времето за изчакване за отпечатък изтече. Опитайте отново."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Времето за изчакване изтече. Опитайте отново."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Лицето не може да бъде съхранено."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Операцията с лице е анулирана."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Удостоверяв. на лицето е анулирано от потребителя."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Твърде много опити. Опитайте отново по-късно."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Твърде много опити. Удост. с лице е деактивирано."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Опитайте отново."</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 301bcc0..f0787b4 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"স্বীকৃত নয়"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"আঙ্গুলের ছাপ যাচাই করা হয়েছে"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"ফেস যাচাই করা হয়েছে"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"ফেস যাচাই করা হয়েছে, \'কনফার্ম করুন\' বোতাম প্রেস করুন"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"আঙ্গুলের ছাপ নেওয়ার হার্ডওয়্যার অনুপলব্ধ৷"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"আঙ্গুলের ছাপ সংরক্ষণ করা যাবে না৷ অনুগ্রহ করে একটি বিদ্যমান আঙ্গুলের ছাপ সরান৷"</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"আঙ্গুলের ছাপ নেওয়ার সময়সীমা শেষ হযেছে৷ আবার চেষ্টা করুন৷"</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"ফেসের ছাপ নেওয়ার সময়সীমা শেষ৷ আবার চেষ্টা করুন৷"</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"ফেস স্টোর করা যাবে না।"</string>
     <string name="face_error_canceled" msgid="283945501061931023">"ফেস অপারেশন বাতিল করা হয়েছে৷"</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"ফেস যাচাইকরণ ব্যবহারকারীর দ্বারা বাতিল করা হয়েছে।"</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"অনেকবার চেষ্টা করা হয়েছে। পরে আবার চেষ্টা করুন।"</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"অনেকবার চেষ্টা করা হয়েছে৷ ফেস যাচাইকরণ বন্ধ আছে।"</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"আবার চেষ্টা করুন।"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index e6fde5b..e210d90e 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -531,10 +531,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Nije prepoznato"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Otisak prsta je potvrđen"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Lice je provjereno"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Lice je provjereno, pritisnite dugme za potvrdu"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardver za otisak prsta nije dostupan."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Otisak prsta se ne može pohraniti. Uklonite postojeći otisak prsta."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Vrijeme za prepoznavanje otiska prsta je isteklo. Pokušajte ponovo."</string>
@@ -571,8 +569,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Vrijeme za prepoznavanje lica je isteklo. Pokušajte ponovo."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Nije moguće pohraniti lice."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Prepoznavanje lica je otkazano."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Korisnik je otkazao provjeru lica."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Previše pokušaja. Pokušajte ponovo kasnije."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Previše pokušaja. Autentifikacija lica onemogućena."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Pokušajte ponovo."</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 9318715..b1d4994 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"No s\'ha reconegut"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"L\'empremta digital s\'ha autenticat"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Cara autenticada"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Cara autenticada; prem el botó per confirmar"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"El maquinari per a empremtes digitals no està disponible."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"L\'empremta digital no es pot desar. Suprimeix-ne una."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"S\'ha esgotat el temps d\'espera per a l\'empremta digital. Torna-ho a provar."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"S\'ha esgotat el temps d\'espera. Torna-ho a provar."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"La cara no es pot desar."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"S\'ha cancel·lat el reconeixement facial."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Autenticació facial cancel·lada per l\'usuari."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Massa intents. Torna-ho a provar més tard."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Massa intents. Autenticació facial desactivada."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Torna-ho a provar."</string>
@@ -814,8 +811,8 @@
     <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"Falta la targeta SIM o no es pot llegir. Insereix-ne una."</string>
     <string name="lockscreen_permanent_disabled_sim_message_short" msgid="5096149665138916184">"Targeta SIM no utilitzable."</string>
     <string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"La targeta SIM està desactivada permanentment.\n Contacta amb el teu proveïdor de serveis sense fil per obtenir-ne una altra."</string>
-    <string name="lockscreen_transport_prev_description" msgid="6300840251218161534">"Ruta anterior"</string>
-    <string name="lockscreen_transport_next_description" msgid="573285210424377338">"Ruta següent"</string>
+    <string name="lockscreen_transport_prev_description" msgid="6300840251218161534">"Pista anterior"</string>
+    <string name="lockscreen_transport_next_description" msgid="573285210424377338">"Pista següent"</string>
     <string name="lockscreen_transport_pause_description" msgid="3980308465056173363">"Posa en pausa"</string>
     <string name="lockscreen_transport_play_description" msgid="1901258823643886401">"Reprodueix"</string>
     <string name="lockscreen_transport_stop_description" msgid="5907083260651210034">"Atura"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 45c57d0..a537d6d 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -534,10 +534,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Nerozpoznáno"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Otisk byl ověřen"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Obličej byl ověřen"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Obličej byl ověřen, stiskněte tlačítko pro potvrzení"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Není k dispozici hardware ke snímání otisků prstů."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Otisk prstu nelze uložit. Odstraňte existující otisk prstu."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Časový limit sejmutí otisku prstu vypršel. Zkuste to znovu."</string>
@@ -574,8 +572,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Limit ověření obličeje vypršel. Zkuste to znovu."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Obličej nelze uložit."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Operace snímání obličeje byla zrušena."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Ověření obličeje bylo zrušeno uživatelem."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Příliš mnoho pokusů. Zkuste to později."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Příliš mnoho pokusů. Ověření obličeje je zakázáno."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Zkuste to znovu."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index f279f0b..28c08b1 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Ikke genkendt"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Fingeraftrykket blev godkendt"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Ansigtet er godkendt"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Ansigtet er godkendt. Tryk på Bekræft."</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardwaren til fingeraftryk er ikke tilgængelig."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingeraftrykket kan ikke gemmes. Fjern et eksisterende fingeraftryk."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Registrering af fingeraftryk fik timeout. Prøv igen."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Ansigtsgenkendelse fik timeout. Prøv igen."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Ansigtet kan ikke gemmes."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Ansigtshandlingen blev annulleret."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Ansigtsgodkendelsen blev annulleret af brugeren."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Du har prøvet for mange gange. Prøv igen senere."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"For mange forsøg – Ansigtsgenkendelse deaktiveret."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Prøv igen."</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 7ec4401..4a2efbd 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Nicht erkannt"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Fingerabdruck wurde authentifiziert"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Gesicht authentifiziert"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Gesicht authentifiziert, bitte bestätigen"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Fingerabdruckhardware nicht verfügbar"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingerabdruck kann nicht gespeichert werden. Entferne einen vorhandenen Fingerabdruck."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Zeitüberschreitung für Fingerabdruck. Bitte versuche es noch einmal."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Zeitüberschreitung für Gesicht. Versuch es erneut."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Gesicht kann nicht gespeichert werden."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Gesichtserkennung abgebrochen."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Gesichtsauthentifizierung vom Nutzer abgebrochen."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Zu viele Versuche. Versuch es später noch einmal."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Zu viele Versuche. Gesichtserkennung deaktiviert."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Versuch es noch einmal."</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index f2309e8..04b9749 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Δεν αναγνωρίστηκε"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Η ταυτότητα του δακτυλικού αποτυπώματος ελέγχθηκε"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Έγινε έλεγχος ταυτότητας προσώπου"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Έγινε έλεγχος ταυτότητας προσώπου, πατήστε \"Επιβεβαίωση\""</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Ο εξοπλισμός μοναδικού χαρακτηριστικού δεν είναι διαθέσιμος."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Δεν είναι δυνατή η αποθήκευση μοναδικού χαρακτηριστικού. Καταργήστε το υπάρχον μοναδικό χαρακτηριστικό."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Λήξη χρονικού ορίου μοναδικού χαρακτηριστικού. Δοκιμάστε ξανά."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Λήξη χρονικού ορίου προσώπου. Δοκιμάστε ξανά."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Δεν είναι δυνατή η αποθήκευση του προσώπου."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Η ενέργεια προσώπου ακυρώθηκε."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Ο έλεγχος ταυτότητας προσώπου ακυρώθηκε από τον χρήστη."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Πάρα πολλές προσπάθειες. Δοκιμάστε ξανά αργότερα."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Πολλές προσπάθειες. Αποτυχία ελέγ. ταυτ. προσώπου."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Δοκιμάστε ξανά."</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 1eeb1c3..8592355 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Not recognised"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Fingerprint authenticated"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Face authenticated"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Face authenticated. Please press confirm"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Fingerprint hardware not available."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingerprint can\'t be stored. Please remove an existing fingerprint."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Fingerprint timeout reached. Try again."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Face time out reached. Try again."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Face can’t be stored."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Face operation cancelled."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Face authentication cancelled by user."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Too many attempts. Try again later."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Too many attempts. Facial authentication disabled."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Try again."</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 699e50f..1e075f8 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Not recognised"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Fingerprint authenticated"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Face authenticated"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Face authenticated. Please press confirm"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Fingerprint hardware not available."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingerprint can\'t be stored. Please remove an existing fingerprint."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Fingerprint timeout reached. Try again."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Face time out reached. Try again."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Face can’t be stored."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Face operation cancelled."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Face authentication cancelled by user."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Too many attempts. Try again later."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Too many attempts. Facial authentication disabled."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Try again."</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 1eeb1c3..8592355 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Not recognised"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Fingerprint authenticated"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Face authenticated"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Face authenticated. Please press confirm"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Fingerprint hardware not available."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingerprint can\'t be stored. Please remove an existing fingerprint."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Fingerprint timeout reached. Try again."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Face time out reached. Try again."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Face can’t be stored."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Face operation cancelled."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Face authentication cancelled by user."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Too many attempts. Try again later."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Too many attempts. Facial authentication disabled."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Try again."</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 1eeb1c3..8592355 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Not recognised"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Fingerprint authenticated"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Face authenticated"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Face authenticated. Please press confirm"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Fingerprint hardware not available."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingerprint can\'t be stored. Please remove an existing fingerprint."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Fingerprint timeout reached. Try again."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Face time out reached. Try again."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Face can’t be stored."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Face operation cancelled."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Face authentication cancelled by user."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Too many attempts. Try again later."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Too many attempts. Facial authentication disabled."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Try again."</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 63726f8..9138098 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‎‎‏‎‏‎‎‏‏‏‏‏‎‎‏‏‏‏‎‎‎‏‎‎‏‏‏‎‎‏‏‎‏‎‎‏‏‎‎‎‎‎‎‏‎‎‏‎‏‎‏‎‎‏‎‎Not recognized‎‏‎‎‏‎"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎‏‎‏‏‏‎‏‎‎‎‏‎‏‏‎‎‏‎‎‎‎‎‏‎‏‎‎‎‏‎‏‏‎‎‎‏‏‎‏‎‎‎‎‎‏‎‏‏‏‏‎‎‎‎‎Fingerprint authenticated‎‏‎‎‏‎"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‎‎‎‏‎‏‎‎‏‏‏‎‎‏‎‎‎‎‏‏‏‎‏‏‎‏‎‏‎‎‎‎‎‏‎‏‏‏‎‏‎‏‎‎‎‏‎‏‎‏‎‏‏‏‎Face authenticated‎‏‎‎‏‎"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‎‏‎‏‏‏‏‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‏‎‏‎‎Face authenticated, please press confirm‎‏‎‎‏‎"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‎‎‏‎‎‎‏‏‏‎‎‏‎‎‏‏‎‎‎‏‎‏‏‎‏‎‏‏‏‏‏‎‎‏‏‏‎‎‎‏‏‏‏‎‏‎‏‎‏‎‎‎Fingerprint hardware not available.‎‏‎‎‏‎"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‎‏‏‏‎‎‎‎‎‏‎‏‏‏‎‎‏‎‎‏‏‎‎‏‏‏‎‏‎‎‏‏‏‎‎‏‏‏‏‎‎‏‎‏‏‏‎‎‎‏‏‎‎Fingerprint can\'t be stored. Please remove an existing fingerprint.‎‏‎‎‏‎"</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‎‎‎‎‎‎‎‎‎‏‎‏‎‏‎‏‏‏‎‎‏‏‎‎‏‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‏‏‎Fingerprint time out reached. Try again.‎‏‎‎‏‎"</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‏‎‏‏‎‏‎‏‏‏‎‎‎‎‎‎‎‏‎‏‏‏‎‎‏‏‎‏‏‎‎‎‎‎‏‎‏‏‏‏‎‎‎‎‎‏‏‎‏‏‏‎‎‏‏‎‎Face time out reached. Try again.‎‏‎‎‏‎"</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‎‎‏‎‏‎‎‎‎‏‏‎‎‎‎‏‏‎‎‏‎‎‎‎‎‎‏‏‎‏‏‏‏‎‎‎‎‎‎‏‏‎‎‎‎‎‎‎‎‎‎‏‎‎Face can’t be stored.‎‏‎‎‏‎"</string>
     <string name="face_error_canceled" msgid="283945501061931023">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‏‏‏‏‎‎‎‎‏‏‎‎‎‏‏‎‏‏‏‎‏‏‎‏‏‏‎‎‎‏‏‎‎‏‎‏‏‏‎‏‏‏‏‎‎‎‎‎‎‎‎‎‏‏‏‏‎Face operation canceled.‎‏‎‎‏‎"</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‎‏‏‎‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‎‏‏‎‏‎‎‏‎‏‎‏‏‎‎‎‏‏‏‎‏‏‎Face authentication canceled by user.‎‏‎‎‏‎"</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‎‎‏‎‎‏‏‎‎‏‏‏‎‎‏‏‎‎‎‏‎‏‎‎‎‎‏‎‎‎‏‏‏‏‎‏‏‏‎‎‎‎‏‎‎‎‎‏‎‏‏‎‎‎‎Too many attempts. Try again later.‎‏‎‎‏‎"</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‎‎‏‏‎‎‏‏‎‏‎‎‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‎‎‎‎‏‎‏‎‎‏‎‏‎‎‏‏‎‏‏‏‎‏‎‎Too many attempts. Facial authentication disabled.‎‏‎‎‏‎"</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‎‏‎‏‎‎‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‎‎‎‏‎‏‎‎‎‏‏‎‏‎‎‎‏‏‎‎‏‏‏‎‎‏‏‎‎Try again.‎‏‎‎‏‎"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 6a49e03..6176b7b 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"No se reconoció"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Se autenticó la huella digital"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Se autenticó el rostro"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Se autenticó el rostro; presiona Confirmar"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"El hardware para detectar huellas digitales no está disponible."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"No se puede almacenar la huella digital. Elimina una de las existentes."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Finalizó el tiempo de espera para la huella digital. Vuelve a intentarlo."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Se agotó el tiempo. Vuelve a intentarlo."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"No se puede almacenar el rostro."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Se canceló el reconocimiento facial."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"El usuario canceló la autenticación de rostro."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Demasiados intentos. Inténtalo de nuevo más tarde."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Demasiados intentos. Autent. facial inhabilitada."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Vuelve a intentarlo."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index b62f4c9..dd766f7 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"No se reconoce"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Se ha autenticado la huella digital"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Cara autenticada"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Se ha autenticado la cara, pulsa para confirmar"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"El hardware de huella digital no está disponible."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"No se puede almacenar la huella digital. Elimina una ya creada."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Se ha alcanzado el tiempo de espera de la huella digital. Vuelve a intentarlo."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Has sobrepasado el tiempo. Inténtalo de nuevo."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"No se pueden registrar más caras."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Se ha cancelado el reconocimiento facial."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"El usuario ha cancelado la autenticación de la cara."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Demasiados intentos. Inténtalo de nuevo más tarde."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Demasiados intentos. Autent. facial inhabilitada."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Inténtalo de nuevo."</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 8f011f8..650fcb6 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Ei tuvastatud"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Sõrmejälg autenditi"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Nägu on autenditud"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Nägu on autenditud, vajutage käsku Kinnita"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Sõrmejälje riistvara pole saadaval."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Sõrmejälge ei saa salvestada. Eemaldage olemasolev sõrmejälg."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Sõrmejälje riistvara taimeri ajalõpp. Proovige uuesti."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Näotuvastuse taimeri ajalõpp. Proovige uuesti."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Nägu ei saa salvestada."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Näotuvastuse toiming tühistati."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Kasutaja tühistas näo autentimise."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Liiga palju katseid. Proovige hiljem uuesti."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Liiga palju katseid. Näotuvastus on keelatud."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Proovige uuesti."</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index a070cc5..6a6fdbf 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Ez da ezagutu"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Autentifikatu da hatz-marka"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Autentifikatu da aurpegia"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Autentifikatu da aurpegia; sakatu Berretsi"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hatz-markaren hardwarea ez dago erabilgarri."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Ezin da gorde hatz-marka digitala. Kendu lehendik gordeta duzunetako bat."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Hatz-marka digitalak prozesatzeko denbora-muga gainditu da. Saiatu berriro."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Gainditu da aurpegiak prozesatzeko denbora-muga. Saiatu berriro."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Ezin da gorde aurpegia."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Utzi da aurpegiaren bidezko eragiketa."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Erabiltzaileak utzi du aurpegi-autentifikazioa."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Saiakera gehiegi egin dituzu. Saiatu berriro geroago."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Saiakera gehiegi egin dituzu. Desgaitu egin da autentifikazioa."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Saiatu berriro."</string>
@@ -1139,7 +1136,7 @@
     <string name="aerr_application_repeated" msgid="3146328699537439573">"Behin eta berriz gelditzen ari da <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
     <string name="aerr_process_repeated" msgid="6235302956890402259">"Behin eta berriz gelditzen ari da <xliff:g id="PROCESS">%1$s</xliff:g>"</string>
     <string name="aerr_restart" msgid="7581308074153624475">"Ireki aplikazioa berriro"</string>
-    <string name="aerr_report" msgid="5371800241488400617">"Bidali iritzia"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Bidali oharrak"</string>
     <string name="aerr_close" msgid="2991640326563991340">"Itxi"</string>
     <string name="aerr_mute" msgid="1974781923723235953">"Ezkutatu gailua berrabiarazi arte"</string>
     <string name="aerr_wait" msgid="3199956902437040261">"Itxaron"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 3101b72..2310f9e 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"شناسایی نشد"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"اثر انگشت احراز هویت شد"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"چهره احراز هویت شد"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"چهره احراز هویت شد، لطفاً تأیید را فشار دهید"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"سخت‌افزار اثرانگشت در دسترس نیست."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ذخیره اثر انگشت ممکن نیست. لطفاً یک اثر انگشت موجود را حذف کنید."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"مهلت زمانی ثبت اثر انگشت به پایان رسید. دوباره امتحان کنید."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"مهلت زمانی شناسایی چهره تمام شد. دوباره امتحان کنید"</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"نمی‌توان چهره را ذخیره کرد."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"عملیات شناسایی چهره لغو شد."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"احراز هویت چهره توسط کاربر لغو شد."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"تعداد زیادی تلاش ناموفق. بعداً دوباره امتحان کنید."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"چندین تلاش ناموفق. احراز هویت با چهره غیرفعال شد."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"دوباره امتحان کنید."</string>
@@ -900,7 +897,7 @@
     <string name="js_dialog_before_unload_negative_button" msgid="5614861293026099715">"ماندن در این صفحه"</string>
     <string name="js_dialog_before_unload" msgid="3468816357095378590">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nمطمئنید می‌خواهید این صفحه را ترک کنید؟"</string>
     <string name="save_password_label" msgid="6860261758665825069">"تأیید"</string>
-    <string name="double_tap_toast" msgid="4595046515400268881">"نکته: برای بزرگ‌نمایی و کوچک‌نمایی، دو بار ضربه بزنید."</string>
+    <string name="double_tap_toast" msgid="4595046515400268881">"نکته: برای نزدیک‌نمایی و دورنمایی، دو بار ضربه بزنید."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"تکمیل خودکار"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"راه‌اندازی تکمیل خودکار"</string>
     <string name="autofill_window_title" msgid="4107745526909284887">"تکمیل خودکار با <xliff:g id="SERVICENAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 346992f..4f2531c 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Ei tunnistettu"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Sormenjälki tunnistettu"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Kasvot tunnistettu"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Kasvot tunnistettu, valitse Vahvista"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Sormenjälkilaitteisto ei ole käytettävissä."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Sormenjälkeä ei voida tallentaa. Poista aiemmin lisätty sormenjälki."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Sormenjälkitunnistimen toiminta aikakatkaistiin. Yritä uudelleen."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Kasvotoiminto aikakatkaistiin. Yritä uudelleen."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Kasvoja ei voi tallentaa."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Kasvotoiminto peruutettu"</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Käyttäjä peruutti kasvojentunnistuksen."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Liian monta yritystä. Yritä myöhemmin uudelleen."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Liikaa yrityksiä. Kasvojentodennus ei käytössä."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Yritä uudelleen."</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 16fd62a..39889ec 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Données biométriques non reconnues"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Empreinte digitale authentifiée"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Visage authentifié"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Visage authentifié, veuillez appuyer sur le bouton Confirmer"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Matériel d\'empreinte numérique indisponible."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"L\'empreinte digitale ne peut pas être enregistrée. Veuillez supprimer une empreinte existante."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Le temps attribué pour lire l\'empreinte est écoulé. Veuillez essayer de nouveau."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Temps de reconn. visage écoulé. Veuillez réessayer."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Impossible de stocker le visage."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Opération de reconnaissance du visage annulée."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Authentification du visage annulée par l\'utilisateur"</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Trop de tentatives. Veuillez réessayer plus tard."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Trop de tentatives. Capt. reconn. visage désactivé."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Réessayez."</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 76eed1f..9759415 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Non reconnu"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Empreinte digitale authentifiée"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Visage authentifié"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Visage authentifié, veuillez appuyer sur \"Confirmer\""</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Matériel d\'empreinte numérique indisponible."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Impossible d\'enregistrer l\'empreinte numérique. Veuillez supprimer une empreinte."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Délai de détection de l\'empreinte numérique expiré. Veuillez réessayer."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Délai de détection du visage expiré. Réessayez."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Impossible de stocker les informations du visage."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Opération de reconnaissance faciale annulée."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Authentification faciale annulée par l\'utilisateur."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Trop de tentatives. Réessayez plus tard."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Trop d\'essais. Authentification faciale désactivée."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Réessayez."</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index f644919..318dd3e 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Non se recoñeceu"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Autenticouse a impresión dixital"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Autenticouse a cara"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Autenticouse a cara, preme Confirmar"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardware de impresión dixital non dispoñible."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Non se pode almacenar a impresión dixital. Elimina unha impresión dixital existente."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Esgotouse o tempo de espera da impresión dixital. Téntao de novo."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Esgotouse o tempo de espera. Téntao de novo."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Non se puido almacenar a cara."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Cancelouse a operación relacionada coa cara"</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"O usuario cancelou a autenticación da cara."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Demasiados intentos. Téntao de novo máis tarde."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Demasiados intentos. Autenticación desactivada."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Téntao de novo."</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 4ea553c..13090c6 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"ઓળખાયેલ નથી"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"ફિંગરપ્રિન્ટ પ્રમાણિત કરી"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"ચહેરા પ્રમાણિત"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"ચહેરા પ્રમાણિત, કૃપા કરીને કન્ફર્મ કરો"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ફિંગરપ્રિન્ટ હાર્ડવેર ઉપલબ્ધ નથી."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ફિંગરપ્રિન્ટ સંગ્રહિત કરી શકાતી નથી. કૃપા કરીને અસ્તિત્વમાંની ફિંગરપ્રિન્ટ દૂર કરો."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ફિંગરપ્રિન્ટનો સમય બાહ્ય થયો. ફરી પ્રયાસ કરો."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"ચહેરા માટેનો સમય સમાપ્ત થયો. ફરી પ્રયાસ કરો."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"ચહેરો સંગ્રહિત કરી શકાશે નહીં."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"ચહેરા સંબંધિત કાર્યવાહી રદ કરવામાં આવી છે."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"વપરાશકર્તાએ ચહેરા પ્રમાણીકરણ રદ કર્યુ."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"ઘણા બધા પ્રયત્નો. થોડા સમય પછી ફરી પ્રયાસ કરો."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"ઘણા બધા પ્રયત્નો. ચહેરાનું પ્રમાણીકરણ બંધ કરવામાં આવ્યું છે."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"ફરી પ્રયાસ કરો."</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index c24b0ae..bebd489 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -530,10 +530,8 @@
     <!-- no translation found for biometric_not_recognized (5770511773560736082) -->
     <skip />
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"फ़िंगरप्रिंट की पुष्टि हो गई"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"चेहरे की पहचान की गई"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"चेहरे की पहचान की गई, कृपया पुष्टि बटन दबाएं"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"फ़िंगरप्रिंट हार्डवेयर उपलब्ध नहीं है."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"फ़िंगरप्रिंट को संग्रहित नहीं किया जा सका. कृपया कोई मौजूदा फ़िंगरप्रिंट निकालें."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"फ़िंगरप्रिंट का समय समाप्त हो गया. पुनः प्रयास करें."</string>
@@ -570,8 +568,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"चेहरे की पहचान का समय खत्म हुआ. फिर से कोशिश करें."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"चेहरा सेव करने की सीमा पूरी हो गई है."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"चेहरा पहचानने की कार्रवाई रद्द की गई."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"उपयोगकर्ता ने चेहरे की पहचान रद्द कर दी."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"कई बार कोशिश की गई. बाद में कोशिश करें."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"कई बार कोशिश की. चेहरा पहचानने की सुविधा बंद हुई."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"फिर से कोशिश करें."</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 6a9d307..839d423 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -531,10 +531,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Nije prepoznato"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Autentificirano otiskom prsta"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Lice je autentificirano"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Lice je autentificirano, pritisnite Potvrdi"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardver za otisak prsta nije dostupan."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Otisak prsta nije pohranjen. Uklonite postojeći otisak prsta."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Isteklo je vrijeme čekanja za otisak prsta. Pokušajte ponovo."</string>
@@ -571,8 +569,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Isteklo je vrijeme čekanja za lice. Pokušajte opet"</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Nije moguće pohraniti lice."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Otkazana je radnja s licem."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Autentifikaciju lica otkazao je korisnik."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Previše pokušaja. Pokušajte ponovo kasnije."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Previše pokušaja. Autentifikacija lica onemogućena"</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Pokušajte ponovo."</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 474c73a..bc54bfa 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Nem ismerhető fel"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Ujjlenyomat hitelesítve"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Arc hitelesítve"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Arc hitelesítve; nyomja meg a Megerősítés lehetőséget"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Az ujjlenyomathoz szükséges hardver nem érhető el."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Az ujjlenyomat nem tárolható. Távolítson el egy meglévő ujjlenyomatot."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Az ujjlenyomat-beolvasási műveletkor időtúllépés történt. Próbálkozzon újra."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Időtúllépés az arcbeolvasásnál. Próbálja újra."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Az arc nem tárolható."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Az arccal kapcsolatos művelet törölve."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Az arc hitelesítését a felhasználó visszavonta."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Túl sok próbálkozás. Próbálja újra később."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Túl sok próbálkozás. Arcfelismerés letiltva."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Próbálkozzon újra."</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index b9e6c62..4a828fa 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Չհաջողվեց ճանաչել"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Մատնահետքը նույնականացվեց"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Դեմքը ճանաչվեց"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Դեմքը ճանաչվեց: Սեղմեք «Հաստատել»:"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Մատնահետքի սարքն անհասանելի է:"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Հնարավոր չէ պահել մատնահետքը: Հեռացրեք առկա մատնահետքը:"</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Մատնահետքի գրանցման ժամանակը սպառվել է: Փորձեք նորից:"</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Ժամանակը սպառվել է: Նորից փորձեք:"</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Դեմքը հնարավոր չէ պահել։"</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Դեմքի ճանաչումը չեղարկվել է։"</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Դեմքի ճանաչումը չեղարկվել է օգտատիրոջ կողմից:"</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Չափից շատ փորձեր եք կատարել: Փորձեք ավելի ուշ:"</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Չափից շատ փորձեր եք կատարել: Դեմքի ճանաչման գործառույթն անջատվել է։"</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Նորից փորձեք:"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 8298a18..167082d 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Tidak dikenali"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Sidik jari diautentikasi"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Wajah diautentikasi"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Wajah diautentikasi, silakan tekan konfirmasi"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardware sidik jari tidak tersedia."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Sidik jari tidak dapat disimpan. Hapus sidik jari yang ada."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Waktu sidik jari habis. Coba lagi."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Waktu tunggu wajah habis. Harap coba lagi."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Wajah tidak dapat disimpan."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Pemrosesan wajah dibatalkan."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Autentikasi wajah dibatalkan oleh pengguna."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Terlalu banyak percobaan. Coba lagi nanti."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Terlalu sering dicoba. Autentikasi wajah dinonaktifkan."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Coba lagi."</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 2649a1a..0c7e6b8 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Þekktist ekki"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Fingrafar staðfest"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Andlit staðfest"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Andlit staðfest, ýttu til að staðfesta"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Fingrafarsvélbúnaður ekki til staðar."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Ekki er hægt að vista fingrafarið. Fjarlægðu eitthvert af fingraförunum sem fyrir eru."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tímamörk runnu út fyrir fingrafar. Reyndu aftur."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Tímamörk runnu út fyrir andlit. Reyndu aftur."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Ekki tókst að geyma andlit."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Hætt við andlitsgreiningu."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Notandi hætti við andlitsgreiningu."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Of margar tilraunir. Reyndu aftur síðar."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Of margar tilraunir. Slökkt á andlitsgreiningu."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Reyndu aftur."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 5c28097..a6d5d23 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Non riconosciuto"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Impronta digitale autenticata"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Volto autenticato"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Volto autenticato, premi Conferma"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardware per l\'impronta digitale non disponibile."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Impossibile memorizzare l\'impronta digitale. Rimuovi un\'impronta esistente."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Timeout impronta digitale. Riprova."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Timeout operazione associata al volto. Riprova."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Il volto non può essere memorizzato."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Operazione associata al volto annullata."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Autenticazione del volto annullata dall\'utente."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Troppi tentativi. Riprova più tardi."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Troppi tentativi. Autenticazione disattivata."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Riprova."</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 5dd1617..48933f9 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -534,10 +534,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"לא זוהתה"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"טביעת האצבע אומתה"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"זיהוי הפנים בוצע"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"זיהוי הפנים בוצע. יש ללחוץ על אישור"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"החומרה בשביל טביעת אצבע אינה זמינה."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"לא ניתן לאחסן טביעת אצבע. הסר טביעת אצבע קיימת."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"חלף הזמן הקצוב לטביעת אצבע. נסה שוב."</string>
@@ -574,8 +572,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"חלף הזמן הקצוב לזיהוי הפנים. יש לנסות שוב."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"לא ניתן לשמור את הפנים."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"פעולת הפנים בוטלה."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"זיהוי הפנים בוטל על ידי המשתמש."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"יותר מדי ניסיונות. יש לנסות שוב מאוחר יותר."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"יותר מדי ניסיונות. אימות הפנים הושבת."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"יש לנסות שוב."</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 7b53ed4..994039c 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"認識されませんでした"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"指紋認証を完了しました"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"顔を認証しました"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"顔を認証しました。[確認] を押してください"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"指紋ハードウェアは使用できません。"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"指紋を保存できません。既存の指紋を削除してください。"</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"指紋の読み取りがタイムアウトになりました。もう一度お試しください。"</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"読み取りのタイムアウトです。もう一度お試しください。"</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"顔の情報を保存できません。"</string>
     <string name="face_error_canceled" msgid="283945501061931023">"顔の操作をキャンセルしました。"</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"顔の認証がユーザーによりキャンセルされました。"</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"試行回数の上限です。後でもう一度お試しください。"</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"試行回数の上限です。顔認証は無効になりました。"</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"もう一度お試しください。"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 7226296..a9ce748 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"არ არის ამოცნობილი"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"თითის ანაბეჭდი ავტორიზებულია"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"სახე ავტორიზებულია"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"სახე ავტორიზებულია, დააჭირეთ დადასტურებას"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"თითის ანაბეჭდის აპარატურა არ არის ხელმისაწვდომი."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"თითის ანაბეჭდის შენახვა ვერ ხერხდება. გთხოვთ, ამოშალოთ არსებული თითის ანაბეჭდი."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"თითის ანაბეჭდის ლოდინის დრო ამოიწურა. სცადეთ ხელახლა."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"სახის ამოცნობის დრო ამოიწურა. ცადეთ ხელახლა."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"სახის შენახვა ვერ მოხერხდა."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"სახის ამოცნობა გაუქმდა."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"სახის ავტორიზაცია გაუქმდა მომხმარებლის მიერ."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"დაფიქსირდა ბევრი მცდელობა. ცადეთ მოგვიანებით."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"დაფიქსირდა ბევრი მცდელობა. სახის ამოცნობა გაითიშა."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"ცადეთ ხელახლა."</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 457933e..a8b527b 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Танылмады"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Саусақ ізі аутентификацияланды"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Бет танылды"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Бет танылды, \"Растау\" түймесін басыңыз"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Саусақ ізі жабдығы қолжетімді емес."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Саусақ ізін сақтау мүмкін емес. Бар саусақ ізін жойыңыз."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Саусақ ізін күту уақыты бітті. Әрекетті қайталаңыз."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Күту уақыты бітті. Әрекетті қайталаңыз."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Бетті сақтау мүмкін емес."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Бетті танудан бас тартылды."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Пайдаланушы бетті тану әрекетінен бас тартты."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Тым көп әрекет жасалды. Кейінірек қайталаңыз."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Тым көп әрекет жасалды. Бетті тану функциясы өшірілді."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Қайталап көріңіз."</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index b3a3a01..2620ce4 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"មិនអាចសម្គាល់បានទេ"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"បាន​ផ្ទៀង​ផ្ទាត់​ស្នាម​ម្រាមដៃ"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"បានផ្ទៀងផ្ទាត់​មុខ"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"បានផ្ទៀងផ្ទាត់​មុខ សូម​ចុច​បញ្ជាក់"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ផ្នែករឹងស្នាមម្រាមដៃមិនមានទេ។"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"មិនអាចផ្ទុកស្នាមម្រាមដៃទេ។ សូមយកស្នាមម្រាមដៃដែលមានស្រាប់ចេញ។"</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ការផ្តិតម្រាមដៃបានអស់ពេល។ សូមព្យាយាមម្តងទៀត។"</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"ការសម្គាល់​ផ្ទៃមុខ​បាន​អស់ម៉ោង។ សូមព្យាយាមម្ដងទៀត។"</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"មិន​អាច​រក្សាទុក​ផ្ទៃ​មុខ​បានទេ។"</string>
     <string name="face_error_canceled" msgid="283945501061931023">"បាន​បោះបង់​ប្រតិបត្តិការចាប់​ផ្ទៃមុខ។"</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"ការផ្ទៀងផ្ទាត់​មុខ​ត្រូវបានបោះបង់ដោយអ្នកប្រើប្រាស់។"</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"ព្យាយាមចូលច្រើនពេកហើយ។ សូមព្យាយាមម្តងទៀតពេលក្រោយ។"</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"ព្យាយាមចូលច្រើនពេកហើយ។ បាន​បិទការផ្ទៀងផ្ទាត់​ផ្ទៃ​មុខ។"</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"សូមព្យាយាម​ម្ដងទៀត។"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 2dc0bb1..1b83ec2 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"ಗುರುತಿಸಲಾಗಿಲ್ಲ"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಅನ್ನು ಪ್ರಮಾಣೀಕರಣ ಮಾಡಲಾಗಿದೆ"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"ಮುಖವನ್ನು ದೃಢೀಕರಿಸಲಾಗಿದೆ"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"ಮುಖವನ್ನು ದೃಢೀಕರಿಸಲಾಗಿದೆ, ದೃಢೀಕರಣವನ್ನು ಒತ್ತಿ"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ಬೆರಳಚ್ಚು ಹಾರ್ಡ್‌ವೇರ್‌ ಲಭ್ಯವಿಲ್ಲ."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ಬೆರಳಚ್ಚು ಸಂಗ್ರಹಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಬೆರಳಚ್ಚು ತೆಗೆದುಹಾಕಿ."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ಬೆರಳಚ್ಚು ಅವಧಿ ಮೀರಿದೆ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"ಮುಖ ಸಮಯದ ಅವಧಿಯನ್ನು ತಲುಪಿದೆ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"ಮುಖವನ್ನು ಸಂಗ್ರಹಿಸಲಾಗುವುದಿಲ್ಲ."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"ಮುಖದ ಕಾರ್ಯಚರಣೆಯನ್ನು ರದ್ದುಗೊಳಿಸಲಾಗಿದೆ."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"ಮುಖ ದೃಢೀಕರಣವನ್ನು ಬಳಕೆದಾರರ ಮೂಲಕ ರದ್ದುಗೊಳಿಸಲಾಗಿದೆ."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"ಹಲವು ಬಾರಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. ನಂತರ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"ಹಲವು ಪ್ರಯತ್ನ. ಮುಖದ ದೃಢೀಕರಣ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index abed24c..6223dab 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"인식할 수 없음"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"지문이 인증됨"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"얼굴이 인증되었습니다"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"얼굴이 인증되었습니다. 확인을 누르세요"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"지문 인식 하드웨어를 사용할 수 없습니다."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"지문을 저장할 수 없습니다. 기존 지문을 삭제하세요."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"지문 인식 시간이 초과되었습니다. 다시 시도하세요."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"얼굴 인식 시간이 초과되었습니다. 다시 시도하세요."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"얼굴을 저장할 수 없습니다."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"얼굴 인식 작업이 취소되었습니다."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"사용자가 얼굴 인증을 취소했습니다."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"시도 횟수가 너무 많습니다. 나중에 다시 시도하세요."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"시도 횟수가 너무 많아 얼굴 인증이 사용 중지되었습니다."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"다시 시도해 보세요."</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index fb8a816..f49746f 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Таанылган жок"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Манжа изинин аныктыгы текшерилди"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Жүздүн аныктыгы текшерилди"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Жүздүн аныктыгы текшерилди, эми \"Ырастоону\" басыңыз"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Манжа изинин аппараттык камсыздоосу жеткиликтүү эмес."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Манжа изин сактоо мүмкүн эмес. Учурдагы манжа изин алып салыңыз."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Манжа изин күтүү мөөнөтү бүттү. Кайра аракет кылыңыз."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Жүздүн аныктыгын текшерүүнү күтүү мөөнөтү бүттү. Кайра аракет кылыңыз."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Жүздү сактоо мүмкүн эмес."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Жүздүн аныктыгын текшерүү жокко чыгарылды."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Жүздүн аныктыгын текшерүү колдонуучу аркылуу жокко чыгарылды."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Өтө көп жолу аракет жасадыңыз. Кийинчерээк кайра аракет кылыңыз."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Өтө көп жолу аракет жасадыңыз. Жүздүн аныктыгын текшерүү сенсору өчүрүлдү."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Кайра аракет кылыңыз."</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 8b6a052..9fc6033 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"ບໍ່ຮັບຮູ້"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"ພິສູດຢືນຢັນລາຍນິ້ວມືແລ້ວ"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"ພິສູດຢືນຢັນໃບໜ້າແລ້ວ"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"ພິສູດຢືນຢັນໃບໜ້າແລ້ວ, ກະລຸນາກົດຢືນຢັນ"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ບໍ່​ມີ​ຮາດ​ແວລາຍ​ນີ້ວ​ມື​ໃຫ້​ຢູ່."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ບໍ່​ສາ​ມາດ​ເກັບ​ຮັກ​ສາ​ລາຍ​ນີ້ວ​ມື​ໄວ້​ໄດ້. ກະ​ລຸ​ນາ​ເອົາ​ລາຍ​ນີ້ວ​ມື​ທີ່​ມີ​ຢູ່​ອອກ​ໄປ."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ເວ​ລາ​ລາຍ​ນີ້ວ​ມື​ບໍ່​ເຂົ້າ​ເຖິງ​ໄດ້. ລອງ​ໃໝ່​ອີກ."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"ໝົດເວລາກວດໃບໜ້າແລ້ວ. ກະລຸນາລອງອີກຄັ້ງ."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"ບໍ່ສາມາດເກັບຮັກສາໃບໜ້າໄວ້ໄດ້."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"ຍົກເລີກການດຳເນີນການກັບໃບໜ້າແລ້ວ."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"ຜູ້ໃຊ້ຍົກເລີກການພິສູດຢືນຢັນໃບໜ້າແລ້ວ."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"ມີຄວາມພະຍາຍາມຫຼາຍຄັ້ງເກີນໄປ. ກະລຸນາລອງໃໝ່ໃນພາຍຫຼັງ."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"ມີຄວາມພະຍາຍາມຫຼາຍຄັ້ງເກີນໄປ. ປິດນຳໃຊ້ການກວດສອບຄວາມຖືກຕ້ອງດ້ວຍໃບໜ້າແລ້ວ."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"ລອງອີກຄັ້ງ."</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 7fc1c98..d6869c1 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -534,10 +534,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Neatpažinta"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Kontrolinis kodas autentifikuotas"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Veidas autentifikuotas"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Veidas autentifikuotas, paspauskite patvirtinimo mygtuką"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Kontrolinio kodo aparatinė įranga nepasiekiama."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Negalima išsaugoti kontrolinio kodo. Pašalinkite esamą kontrolinį kodą."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Baigėsi kontrolinio kodo nustatymo skirtasis laikas. Bandykite dar kartą."</string>
@@ -574,8 +572,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Baigėsi veido atpaž. skirt. laik. Band. dar kartą."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Nepavyko išsaugoti veido duomenų."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Veido atpažinimo operacija atšaukta."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Veido autentifikavimą atšaukė naudotojas."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Per daug bandymų. Vėliau bandykite dar kartą."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Per daug bandymų. Veido autentifik. išjungtas."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Bandykite dar kartą."</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 60a32de..156a1a9 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -531,10 +531,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Dati nav atpazīti"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Pirksta nospiedums tika autentificēts."</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Seja autentificēta"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Seja ir autentificēta. Nospiediet pogu Apstiprināt."</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Nospieduma aparatūra nav pieejama."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Pirkstu nospiedumu nevar saglabāt. Lūdzu, noņemiet esošu pirksta nospiedumu."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Pirkstu nospiedumu nolasīšanas aparatūras noildze. Mēģiniet vēlreiz."</string>
@@ -571,8 +569,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Sejas datu nolasīšanas noildze. Mēģiniet vēlreiz."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Sejas datus nevar saglabāt."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Darbība ar sejas datiem atcelta."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Lietotājs atcēla sejas autentificēšanu."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Pārāk daudz mēģinājumu. Vēlāk mēģiniet vēlreiz."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Par daudz mēģinājumu. Sejas atpazīšana atspējota."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Mēģiniet vēlreiz."</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 4ae6f31..8bca75e 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Непознат"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Отпечатокот е проверен"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Лицето е проверено"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Лицето е проверено, притиснете го копчето „Потврди“"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Хардвер за отпечаток од прст не е достапен."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Отпечатокот не може да се складира. Отстранете го постоечкиот отпечаток."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Се достигна времето на истекување на отпечатокот. Обидете се повторно."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Истече времето за проверка на лице. Повторен обид."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Лицето не може да се чува."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Операцијата со лице се откажа."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Проверката на лицето е откажана од корисникот."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Премногу обиди. Обидете се повторно подоцна."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Премногу обиди. Проверката на лице е оневозможена."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Обидете се повторно."</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 2cd83cc..1efdc72 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"തിരിച്ചറിഞ്ഞില്ല"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"ഫിംഗർപ്രിന്റ് പരിശോധിച്ചുറപ്പിച്ചു"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"മുഖം പരിശോധിച്ചുറപ്പിച്ചു"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"മുഖം പരിശോധിച്ചുറപ്പിച്ചു, സ്ഥിരീകരിക്കുക അമർത്തുക"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ഫിംഗർപ്രിന്റ് ഹാർഡ്‌വെയർ ലഭ്യമല്ല."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"വിരലടയാളം സംഭരിക്കാനാവില്ല. നിലവിലുള്ള വിരലടയാളം നീക്കംചെയ്യുക."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"വിരലടയാളം നൽകേണ്ട സമയം കഴിഞ്ഞു. വീണ്ടും ശ്രമിക്കുക."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"മുഖം നൽകേണ്ട സമയം കഴിഞ്ഞു. വീണ്ടും ശ്രമിക്കുക."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"മുഖം സൂക്ഷിക്കാനാവില്ല."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"മുഖത്തിന്റെ പ്രവർത്തനം റദ്ദാക്കി."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"മുഖം പരിശോധിച്ചുറപ്പിക്കൽ ഉപയോക്താവ് റദ്ദാക്കി."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"നിരവധി തവണ ശ്രമിച്ചു. പിന്നീട് വീണ്ടും ശ്രമിക്കുക."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"നിരവധി തവണ ശ്രമിച്ചു. മുഖം തിരിച്ചറിയൽ പ്രവർത്തനരഹിതമാക്കി."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"വീണ്ടും ശ്രമിക്കുക."</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 35936ee..86ae178 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Таниагүй"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Хурууны хээг нотолсон"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Царайг баталгаажууллаа"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Царайг баталгаажууллаа. Баталгаажуулах товчлуурыг дарна уу"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Хурууны хээний тоног төхөөрөмж бэлэн бус байна."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Хурууны хээг хадгалах боломжгүй байна. Одоо байгаа хурууны хээг арилгана уу."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Хурууны хээ оруулах хугацаа өнгөрсөн байна. Дахин оруулна уу."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Царай таниулах хугацаа дууслаа. Дахин оролдоно уу."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Царайг хадгалах боломжгүй байна."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Царайны үйл ажиллагааг цуцаллаа."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Хэрэглэгч царайгаар баталгаажуулахыг цуцалсан байна."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Хэт олон удаа оролдлоо. Дараа дахин оролдоно уу."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Хэт олон удаа оролдлоо. Царай танилтыг идэвхгүй болголоо."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Дахин оролдоно уу."</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index ec96ec1..70ed012 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"ओळखले नाही"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"फिंगरप्रिंट ऑथेंटिकेट केली आहे"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"चेहरा ऑथेंटिकेशन केलेला आहे"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"चेहरा ऑथेंटिकेशन केलेला आहे, कृपया कंफर्म दाबा"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"फिंगरप्रिंट हार्डवेअर उपलब्‍ध नाही."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"फिंगरप्रिंट स्टोअर केले जाऊ शकत नाही. कृपया विद्यमान फिंगरप्रिंट काढा."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"फिंगरप्रिंट टाइमआउट झाले. पुन्हा प्रयत्न करा."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"चेहरा टाइमआउट झाला. पुन्हा प्रयत्न करा."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"चेहरा स्टोअर केला जाऊ शकत नाही."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"चेहरा ऑपरेशन रद्द केले गेले."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"वापरकर्त्याने चेहरा ऑथेंटिकेशन रद्द केले."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"खूप जास्त प्रयत्न केले. नंतर पुन्हा प्रयत्न करा."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"खूप जास्त प्रयत्न केले. चेहरा ऑथेंटिकेशन बंद केले गेले."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"पुन्हा प्रयत्न करा."</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 7de8dc1..208fed6 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Tidak dikenali"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Cap jari disahkan"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Wajah disahkan"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Wajah disahkan, sila tekan sahkan"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Perkakasan cap jari tidak tersedia."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Cap jari tidak dapat disimpan. Sila alih keluar cap jari sedia ada."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tamat masa cap jari dicapai. Cuba lagi."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Tamat masa wajah dicapai. Cuba lagi."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Wajah tidak dapat disimpan."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Pengendalian wajah dibatalkan."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Pengesahan wajah dibatalkan oleh pengguna."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Terlalu banyak percubaan. Cuba sebentar lagi."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Terlalu banyak percubaan. Pengesahan wajah dilumpuhkan."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Cuba lagi."</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 9f107f8..71dd4b6 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"မသိပါ"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"လက်ဗွေကို အထောက်အထား စိစစ်ပြီးပါပြီ"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"မျက်နှာ အထောက်အထားစိစစ်ပြီးပြီ"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"မျက်နှာ အထောက်အထားစိစစ်ပြီးပြီ၊ အတည်ပြုရန်ကို နှိပ်ပါ"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"လက်ဗွေရာ ဟာ့ဒ်ဝဲ မရနိုင်ပါ။"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"လက်ဗွေရာ သိုလှောင်၍မရပါ။ ကျေးဇူးပြု၍ ရှိပြီးလက်ဗွေရာအား ဖယ်ရှားပါ။"</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"လက်ဗွေရာအချိန်ကုန် သွားပါသည်။ ထပ်မံကြိုးစားပါ။"</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"မျက်နှာ သက်တမ်းကုန်သွားပါပြီ။ ထပ်စမ်းကြည့်ပါ။"</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"မျက်နှာကို သိမ်း၍မရပါ။"</string>
     <string name="face_error_canceled" msgid="283945501061931023">"မျက်နှာ ဆောင်ရွက်ခြင်းကို ပယ်ဖျက်လိုက်ပါပြီ။"</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"အသုံးပြုသူက မျက်နှာအထောက်အထားစိစစ်မှု မလုပ်တော့ပါ။"</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"အကြိမ်များစွာ စမ်းပြီးပါပြီ။ နောက်မှထပ်စမ်းပါ။"</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"အကြိမ်များစွာ စမ်းပြီးပါပြီ။ ပိတ်လိုက်ပါပြီ။"</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"ထပ်စမ်းကြည့်ပါ။"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index d315aca..28e7d33 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Ikke gjenkjent"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Fingeravtrykket er godkjent"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Ansiktet er autentisert"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Ansiktet er autentisert. Trykk på Bekreft"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Maskinvare for fingeravtrykk er ikke tilgjengelig."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingeravtrykket kan ikke lagres. Fjern et eksisterende fingeravtrykk."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tidsavbrudd for fingeravtrykk er nådd. Prøv på nytt."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Tidsavbrudd for ansikt er nådd. Prøv igjen."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Ansiktet kan ikke lagres."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Ansikt-operasjonen ble avbrutt."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Ansiktsautentiseringen ble avbrutt av brukeren."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"For mange forsøk. Prøv igjen senere."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"For mange forsøk. Ansiktsautentisering er slått av."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Prøv igjen."</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index c67a871..875f87d 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"पहिचान भएन"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"फिंगरप्रिन्ट प्रमाणीकरण गरियो"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"अनुहार प्रमाणीकरण गरियो"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"अनुहार प्रमाणीकरण गरियो, कृपया पुष्टि गर्नुहोस् थिच्नुहोस्"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"औँठाछाप हार्डवेयर उपलब्ध छैन।"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"औँठाछाप भण्डारण गर्न सकिँदैन। कृपया अवस्थित औठाछाप हटाउनुहोस्।"</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"औँठाछापको समय सकिएको छ। फेरि प्रयास गर्नुहोस्।"</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"अनुहारको समय सकिएको छ। फेरि प्रयास गर्नुहोस्‌।"</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"अनुहार भण्डारण गर्न सकिँदैन।"</string>
     <string name="face_error_canceled" msgid="283945501061931023">"अनुहार पहिचान रद्द गरियो।"</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"प्रयोगकर्ताले अनुहार प्रमाणीकरण रद्द गर्नु भयो।"</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"धेरैपटक प्रयासहरू भए। पछि फेरि प्रयास गर्नुहोस्‌।"</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"अत्यधिक धेरैपटक गलत प्रयासहरू भए। अनुहार प्रमाणिकरणलाई असक्षम पारियो।"</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"फेरि प्रयास गर्नुहोस्।"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 345d9d4..b95ba19 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Niet herkend"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Vingerafdruk geverifieerd"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Gezicht geverifieerd"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Gezicht geverifieerd. Druk op Bevestigen."</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardware voor vingerafdruk niet beschikbaar."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Vingerafdruk kan niet worden opgeslagen. Verwijder een bestaande vingerafdruk."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Time-out bereikt voor vingerafdruk. Probeer het opnieuw."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Time-out voor gezicht bereikt. Probeer opnieuw."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Gezicht kan niet worden opgeslagen."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Bewerking voor gezichtsherkenning geannuleerd."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Gezichtsverificatie geannuleerd door gebruiker."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Te veel pogingen. Probeer het later opnieuw."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Te veel pogingen. Gezichtsherkenning inactief."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Probeer het opnieuw."</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 3e4260f..9d3fa8e 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"ଚିହ୍ନଟ ହେଲାନାହିଁ"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ପ୍ରମାଣୀକୃତ ହେଲା"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"ମୁହଁ ଚିହ୍ନଟ ହୋଇଛି"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"ମୁହଁ ଚିହ୍ନଟ ହୋଇଛି, ଦୟାକରି ସୁନିଶ୍ଚିତ ଦବାନ୍ତୁ"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ହାର୍ଡୱେର୍‍ ଉପଲବ୍ଧ ନାହିଁ।"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ଷ୍ଟୋର୍‍ କରାଯାଇପାରିବ ନାହିଁ। ଦୟାକରି ପୂର୍ବରୁ ଥିବା ଆଙ୍ଗୁଠି ଚିହ୍ନକୁ ବାହାର କରିଦିଅନ୍ତୁ।"</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ଆଙ୍ଗୁଠି ଚିହ୍ନର ସମୟ ଶେଷ ହେଲା । ପୁଣିଥରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"ଫେସ୍‍ର ସମୟସୀମା ସରିଗଲା। ପୁଣିଥରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"ଫେସ୍‍ ମେମୋରୀରେ ଷ୍ଟୋର୍‍ କରାଯାଇପାରିବ ନାହିଁ।"</string>
     <string name="face_error_canceled" msgid="283945501061931023">"ଫେସ୍‍ର ଅପରେଶନ୍‍ କ୍ୟାନ୍ସଲ୍‍ ହୋ‍ଇଗଲା"</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"ଉପଯୋଗକର୍ତ୍ତା ମୁହଁ ଚିହ୍ନଟକରଣ ବାତିଲ୍‌ କରିଛନ୍ତି।"</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"ବାରମ୍ବାର ଚେଷ୍ଟା। ପରେ ପୁଣିଥରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"ବାରମ୍ବାର ଚେଷ୍ଟା। ଫେସ୍‍ ପ୍ରମାଣୀକରଣ ଅକ୍ଷମ କରାଗଲା।"</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"ପୁଣିଥରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index bdcf2fe..6e615a8 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"ਪਛਾਣ ਨਹੀਂ ਹੋਈ"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਪ੍ਰਮਾਣਿਤ ਹੋਇਆ"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"ਚਿਹਰਾ ਪੁਸ਼ਟੀਕਰਨ"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"ਚਿਹਰਾ ਪੁਸ਼ਟੀਕਰਨ, ਕਿਰਪਾ ਕਰਕੇ \'ਪੁਸ਼ਟੀ ਕਰੋ\' ਦਬਾਓ"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਹਾਰਡਵੇਅਰ ਉਪਲਬਧ ਨਹੀਂ।"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸਟੋਰ ਨਹੀਂ ਕੀਤਾ ਸਕਦਾ। ਕਿਰਪਾ ਕਰਕੇ ਇੱਕ ਮੌਜੂਦਾ ਫਿੰਗਰਪ੍ਰਿੰਟ ਹਟਾਓ।"</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਦਾ ਸਮਾਂ ਸਮਾਪਤ ਹੋ ਗਿਆ ਹੈ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"ਚਿਹਰਾ ਪਛਾਣਨ ਦਾ ਸਮਾਂ ਸਮਾਪਤ ਹੋਇਆ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"ਚਿਹਰੇ ਦੀ ਜਾਣਕਾਰੀ ਨੂੰ ਸਟੋਰ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ।"</string>
     <string name="face_error_canceled" msgid="283945501061931023">"ਚਿਹਰਾ ਪਛਾਣਨ ਦੀ ਪ੍ਰਕਿਰਿਆ ਰੱਦ ਕੀਤੀ ਗਈ।"</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"ਵਰਤੋਂਕਾਰ ਵੱਲੋਂ ਚਿਹਰਾ ਪੁਸ਼ਟੀਕਰਨ ਨੂੰ ਰੱਦ ਕੀਤਾ ਗਿਆ।"</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"ਹੱਦੋਂ ਵੱਧ ਕੋਸ਼ਿਸ਼ਾਂ। ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"ਹੱਦੋਂ ਵੱਧ ਕੋਸ਼ਿਸ਼ਾਂ। ਚਿਹਰਾ ਪ੍ਰਮਾਣੀਕਰਨ ਬੰਦ ਹੈ।"</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 3e08d50..81a869a 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -534,10 +534,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Nie rozpoznano"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Uwierzytelniono odciskiem palca"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Twarz rozpoznana"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Twarz rozpoznana, kliknij Potwierdź"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Czytnik linii papilarnych nie jest dostępny."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Nie można zapisać odcisku palca. Usuń istniejący odcisk palca."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Osiągnięto limit czasu odczytu linii papilarnych. Spróbuj ponownie."</string>
@@ -574,8 +572,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Upłynął limit czasu analizy twarzy. Spróbuj ponownie."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Nie można zapisać informacji o twarzy."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Analiza twarzy została anulowana."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Użytkownik anulował uwierzytelnianie twarzą."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Zbyt wiele prób. Spróbuj ponownie później."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Zbyt wiele prób. Wyłączono uwierzytelnianie za pomocą twarzy."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Spróbuj ponownie."</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index d604aab..5ac7c2e 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Não reconhecido"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Impressão digital autenticada"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Rosto autenticado"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Rosto autenticado, pressione \"Confirmar\""</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardware de impressão digital não disponível."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Não foi possível armazenar a impressão digital. Remova uma impressão digital já existente."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tempo máximo para captura da impressão digital atingido. Tente novamente."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Tempo máx. p/ captura facial atingido. Tente novamente."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Não é possível armazenar um rosto."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Operação facial cancelada."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Autenticação facial cancelada pelo usuário."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Excesso de tentativas. Tente novamente mais tarde."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Excesso de tentativas. Autenticação facial desat."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Tente novamente."</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index cde63d5..52f067f 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -423,11 +423,11 @@
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"alterar as suas definições de áudio"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permite que a aplicação modifique definições de áudio globais, tais como o volume e qual o altifalante utilizado para a saída de som."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"gravar áudio"</string>
-    <string name="permdesc_recordAudio" msgid="4245930455135321433">"Esta aplicação pode gravar áudio através do microfone a qualquer momento."</string>
+    <string name="permdesc_recordAudio" msgid="4245930455135321433">"Esta aplicação pode gravar áudio através do microfone em qualquer altura."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"enviar comandos para o SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Permite que a aplicação envie comandos para o SIM. Esta ação é muito perigosa."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"tirar fotos e vídeos"</string>
-    <string name="permdesc_camera" msgid="5392231870049240670">"Esta aplicação pode tirar fotos e gravar vídeos através da câmara a qualquer momento."</string>
+    <string name="permdesc_camera" msgid="5392231870049240670">"Esta aplicação pode tirar fotos e gravar vídeos através da câmara em qualquer altura."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"controlar vibração"</string>
     <string name="permdesc_vibrate" msgid="6284989245902300945">"Permite à aplicação controlar o vibrador."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"marcar números de telefone diretamente"</string>
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Não reconhecido."</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"A impressão digital foi autenticada."</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Rosto autenticado."</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Rosto autenticado. Prima Confirmar."</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardware de impressão digital não disponível."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Não é possível armazenar a impressão digital. Remova uma impressão digital existente."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Foi atingido o limite de tempo da impressão digital. Tente novamente."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Limite de tempo de rosto atingido. Tente novamente."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Não é possível armazenar o rosto."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Operação de rosto cancelada."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Autenticação facial cancelada pelo utilizador."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Demasiadas tentativas. Tente novamente mais tarde."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Demasiadas tentativas. Autenticação facial desativada."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Tente novamente."</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index d604aab..5ac7c2e 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Não reconhecido"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Impressão digital autenticada"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Rosto autenticado"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Rosto autenticado, pressione \"Confirmar\""</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardware de impressão digital não disponível."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Não foi possível armazenar a impressão digital. Remova uma impressão digital já existente."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tempo máximo para captura da impressão digital atingido. Tente novamente."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Tempo máx. p/ captura facial atingido. Tente novamente."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Não é possível armazenar um rosto."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Operação facial cancelada."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Autenticação facial cancelada pelo usuário."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Excesso de tentativas. Tente novamente mais tarde."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Excesso de tentativas. Autenticação facial desat."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Tente novamente."</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index add43b8..0c945f7 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -531,10 +531,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Nu este recunoscut"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Amprentă autentificată"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Chip autentificat"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Chip autentificat, apăsați Confirmați"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardware-ul pentru amprentă nu este disponibil."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Amprenta nu poate fi stocată. Eliminați o amprentă existentă."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Timpul pentru amprentare a expirat. Încercați din nou."</string>
@@ -571,8 +569,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Timpul pentru reunoaștere facială a expirat. Încercați din nou."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Chipul nu poate fi stocat."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Operațiunea privind chipul a fost anulată."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Autentificarea chipului anulată de utilizator."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Prea multe încercări. Reîncercați mai târziu."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Prea multe încercări. Autentificarea facială este dezactivată."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Încercați din nou."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 3a4ed82..fd70e9c 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -534,10 +534,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Не распознано"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Отпечаток пальца проверен"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Лицо распознано"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Лицо распознано, нажмите кнопку \"Подтвердить\""</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Сканер недоступен"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Чтобы сохранить новый отпечаток, удалите существующий."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Превышено время ожидания. Повторите попытку."</string>
@@ -574,8 +572,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Превышено время ожидания. Повторите попытку."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Невозможно сохранить распознанное лицо"</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Распознавание отменено"</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Распознавание лица отменено пользователем."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Слишком много попыток. Повторите позже."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Слишком много попыток. Сканер отключен."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Попробуйте ещё раз"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 17ead66..3bd8ceb 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"හඳුනා නොගන්නා ලදී"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"ඇඟිලි සලකුණ සත්‍යාපනය කරන ලදී"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"මුහුණ සත්‍යාපනය කරන ලදී"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"මුහුණ සත්‍යාපනය කරන ලදී, කරුණාකර තහවුරු කරන්න ඔබන්න"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ඇඟිලි සලකුණු දෘඪාංගය ලද නොහැකිය."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ඇඟිලි සලකුණ ගබඩා කළ නොහැක. දැනට පවතින ඇඟිලි සලකුණක් ඉවත් කරන්න."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ඇඟිලි සලකුණු කාල නිමාව ළඟා විය. නැවත උත්සාහ කරන්න."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"මුහුණු කාල නිමාව ළඟා විය. නැවත උත්සාහ කරන්න."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"මුහුණ ගබඩා කළ නොහැක."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"මුහුණු මෙහෙයුම අවලංගු කරන ලදී."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"පරිශීලකයා විසින් මුහුණ සත්‍යාපනය අවලංගු කරන ලදී."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"උත්සාහයන් ඉතා වැඩි ගණනකි. පසුව නැවත උත්සාහ කරන්න."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"උත්සාහයන් ඉතා වැඩි ගණනකි. මුහුණු සත්‍යාපනය අබල කරන ලදී."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"නැවත උත්සාහ කරන්න."</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index cb44b74..c0981ce 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -534,10 +534,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Nerozpoznané"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Odtlačok bol overený"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Tvár bola overená"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Tvár bola overená, stlačte tlačidlo potvrdenia"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardvér na snímanie odtlačku prsta nie je k dispozícii"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Odtlačok prsta nie je možné uložiť. Odstráňte existujúci odtlačok."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Časový limit rozpoznania odtlačku vypršal. Skúste to znova."</string>
@@ -574,8 +572,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Limit rozpoznania tváre vypršal. Skúste to znova."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Tvár sa nedá uchovať."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Operácia týkajúca sa tváre bola zrušená"</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Overenie tváre bolo zrušené používateľom."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Príliš veľa pokusov. Skúste to znova neskôr."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Príliš veľa pokusov. Overenie tváre je zakázané."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Skúste to znova."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 039bbaa..261e6ed 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -534,10 +534,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Ni prepoznano"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Pristnost prstnega odtisa je preverjena"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Pristnost obraza je potrjena"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Pristnost obraza je preverjena. Pritisnite gumb »Potrdi«."</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Strojna oprema za prstne odtise ni na voljo."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Prstnega odtisa ni mogoče shraniti. Odstranite obstoječi prstni odtis."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Dosežena časovna omejitev za prstni odtis. Poskusite znova."</string>
@@ -574,8 +572,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Dosežena časovna omejitev za obraz. Poskusite znova."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Obraza ni mogoče shraniti."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Dejanje z obrazom je bilo preklicano."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Preverjanje pristnosti obraza preklical uporabnik"</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Preveč poskusov. Poskusite znova pozneje."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Preveč poskusov. Preverjanje pristnosti obraza je onemogočeno."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Poskusite znova."</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index ee0960b..4b6cb09 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Nuk njihet"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Gjurma e gishtit u vërtetua"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Fytyra u vërtetua"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Fytyra u vërtetua, shtyp \"Konfirmo\""</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardueri i gjurmës së gishtit nuk mundësohet."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Gjurma e gishtit nuk mund të ruhet. Hiq një gjurmë gishti ekzistuese."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Koha e veprimit për gjurmën e gishtit skadoi. Provo përsëri."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Mbaroi afati për fytyrën. Provo sërish."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Fytyra nuk mund të ruhet."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Veprimi me fytyrën u anulua."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Vërtetimi me fytyrë u anulua nga përdoruesi."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Shumë përpjekje. Provo sërish më vonë."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Shumë përpjekje. Vërtetimi për fytyrën joaktiv."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Provo sërish."</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 6ff3a78..449fdfc 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -531,10 +531,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Није препознато"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Отисак прста је потврђен"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Лице је потврђено"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Лице је потврђено. Притисните Потврди"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Хардвер за отиске прстију није доступан."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Није могуће сачувати отисак прста. Уклоните неки од постојећих отисака прстију."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Временско ограничење за отисак прста је истекло. Пробајте поново."</string>
@@ -571,8 +569,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Истекло је време за проверу лица. Пробајте поново."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Није могуће сачувати лице."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Обрада лица је отказана."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Корисник је отказао потврду лица."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Превише покушаја. Пробајте поново касније."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Више покушаја. Потврда идентитета је онемогућена."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Пробајте поново."</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 20969d3..9f46514 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Identifierades inte"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Fingeravtrycket har autentiserats"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Ansiktet har autentiserats"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Ansiktet har autentiserats. Tryck på Bekräfta"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Det finns ingen maskinvara för fingeravtryck."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingeravtrycket kan inte lagras. Ta bort ett befintligt fingeravtryck."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tidsgränsen för fingeravtrycket har uppnåtts. Försök igen."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Tidsgränsen för ansikte har nåtts. Försök igen."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Det gick inte att lagra ansiktet."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Ansiktsåtgärden har avbrutits."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Autentiseringen av ansiktet avbröts av användaren."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Du har gjort för många försök. Försök igen senare."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"För många försök. Ansiktsautentisering inaktiverad"</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Försök igen."</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index ce81bc7..b0858dc 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -130,9 +130,9 @@
   </string-array>
     <!-- no translation found for wfcSpnFormat_spn (4998685024207291232) -->
     <skip />
-    <string name="wfcSpnFormat_spn_wifi_calling" msgid="136001023263502280">"<xliff:g id="SPN">%s</xliff:g>Kupiga simu Kupitia Wi-Fi"</string>
+    <string name="wfcSpnFormat_spn_wifi_calling" msgid="136001023263502280">"Kupiga Simu Kupitia Wi-Fi ya <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wlan_call" msgid="2533371081782489793">"Simu ya WLAN"</string>
-    <string name="wfcSpnFormat_spn_wlan_call" msgid="2315240198303197168">"<xliff:g id="SPN">%s</xliff:g> Simu ya WLAN"</string>
+    <string name="wfcSpnFormat_spn_wlan_call" msgid="2315240198303197168">"Simu ya WLAN ya <xliff:g id="SPN">%s</xliff:g>"</string>
     <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>
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Hayatambuliki"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Imethibitisha alama ya kidole"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Uso umethibitishwa"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Uso umethibitishwa, tafadhali bonyeza thibitisha"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Maunzi ya kitambulisho hayapatikani."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Kitambulisho hakiwezi kuhifadhiwa. Tafadhali ondoa kitambulisho kilichopo."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Muda wa kitambulisho umekwisha. Jaribu tena."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Muda wa kutambua uso umeisha. Jaribu tena."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Huwezi kuhifadhi uso."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Utendaji wa kitambulisho umeghairiwa."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Uthibitishaji wa uso umeghairiwa na mtumiaji."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Umejaribu mara nyingi mno. Jaribu tena baadaye."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Umejaribu mara nyingi mno. Kitambuzi cha uso kimezimwa."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Jaribu tena."</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 9683e4c..b84d68e 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"அடையாளங்காணபடவில்லை"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"கைரேகை அங்கீகரிக்கப்பட்டது"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"முகம் அங்கீகரிக்கப்பட்டது"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"முகம் அங்கீகரிக்கப்பட்டது. ’உறுதிப்படுத்துக’ என்பதை அழுத்துக"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"கைரேகை வன்பொருள் இல்லை."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"கைரேகையைச் சேமிக்க முடியவில்லை. ஏற்கனவே உள்ள கைரேகையை அகற்றவும்."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"கைரேகைக்கான நேரம் முடிந்தது. மீண்டும் முயலவும்."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"முகப் பதிவிற்கான நேரம் முடிந்தது. மீண்டும் முயல்க."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"முகத்தைச் சேமிக்க இயலாது."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"முக அங்கீகாரச் செயல்பாடு ரத்துசெய்யப்பட்டது."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"பயனர், முக அங்கீகாரத்தை ரத்துசெய்தார்."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"பலமுறை முயன்றுவிட்டீர்கள். பிறகு முயலவும்."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"பலமுறை தோல்வி. முக அங்கீகாரம் முடக்கப்பட்டது."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"மீண்டும் முயலவும்."</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 9757720..a5430b6 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"గుర్తించలేదు"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"వేలిముద్ర ప్రమాణీకరించబడింది"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"ముఖం ప్రమాణీకరించబడింది"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"ముఖం ప్రమాణీకరించబడింది, దయచేసి ధృవీకరించును నొక్కండి"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"వేలిముద్ర హార్డ్‌వేర్ అందుబాటులో లేదు."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"వేలిముద్రను నిల్వ చేయడం సాధ్యపడదు. దయచేసి ఇప్పటికే ఉన్న వేలిముద్రను తీసివేయండి."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"వేలిముద్ర గడువు సమయం చేరుకుంది. మళ్లీ ప్రయత్నించండి."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"ముఖ గడువు సమయం చేరుకుంది. మళ్లీ ప్రయత్నించండి."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"ముఖం నిల్వ చేయబడదు."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"ముఖ కార్యకలాపం రద్దయింది."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"వినియోగదారు ద్వారా ముఖ ప్రమాణీకరణ రద్దు చేయబడింది."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"చాలా ఎక్కువ ప్రయత్నాలు చేసారు. తర్వాత మళ్లీ ప్రయత్నించండి."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"చాలా ఎక్కువ ప్రయత్నాలు చేసారు. ముఖ ప్రమాణీకరణ నిలిపివేయబడింది."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"మళ్లీ ప్రయత్నించండి."</string>
diff --git a/core/res/res/values-television/themes.xml b/core/res/res/values-television/themes.xml
index 0712cbc..48b59c7 100644
--- a/core/res/res/values-television/themes.xml
+++ b/core/res/res/values-television/themes.xml
@@ -15,7 +15,6 @@
 -->
 <resources>
     <style name="Theme.Dialog.Alert" parent="Theme.Leanback.Light.Dialog.Alert" />
-    <style name="Theme.DeviceDefault.Dialog.AppError" parent="Theme.Leanback.Dialog.AppError" />
     <style name="Theme.Holo.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
     <style name="Theme.Holo.Light.Dialog.Alert" parent="Theme.Leanback.Light.Dialog.Alert" />
     <style name="Theme.Material.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
diff --git a/core/res/res/values-television/themes_device_defaults.xml b/core/res/res/values-television/themes_device_defaults.xml
index 293591a..fdd0624 100644
--- a/core/res/res/values-television/themes_device_defaults.xml
+++ b/core/res/res/values-television/themes_device_defaults.xml
@@ -15,8 +15,20 @@
 -->
 <resources>
     <style name="Theme.DeviceDefault.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
+    <style name="Theme.DeviceDefault.Dialog.AppError" parent="Theme.Leanback.Dialog.AppError" />
     <style name="Theme.DeviceDefault.Light.Dialog.Alert" parent="Theme.Leanback.Light.Dialog.Alert" />
-    <style name="Theme.DeviceDefault.Autofill" parent="Theme.Material.Autofill" />
-    <style name="Theme.DeviceDefault.Autofill.Save" parent="Theme.Material.Autofill.Save" />
+
+    <!-- TODO(b/116457731): remove colorBackground from colors_material.xml if not used anymore -->
+    <style name="Theme.DeviceDefault.Autofill" parent="Theme.Material">
+        <item name="colorBackground">@color/autofill_background_material_dark</item>
+    </style>
+    <style name="Theme.DeviceDefault.Autofill.Save" parent="Theme.Material.Panel">
+        <item name="colorBackground">@color/autofill_background_material_dark</item>
+    </style>
+
+    <!-- TV always use dark mode -->
+    <style name="Theme.DeviceDefault.Autofill.Light" parent="Theme.DeviceDefault.Autofill"/>
+    <style name="Theme.DeviceDefault.Light.Autofill.Save" parent="Theme.DeviceDefault.Autofill.Save"/>
+
     <style name="Theme.DeviceDefault.Resolver" parent="Theme.Leanback.Resolver" />
 </resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 89202ca..0b7e031 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"ไม่รู้จัก"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"ตรวจสอบสิทธิ์ลายนิ้วมือแล้ว"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"ตรวจสอบสิทธิ์ใบหน้าแล้ว"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"ตรวจสอบสิทธิ์ใบหน้าแล้ว โปรดกดยืนยัน"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ฮาร์ดแวร์ลายนิ้วมือไม่พร้อมใช้งาน"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ไม่สามารถเก็บลายนิ้วมือได้ โปรดนำลายนิ้วมือที่มีอยู่ออก"</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"หมดเวลาใช้ลายนิ้วมือแล้ว โปรดลองอีกครั้ง"</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"หมดเวลาใช้ใบหน้าแล้ว โปรดลองอีกครั้ง"</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"จัดเก็บข้อมูลใบหน้าไม่ได้"</string>
     <string name="face_error_canceled" msgid="283945501061931023">"ยกเลิกการดำเนินการกับใบหน้าแล้ว"</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"ผู้ใช้ยกเลิกการตรวจสอบสิทธิ์ใบหน้า"</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"ดำเนินการหลายครั้งเกินไป ลองอีกครั้งในภายหลัง"</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"ดำเนินการหลายครั้งเกินไป ปิดใช้การตรวจสอบสิทธิ์ด้วยใบหน้าแล้ว"</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"ลองอีกครั้ง"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 983b53f..e21f59c 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Hindi nakilala"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Na-authenticate ang fingerprint"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Na-authenticate ang mukha"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Na-authenticate ang mukha, pakipindot ang kumpirmahin"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hindi available ang hardware na ginagamitan ng fingerprint."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Hindi maiimbak ang fingerprint. Mangyaring mag-alis ng umiiral nang fingerprint."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Nag-time out ang fingerprint. Subukang muli."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Nag-time out ang mukha. Subukang muli."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Hindi ma-store ang mukha."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Nakansela ang operation kaugnay ng mukha."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Kinansela ng user ang pag-authenticate ng mukha."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Masyadong maraming pagsubok. Subukang muli mamaya."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Sobrang pagsubok. Bawal na: facial authentication."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Subukang muli."</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 0315276..912db20 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Tanınmadı"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Parmak izi kimlik doğrulaması yapıldı"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Yüz kimliği doğrulandı"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Yüz kimliği doğrulandı, lütfen onayla\'ya basın"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Parmak izi donanımı kullanılamıyor."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Parmak izi depolanamıyor. Lütfen mevcut parmak izlerinden birini kaldırın."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Parmak izi için zaman aşımı oluştu. Tekrar deneyin."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Yüz için zaman aşımı oluştu. Tekrar deneyin."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Yüz kaydedilemiyor."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Yüz işlemi iptal edildi."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Yüz kimlik doğrulama işlemini kullanıcı iptal etti."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Çok fazla deneme yapıldı. Daha sonra tekrar deneyin."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Çok fazla deneme yapıldı. Yüz kimlik doğrulaması devre dışı bırakıldı."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Tekrar deneyin."</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 88e2475..f84e3e2 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -534,10 +534,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Не розпізнано"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Відбиток автентифіковано"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Обличчя автентифіковано"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Обличчя автентифіковано. Натисніть \"Підтвердити\""</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Апаратне забезпечення для сканування відбитка недоступне."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Не вдалося зберегти відбиток. Видаліть наявний відбиток."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Час очікування відбитка минув. Повторіть спробу."</string>
@@ -574,8 +572,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Час очікування обличчя минув. Повторіть спробу."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Не вдається зберегти обличчя."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Дію з обличчям скасовано."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Користувач скасував автентифікацію облич."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Забагато спроб. Повторіть пізніше."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Забагато спроб. Автентифікацію обличчя вимкнено."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Повторіть спробу."</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 6e98ebb..dc801cd 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"تسلیم شدہ نہیں ہے"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"فنگر پرنٹ کی تصدیق ہو گئی"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"چہرے کی تصدیق ہو گئی"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"چہرے کی تصدیق ہو گئی، براہ کرم \'تصدیق کریں\' کو دبائيں"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"فنگر پرنٹ ہارڈ ویئر دستیاب نہیں ہے۔"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"فنگر پرنٹ اسٹور نہیں کیا جا سکتا ہے۔ براہ کرم ایک موجودہ فنگر پرنٹ ہٹائیں۔"</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"فنگر پرنٹ کی میعاد ختم ہوگئی۔ دوبارہ کوشش کریں۔"</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"چہرہ پہچانے کی میعاد ختم ہو گئی۔ دوبارہ کوشش کریں۔"</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"چہرے کو اسٹور نہیں کیا جا سکتا۔"</string>
     <string name="face_error_canceled" msgid="283945501061931023">"چہرے پر ہونے والی کارروائی منسوخ ہو گئی۔"</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"صارف نے چہرے کی تصدیق کو مسترد کر دیا۔"</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"کافی زیادہ کوششیں کی گئیں۔ دوبارہ کوشش کریں۔"</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"کافی زیادہ کوششیں کی گئیں۔ چہرے کی توثیق منسوخ ہو گئی۔"</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"دوبارہ کوشش کریں۔"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 15671d1..e51b810 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Aniqlanmadi"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Barmoq izi tekshirildi"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Yuzingiz aniqlandi"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Yuzingiz aniqlandi, tasdiqlash uchun bosing"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Barmoq izi skaneri ish holatida emas."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Barmoq izini saqlab bo‘lmadi. Mavjud barmoq izlaridan birini o‘chirib tashlang."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Barmoq izini aniqlash vaqti tugab qoldi. Qayta urinib ko‘ring."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Yuzni aniqlash vaqti tugadi. Qaytadan urining."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Aniqlangan yuz saqlanmadi."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Yuzni aniqlash bekor qilindi."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Yuz tekshiruvi bekor qilindi."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Juda ko‘p urinildi. Keyinroq qaytadan urining."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Juda ko‘p urinildi. Skaner faolsizlantirildi."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Qaytadan urining."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 00ebbbc..4d8a20b 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Không nhận dạng được"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Đã xác thực vân tay"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Đã xác thực khuôn mặt"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Đã xác thực khuôn mặt, vui lòng nhấn để xác nhận"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Phần cứng vân tay không khả dụng."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Không thể lưu vân tay. Vui lòng xóa vân tay hiện có."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Đã hết thời gian chờ vân tay. Hãy thử lại."</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Đã hết thời gian chờ khuôn mặt. Hãy thử lại."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Không thể lưu khuôn mặt."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Đã hủy thao tác dùng khuôn mặt."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Người dùng đã hủy thao tác xác thực khuôn mặt."</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Bạn đã thử quá nhiều lần. Hãy thử lại sau."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Đã thử quá nhiều lần. Đã tắt xác thực khuôn mặt."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Hãy thử lại."</string>
diff --git a/core/res/res/values-watch/themes.xml b/core/res/res/values-watch/themes.xml
deleted file mode 100644
index 1be47ba..0000000
--- a/core/res/res/values-watch/themes.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<resources>
-    <!-- Theme for the dialog shown when an app crashes or ANRs. Override to make it dark. -->
-    <style name="Theme.DeviceDefault.Dialog.AppError" parent="Theme.DeviceDefault.Dialog.Alert">
-        <item name="windowContentTransitions">false</item>
-        <item name="windowActivityTransitions">false</item>
-        <item name="windowCloseOnTouchOutside">false</item>
-    </style>
-</resources>
diff --git a/core/res/res/values-watch/themes_device_defaults.xml b/core/res/res/values-watch/themes_device_defaults.xml
index a7736e7c..bfba312 100644
--- a/core/res/res/values-watch/themes_device_defaults.xml
+++ b/core/res/res/values-watch/themes_device_defaults.xml
@@ -422,6 +422,13 @@
         <item name="secondaryContentAlpha">@dimen/secondary_content_alpha_device_default</item>
     </style>
 
+    <!-- Theme for the dialog shown when an app crashes or ANRs. Override to make it dark. -->
+    <style name="Theme.DeviceDefault.Dialog.AppError" parent="Theme.DeviceDefault.Dialog.Alert">
+        <item name="windowContentTransitions">false</item>
+        <item name="windowActivityTransitions">false</item>
+        <item name="windowCloseOnTouchOutside">false</item>
+    </style>
+
     <style name="Theme.DeviceDefault.SearchBar" parent="Theme.Material.SearchBar">
         <!-- Color palette Dark -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index e60afa7..609f9bcf 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"无法识别"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"已验证指纹"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"面孔已验证"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"面孔已验证,请按确认按钮"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"指纹硬件无法使用。"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"无法存储指纹。请移除一个现有的指纹。"</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"指纹录入操作超时,请重试。"</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"面孔处理操作超时,请重试。"</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"无法存储面孔。"</string>
     <string name="face_error_canceled" msgid="283945501061931023">"面孔处理操作已取消。"</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"用户已取消面孔验证。"</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"尝试次数过多,请稍后重试。"</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"尝试次数过多,系统已停用人脸身份验证功能。"</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"请重试。"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index cb93c61..2e3c7d7 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"未能識別"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"驗證咗指紋"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"面孔已經驗證"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"面孔已經驗證,請㩒一下 [確認]"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"無法使用指紋軟件。"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"指紋無法儲存。請移除現有指紋。"</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"指紋已逾時。請再試一次。"</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"臉孔操作已逾時,請再試一次。"</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"無法儲存臉孔。"</string>
     <string name="face_error_canceled" msgid="283945501061931023">"臉孔操作已取消。"</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"使用者已取消臉孔驗證。"</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"嘗試次數過多,請稍後再試。"</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"嘗試次數過多,臉孔驗證已停用。"</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"請再試一次。"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 9c3d75b..9149f47 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"無法辨識"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"指紋驗證成功"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"臉孔驗證成功"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"臉孔驗證成功,請按下 [確認] 按鈕"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"指紋硬體無法使用。"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"無法儲存指紋,請先移除現有指紋。"</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"指紋處理作業逾時,請再試一次。"</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"臉孔處理作業逾時,請再試一次。"</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"無法儲存臉孔。"</string>
     <string name="face_error_canceled" msgid="283945501061931023">"臉孔處理作業已取消。"</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"使用者已取消臉孔驗證。"</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"嘗試次數過多,請稍後再試。"</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"嘗試次數過多,臉孔驗證功能已停用。"</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"請再試一次。"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 07c05aa..75709ca 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -528,10 +528,8 @@
   </string-array>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Akwaziwa"</string>
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Isingxivizo somunwe sigunyaziwe"</string>
-    <!-- no translation found for face_authenticated_no_confirmation_required (4018680978348659031) -->
-    <skip />
-    <!-- no translation found for face_authenticated_confirmation_required (8778347003507633610) -->
-    <skip />
+    <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Ubuso bufakazelwe ubuqiniso"</string>
+    <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Ukuqinisekiswa kobuso, sicela ucindezele okuthi qinisekisa"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Izingxenyekazi zekhompuyutha zezingxivizo zeminwe azitholakali."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Izigxivizo zeminwe azikwazi ukugcinwa. Sicela ususe izigxivizo zeminwe ezikhona."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Kufinyelelwe isikhathi sokuvala sezigxivizo zeminwe. Zama futhi"</string>
@@ -568,8 +566,7 @@
     <string name="face_error_timeout" msgid="4014326147867150054">"Kufinyelelwe kusikhathi sokuvala sobuso. Zama futhi."</string>
     <string name="face_error_no_space" msgid="8224993703466381314">"Ubuso abukwazi ukugcinwa."</string>
     <string name="face_error_canceled" msgid="283945501061931023">"Umsebenzi wobuso ukhanselwe."</string>
-    <!-- no translation found for face_error_user_canceled (8943921120862164539) -->
-    <skip />
+    <string name="face_error_user_canceled" msgid="8943921120862164539">"Ukufakazela ubuqiniso kobuso kukhanselwe umsebenzisi"</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"Imizamo eminingi kakhulu. Zama futhi emuva kwesikhathi."</string>
     <string name="face_error_lockout_permanent" msgid="8198354656746088890">"Imizamo eminingi kakhulu. Ukufakazela ubuqiniso kobuso kukhutshaziwe."</string>
     <string name="face_error_unable_to_process" msgid="238761109287767270">"Zama futhi."</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 65b8807..e0db946 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1425,7 +1425,7 @@
              at {@link android.view.inputmethod.InputConnection#performEditorAction(int)
              InputConnection.performEditorAction(int)}.
              <p>Corresponds to
-             {@link android.view.inputmethod.EditorInfo#IME_FLAG_NO_FULLSCREEN}. -->
+             {@link android.view.inputmethod.EditorInfo#IME_FLAG_NAVIGATE_PREVIOUS}. -->
         <flag name="flagNavigatePrevious" value="0x4000000" />
         <!-- Used to specify that there is something
              interesting that a forward navigation can focus on. This is like using
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 3c0e51e..8ff29ba 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1102,6 +1102,10 @@
          <p>The default value of this attribute is <code>false</code>. -->
     <attr name="isFeatureSplit" format="boolean" />
 
+    <!-- Flag to specify if this APK requires at least one split [either feature or
+         resource] to be present in order to function. Default value is false. -->
+    <attr name="isSplitRequired" format="boolean" />
+
     <!-- Extra options for an activity's UI. Applies to either the {@code <activity>} or
          {@code <application>} tag. If specified on the {@code <application>}
          tag these will be considered defaults for all activities in the
@@ -1422,6 +1426,7 @@
         <attr name="targetSandboxVersion" />
         <attr name="compileSdkVersion" />
         <attr name="compileSdkVersionCodename" />
+        <attr name="isSplitRequired" />
     </declare-styleable>
 
     <!-- The <code>application</code> tag describes application-level components
diff --git a/core/res/res/values/colors_car.xml b/core/res/res/values/colors_car.xml
index 6053728..32671ac8 100644
--- a/core/res/res/values/colors_car.xml
+++ b/core/res/res/values/colors_car.xml
@@ -17,15 +17,271 @@
  */
 -->
 <resources>
-  <!-- car support colors from
-  https://cs.corp.google.com/android/frameworks/support/car/res/values/colors.xml -->
-  <color name="car_user_switcher_user_image_bgcolor">@color/car_grey_50</color>
-  <color name="car_user_switcher_user_image_fgcolor">@color/car_grey_900</color>
-  <color name="car_card_dark">@color/car_dark_blue_grey_700</color>
-  <color name="car_body1_light">@color/car_grey_100</color>
+    <color name="car_background">@color/black</color>
 
-  <color name="car_grey_50">#fffafafa</color>
-  <color name="car_grey_900">#ff212121</color>
-  <color name="car_dark_blue_grey_700">#ff172026</color>
-  <color name="car_grey_100">#fff5f5f5</color>
+    <color name="car_colorPrimary">@color/car_grey_868</color>
+    <color name="car_colorSecondary">@color/car_grey_900</color>
+    <color name="car_colorPrimaryDark">@color/car_grey_958</color>
+
+
+    <!-- Various colors for text sizes. "Light" and "dark" here refer to the lighter or darker
+          shades. -->
+    <color name="car_title_light">@color/car_grey_100</color>
+    <color name="car_title_dark">@color/car_grey_900</color>
+    <color name="car_title">@color/car_title_light</color>
+
+    <color name="car_title2_light">@color/car_grey_100</color>
+    <color name="car_title2_dark">@color/car_grey_900</color>
+    <color name="car_title2">@color/car_title2_light</color>
+
+    <color name="car_headline1_light">@color/car_grey_100</color>
+    <color name="car_headline1_dark">@color/car_grey_800</color>
+    <color name="car_headline1">@color/car_headline1_light</color>
+
+    <color name="car_headline2_light">@color/car_grey_100</color>
+    <color name="car_headline2_dark">@color/car_grey_900</color>
+    <color name="car_headline2">@color/car_headline2_light</color>
+
+    <color name="car_headline3_light">@android:color/white</color>
+    <color name="car_headline3_dark">@color/car_grey_900</color>
+    <color name="car_headline3">@color/car_headline3_light</color>
+
+    <color name="car_headline4_light">@android:color/white</color>
+    <color name="car_headline4_dark">@android:color/black</color>
+    <color name="car_headline4">@color/car_headline4_light</color>
+
+    <color name="car_body1_light">@color/car_grey_100</color>
+    <color name="car_body1_dark">@color/car_grey_900</color>
+    <color name="car_body1">@color/car_body1_light</color>
+
+    <color name="car_body2_light">@color/car_grey_300</color>
+    <color name="car_body2_dark">@color/car_grey_700</color>
+    <color name="car_body2">@color/car_body2_light</color>
+
+    <color name="car_body3_light">@android:color/white</color>
+    <color name="car_body3_dark">@android:color/black</color>
+    <color name="car_body3">@color/car_body3_light</color>
+
+    <color name="car_body4_light">@android:color/white</color>
+    <color name="car_body4_dark">@android:color/black</color>
+    <color name="car_body4">@color/car_body4_light</color>
+
+    <color name="car_action1_light">@color/car_grey_900</color>
+    <color name="car_action1_dark">@color/car_grey_50</color>
+    <color name="car_action1">@color/car_action1_light</color>
+
+    <!-- The tinting colors to create a light- and dark-colored icon respectively. -->
+    <color name="car_tint_light">@color/car_grey_50</color>
+    <color name="car_tint_dark">@color/car_grey_900</color>
+
+    <!-- The tinting color for an icon. This icon is assumed to be on a light background. -->
+    <color name="car_tint">@color/car_tint_light</color>
+
+    <!-- An inverted tinting from car_tint. -->
+    <color name="car_tint_inverse">@color/car_tint_dark</color>
+
+    <!-- The color of the divider. The color here is a lighter shade. -->
+    <color name="car_list_divider_light">#1fffffff</color>
+
+    <!-- The color of the divider. The color here is a darker shade. -->
+    <color name="car_list_divider_dark">#1f000000</color>
+
+    <!-- The color of the dividers in the list. This color is assumed to be on a light colored
+         view. -->
+    <color name="car_list_divider">@color/car_list_divider_light</color>
+
+    <!-- A light and dark colored card. -->
+    <color name="car_card_light">@color/car_grey_50</color>
+    <color name="car_card_dark">@color/car_dark_blue_grey_700</color>
+
+    <!-- The default color of a card in car UI. -->
+    <color name="car_card">@color/car_card_dark</color>
+
+    <!-- The ripple colors. The "dark" and "light" designation here refers to the color of the
+         ripple  itself. -->
+    <color name="car_card_ripple_background_dark">#8F000000</color>
+    <color name="car_card_ripple_background_light">#27ffffff</color>
+
+    <!-- The ripple color for a light colored card. -->
+    <color name="car_card_ripple_background">@color/car_card_ripple_background_light</color>
+
+    <!-- The ripple color for a dark-colored card. This color is the opposite of
+         car_card_ripple_background. -->
+    <color name="car_card_ripple_background_inverse">@color/car_card_ripple_background_dark</color>
+
+    <!-- The top margin before the start of content in an application. -->
+    <dimen name="app_header_height">96dp</dimen>
+
+    <!-- The lighter and darker color for the scrollbar thumb. -->
+    <color name="car_scrollbar_thumb_light">#99ffffff</color>
+    <color name="car_scrollbar_thumb_dark">#7f0b0f12</color>
+
+    <!-- The color of the scroll bar indicator in the PagedListView. This color is assumed to be on
+         a light-colored background. -->
+    <color name="car_scrollbar_thumb">@color/car_scrollbar_thumb_light</color>
+
+    <!-- The inverted color of the scroll bar indicator. This color is always the opposite of
+         car_scrollbar_thumb. -->
+    <color name="car_scrollbar_thumb_inverse">@color/car_scrollbar_thumb_dark</color>
+
+    <!-- The color of the seekbar track secondary progress in SeekbarListItem. -->
+    <color name="car_seekbar_track_secondary_progress">@color/car_grey_500</color>
+
+    <!-- The lighter and darker color for the seekbar track background. -->
+    <color name="car_seekbar_track_background_light">@color/car_grey_400</color>
+    <color name="car_seekbar_track_background_dark">@color/car_grey_700</color>
+    <!-- The color of the seekbar track background in SeekbarListItem. This color is assumed to be
+         on a light-colored background. -->
+    <color name="car_seekbar_track_background">@color/car_seekbar_track_background_dark</color>
+    <!-- background is car_grey_868 with .9 alpha -->
+    <color name="car_toast_background">#E6282a2d</color>
+
+    <!-- Misc colors -->
+    <color name="car_highlight_light">@color/car_teal_700</color>
+    <color name="car_highlight_dark">@color/car_teal_200</color>
+    <color name="car_highlight">@color/car_highlight_dark</color>
+    <color name="car_accent_light">@color/car_highlight_light</color>
+    <color name="car_accent_dark">@color/car_highlight_dark</color>
+    <color name="car_accent">@color/car_highlight_dark</color>
+
+    <color name="car_user_switcher_user_image_bgcolor">@color/car_grey_50</color>
+    <color name="car_user_switcher_user_image_fgcolor">@color/car_grey_900</color>
+
+    <!-- Color palette for cars -->
+    <color name="car_grey_958">#ff0e1013</color>
+    <color name="car_grey_928">#ff17181b</color>
+    <color name="car_grey_900">#ff202124</color>
+    <color name="car_grey_868">#ff282a2d</color>
+    <color name="car_grey_846">#ff2e3234</color>
+    <color name="car_grey_800">#ff3c4043</color>
+    <color name="car_grey_772">#ff464a4d</color>
+    <color name="car_grey_746">#ff4d5256</color>
+    <color name="car_grey_700">#ff5f6368</color>
+    <color name="car_grey_600">#ff80868b</color>
+    <color name="car_grey_500">#ff9aa0a6</color>
+    <color name="car_grey_400">#ffbdc1c6</color>
+    <color name="car_grey_300">#ffdadce0</color>
+    <color name="car_grey_200">#ffe8eaed</color>
+    <color name="car_grey_100">#fff1f3f4</color>
+    <color name="car_grey_50">#fff8f9fa</color>
+
+    <color name="car_blue_900">#ff1d57a9</color>
+    <color name="car_blue_800">#ff2065bb</color>
+    <color name="car_blue_700">#ff2374ce</color>
+    <color name="car_blue_600">#ff2581df</color>
+    <color name="car_blue_500">#ff5195ea</color>
+    <color name="car_blue_400">#ff6ba5ed</color>
+    <color name="car_blue_300">#ff96bff2</color>
+    <color name="car_blue_200">#ffb9d4f6</color>
+    <color name="car_blue_100">#ffd9e6f9</color>
+    <color name="car_blue_50">#ffebf1fc</color>
+
+    <color name="car_green_900">#ff136e39</color>
+    <color name="car_green_800">#ff1b7e42</color>
+    <color name="car_green_700">#ff218c48</color>
+    <color name="car_green_600">#ff28994f</color>
+    <color name="car_green_500">#ff41af6a</color>
+    <color name="car_green_400">#ff5dba80</color>
+    <color name="car_green_300">#ff8dcfa5</color>
+    <color name="car_green_200">#ffb3dfc3</color>
+    <color name="car_green_100">#ffd5ebdf</color>
+    <color name="car_green_50">#ffe8f3ee</color>
+
+    <color name="car_red_900">#ffa81314</color>
+    <color name="car_red_800">#ffb41b1a</color>
+    <color name="car_red_700">#ffc22a2a</color>
+    <color name="car_red_600">#ffd33b30</color>
+    <color name="car_red_500">#ffe25142</color>
+    <color name="car_red_400">#ffe66a5e</color>
+    <color name="car_red_300">#ffed968d</color>
+    <color name="car_red_200">#fff3b9b3</color>
+    <color name="car_red_100">#fff7d8d9</color>
+    <color name="car_red_50">#fffaebeb</color>
+
+    <color name="car_yellow_900">#ffdd860e</color>
+    <color name="car_yellow_800">#ffe59810</color>
+    <color name="car_yellow_700">#ffeda912</color>
+    <color name="car_yellow_600">#fff3b713</color>
+    <color name="car_yellow_500">#fff5c518</color>
+    <color name="car_yellow_400">#fff6cd3a</color>
+    <color name="car_yellow_300">#fff9dc74</color>
+    <color name="car_yellow_200">#fffbe7a2</color>
+    <color name="car_yellow_100">#fffcf0ce</color>
+    <color name="car_yellow_50">#fffdf7e6</color>
+
+    <color name="car_orange_900">#ffb06000</color>
+    <color name="car_orange_800">#ffc26401</color>
+    <color name="car_orange_700">#ffd56e0c</color>
+    <color name="car_orange_600">#ffe8710a</color>
+    <color name="car_orange_500">#fffa7b17</color>
+    <color name="car_orange_400">#fffa903e</color>
+    <color name="car_orange_300">#fffcad70</color>
+    <color name="car_orange_200">#fffdc69c</color>
+    <color name="car_orange_100">#fffedfc8</color>
+    <color name="car_orange_50">#fffeefe3</color>
+
+    <color name="car_pink_900">#ff9c166b</color>
+    <color name="car_pink_800">#ffb80672</color>
+    <color name="car_pink_700">#ffd01884</color>
+    <color name="car_pink_600">#ffe52592</color>
+    <color name="car_pink_500">#fff439a0</color>
+    <color name="car_pink_400">#ffff63b8</color>
+    <color name="car_pink_300">#ffff8bcb</color>
+    <color name="car_pink_200">#fffba9d6</color>
+    <color name="car_pink_100">#fffdcfe8</color>
+    <color name="car_pink_50">#fffde7f3</color>
+
+    <color name="car_teal_900">#ff004d40</color>
+    <color name="car_teal_800">#ff00695c</color>
+    <color name="car_teal_700">#ff00796b</color>
+    <color name="car_teal_600">#ff00897b</color>
+    <color name="car_teal_500">#ff009688</color>
+    <color name="car_teal_400">#ff26a69a</color>
+    <color name="car_teal_300">#ff4db6ac</color>
+    <color name="car_teal_200">#ff80cbc4</color>
+    <color name="car_teal_100">#ffb2dfdb</color>
+    <color name="car_teal_50">#ffe0f2f1</color>
+
+    <color name="car_purple_900">#ff681da8</color>
+    <color name="car_purple_800">#ff7627bb</color>
+    <color name="car_purple_700">#ff8430ce</color>
+    <color name="car_purple_600">#ff9334e6</color>
+    <color name="car_purple_500">#ffa142f4</color>
+    <color name="car_purple_400">#ffaf5cf7</color>
+    <color name="car_purple_300">#ffc58af9</color>
+    <color name="car_purple_200">#ffd7aefb</color>
+    <color name="car_purple_100">#ffe9d2fd</color>
+    <color name="car_purple_50">#fff3e8fd</color>
+
+    <color name="car_cyan_900">#ff01877e</color>
+    <color name="car_cyan_800">#ff099091</color>
+    <color name="car_cyan_700">#ff12a4af</color>
+    <color name="car_cyan_600">#ff12b5cb</color>
+    <color name="car_cyan_500">#ff24c1e0</color>
+    <color name="car_cyan_400">#ff4ecde6</color>
+    <color name="car_cyan_300">#ff78d9ec</color>
+    <color name="car_cyan_200">#ffa1e4f2</color>
+    <color name="car_cyan_100">#ffcbf0f8</color>
+    <color name="car_cyan_50">#ffe4f7fb</color>
+
+
+    <color name="car_grey_1000">#cc000000</color>
+    <color name="car_white_1000">#1effffff</color>
+    <color name="car_blue_grey_800">#ff37474F</color>
+    <color name="car_blue_grey_900">#ff263238</color>
+    <color name="car_dark_blue_grey_600">#ff1d272d</color>
+    <color name="car_dark_blue_grey_700">#ff172026</color>
+    <color name="car_dark_blue_grey_800">#ff11181d</color>
+    <color name="car_dark_blue_grey_900">#ff0c1013</color>
+    <color name="car_dark_blue_grey_1000">#ff090c0f</color>
+    <color name="car_light_blue_300">#ff4fc3f7</color>
+    <color name="car_light_blue_500">#ff03A9F4</color>
+    <color name="car_light_blue_600">#ff039be5</color>
+    <color name="car_light_blue_700">#ff0288d1</color>
+    <color name="car_light_blue_800">#ff0277bd</color>
+    <color name="car_light_blue_900">#ff01579b</color>
+
+
+    <color name="car_red_500a">#ffd50000</color>
+    <color name="car_red_a700">#ffd50000</color>
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 1404383..0daf5a7 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2113,8 +2113,8 @@
     <!-- Type of the long press sensor. Empty if long press is not supported. -->
     <string name="config_dozeLongPressSensorType" translatable="false"></string>
 
-    <!-- Type of the reach sensor. Empty if reach is not supported. -->
-    <string name="config_dozeReachSensorType" translatable="false"></string>
+    <!-- Type of sensor that wakes up the lock screen. Empty if not supported. -->
+    <string name="config_dozeWakeLockScreenSensorType" translatable="false"></string>
 
     <!-- Type of the wake up sensor. Empty if not supported. -->
     <string name="config_dozeWakeScreenSensorType" translatable="false"></string>
@@ -3541,4 +3541,13 @@
 
     <!-- Brand value for attestation of misprovisioned device. -->
     <string name="config_misprovisionedBrandValue" translatable="false"></string>
+
+    <!-- Pre-scale volume at volume step 1 for Absolute Volume -->
+    <fraction name="config_prescaleAbsoluteVolume_index1">50%</fraction>
+
+    <!-- Pre-scale volume at volume step 2 for Absolute Volume -->
+    <fraction name="config_prescaleAbsoluteVolume_index2">70%</fraction>
+
+    <!-- Pre-scale volume at volume step 3 for Absolute Volume -->
+    <fraction name="config_prescaleAbsoluteVolume_index3">85%</fraction>
 </resources>
diff --git a/core/res/res/values/dimens_car.xml b/core/res/res/values/dimens_car.xml
index 7d14f86..a0c02ed 100644
--- a/core/res/res/values/dimens_car.xml
+++ b/core/res/res/values/dimens_car.xml
@@ -16,12 +16,86 @@
 */
 -->
 <resources>
-    <!-- TODO replace with car support lib sizes when available -->
     <dimen name="car_fullscreen_user_pod_icon_text_size">64sp</dimen>
     <dimen name="car_fullscreen_user_pod_width">243dp</dimen>
     <dimen name="car_fullscreen_user_pod_height">356dp</dimen>
     <dimen name="car_fullscreen_user_pod_image_avatar_width">96dp</dimen>
     <dimen name="car_fullscreen_user_pod_image_avatar_height">96dp</dimen>
-    <dimen name="car_padding_4">20dp</dimen>
+
+
+    <!-- Application Bar -->
+    <dimen name="car_app_bar_height">80dp</dimen>
+    <!-- Margin -->
+    <dimen name="car_margin">20dp</dimen>
+    <!-- Lists -->
+    <dimen name="car_single_line_list_item_height">96dp</dimen>
+    <dimen name="car_double_line_list_item_height">@dimen/car_single_line_list_item_height</dimen>
+    <dimen name="car_list_divider_height">1dp</dimen>
+    <!-- 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>
+    <dimen name="car_title2_size">32sp</dimen>
+    <dimen name="car_headline1_size">45sp</dimen>
+    <dimen name="car_headline2_size">32sp</dimen>
+    <dimen name="car_headline3_size">24sp</dimen>
+    <dimen name="car_headline4_size">20sp</dimen>
     <dimen name="car_body1_size">32sp</dimen>
-</resources>
\ No newline at end of file
+    <dimen name="car_body2_size">26sp</dimen>
+    <dimen name="car_body3_size">16sp</dimen>
+    <dimen name="car_body4_size">14sp</dimen>
+    <dimen name="car_body5_size">18sp</dimen>
+    <dimen name="car_label1_size">26sp</dimen>
+    <dimen name="car_label2_size">64sp</dimen>
+    <dimen name="car_action1_size">26sp</dimen>
+    <dimen name="car_action2_size">26sp</dimen>
+
+    <!-- Common icon size for car app -->
+    <dimen name="car_icon_size">56dp</dimen>
+
+    <dimen name="car_card_header_height">96dp</dimen>
+    <dimen name="car_card_action_bar_height">96dp</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>
+
+    <!-- Radius -->
+    <dimen name="car_radius_1">4dp</dimen>
+    <dimen name="car_radius_2">8dp</dimen>
+    <dimen name="car_radius_3">16dp</dimen>
+    <dimen name="car_radius_5">100dp</dimen>
+
+    <!-- Keylines for content. -->
+    <dimen name="car_keyline_1">48dp</dimen>
+    <dimen name="car_keyline_2">108dp</dimen>
+    <dimen name="car_keyline_3">152dp</dimen>
+    <dimen name="car_keyline_4">182dp</dimen>
+
+    <!-- Buttons -->
+    <dimen name="car_button_height">56dp</dimen>
+    <dimen name="car_button_min_width">158dp</dimen>
+    <dimen name="car_button_horizontal_padding">@dimen/car_padding_4</dimen>
+    <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>
+
+    <!-- Seekbar -->
+    <dimen name="car_seekbar_height">6dp</dimen>
+    <dimen name="car_seekbar_padding">26dp</dimen>
+    <dimen name="car_seekbar_thumb_size">24dp</dimen>
+    <dimen name="car_seekbar_thumb_stroke">1dp</dimen>
+    <!-- The space between seekbar and text in ListItem. This value is based on car_seekbar_padding.
+         It brings seekbar and text closer for visual balance while maintaining touch area. -->
+    <dimen name="car_seekbar_text_overlap">-20dp</dimen>
+
+    <!-- Progress Bar -->
+    <dimen name="car_progress_bar_height">@dimen/car_seekbar_height</dimen>
+
+</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index cc99a4e..fadefff 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2912,6 +2912,8 @@
         <!-- @hide For use by platform and tools only. Developers should not specify this value. -->
         <public name="usesNonSdkApi" />
         <public name="minimumUiTimeout" />
+        <public name="isLightTheme" />
+        <public name="isSplitRequired" />
     </public-group>
 
     <public-group type="drawable" first-id="0x010800b4">
diff --git a/core/res/res/values/styles_car.xml b/core/res/res/values/styles_car.xml
new file mode 100644
index 0000000..f6ff1b6
--- /dev/null
+++ b/core/res/res/values/styles_car.xml
@@ -0,0 +1,89 @@
+<?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>
+    <!-- Car text -->
+    <style name="CarBody1">
+        <item name="textStyle">normal</item>
+        <item name="textSize">@dimen/car_body1_size</item>
+        <item name="textColor">@color/car_body1</item>
+    </style>
+
+    <style name="CarBody1.Light">
+        <item name="textColor">@color/car_body1_light</item>
+    </style>
+
+    <style name="CarBody1.Dark">
+        <item name="textColor">@color/car_body2_dark</item>
+    </style>
+
+    <style name="CarBody2">
+        <item name="textStyle">normal</item>
+        <item name="textSize">@dimen/car_body2_size</item>
+        <item name="textColor">@color/car_body2</item>
+    </style>
+
+    <style name="CarBody2.Dark">
+        <item name="textColor">@color/car_body2_dark</item>
+    </style>
+    <style name="CarBody2.Light">
+        <item name="textColor">@color/car_body2_light</item>
+    </style>
+
+    <style name="CarBody3">
+        <item name="textStyle">normal</item>
+        <item name="textSize">@dimen/car_body3_size</item>
+        <item name="textColor">@color/car_body3</item>
+    </style>
+
+    <!-- The smallest styling for body text. The color of this text changes based on the day/night
+         mode. -->
+    <style name="CarBody4">
+        <item name="textStyle">normal</item>
+        <item name="textSize">@dimen/car_body4_size</item>
+        <item name="textColor">@color/car_body4</item>
+    </style>
+
+    <style name="CarAction1">
+        <item name="textStyle">bold</item>
+        <item name="textSize">@dimen/car_action1_size</item>
+        <item name="textColor">@color/car_highlight</item>
+    </style>
+
+    <style name="CarAction1.Dark">
+        <item name="textColor">@color/car_highlight_dark</item>
+    </style>
+    <style name="CarAction1.Light">
+        <item name="textColor">@color/car_highlight_light</item>
+    </style>
+
+    <!-- The styling for title text. The color of this text changes based on day/night mode. -->
+    <style name="CarTitle" >
+        <item name="textStyle">bold</item>
+        <item name="textSize">@dimen/car_title2_size</item>
+        <item name="textColor">@color/car_title</item>
+    </style>
+
+    <!-- Title text that is permanently a dark color. -->
+    <style name="CarTitle.Dark" >
+        <item name="textColor">@color/car_title_dark</item>
+    </style>
+
+    <!-- Title text that is permanently a light color. -->
+    <style name="CarTitle.Light" >
+        <item name="textColor">@color/car_title_light</item>
+    </style>
+
+</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index cf85986..72ae0d6 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3154,7 +3154,9 @@
   <java-symbol type="integer" name="autofill_max_visible_datasets" />
 
   <java-symbol type="style" name="Theme.DeviceDefault.Autofill" />
+  <java-symbol type="style" name="Theme.DeviceDefault.Light.Autofill" />
   <java-symbol type="style" name="Theme.DeviceDefault.Autofill.Save" />
+  <java-symbol type="style" name="Theme.DeviceDefault.Light.Autofill.Save" />
 
   <java-symbol type="dimen" name="notification_big_picture_max_height"/>
   <java-symbol type="dimen" name="notification_big_picture_max_width"/>
@@ -3277,7 +3279,7 @@
   <java-symbol type="array" name="config_hideWhenDisabled_packageNames" />
 
   <java-symbol type="string" name="config_dozeLongPressSensorType" />
-  <java-symbol type="string" name="config_dozeReachSensorType" />
+  <java-symbol type="string" name="config_dozeWakeLockScreenSensorType" />
 
   <java-symbol type="array" name="config_allowedGlobalInstantAppSettings" />
   <java-symbol type="array" name="config_allowedSystemInstantAppSettings" />
@@ -3468,4 +3470,9 @@
   <java-symbol type="integer" name="db_wal_truncate_size" />
   <java-symbol type="integer" name="config_wakeUpDelayDoze" />
   <java-symbol type="string" name="config_dozeWakeScreenSensorType" />
+
+  <!-- For Bluetooth AbsoluteVolume -->
+  <java-symbol type="fraction" name="config_prescaleAbsoluteVolume_index1" />
+  <java-symbol type="fraction" name="config_prescaleAbsoluteVolume_index2" />
+  <java-symbol type="fraction" name="config_prescaleAbsoluteVolume_index3" />
 </resources>
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 92096ab..3385527 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -1681,13 +1681,14 @@
     </style>
 
 
-    <!-- @hide DeviceDefault theme for the autofill FillUi -->
-    <style name="Theme.DeviceDefault.Autofill" parent="Theme.Material.Autofill.Light">
-    </style>
+    <!-- @hide DeviceDefault themes for the autofill FillUi -->
+    <style name="Theme.DeviceDefault.Autofill" />
+    <style name="Theme.DeviceDefault.Light.Autofill" />
 
-    <!-- @hide DeviceDefault theme for the autofill SaveUi -->
-    <style name="Theme.DeviceDefault.Autofill.Save" parent="Theme.Material.Autofill.Save.Light">
-    </style>
+    <!-- @hide DeviceDefault theme for the autofill SaveUi. NOTE: it must be a .Panel so the dialog
+         is shown at the bottom of the screen  -->
+    <style name="Theme.DeviceDefault.Autofill.Save" parent="Theme.DeviceDefault.Panel"/>
+    <style name="Theme.DeviceDefault.Light.Autofill.Save" parent="Theme.DeviceDefault.Light.Panel"/>
 
     <!-- DeviceDefault theme for the default system theme.  -->
     <style name="Theme.DeviceDefault.System" parent="Theme.DeviceDefault.Light.DarkActionBar" />
@@ -1715,4 +1716,10 @@
         <item name="colorAccent">@color/accent_device_default_dark</item>
     </style>
 
+    <style name="Theme.DeviceDefault.Light.Dialog.Alert.UserSwitchingDialog" parent="Theme.DeviceDefault.NoActionBar.Fullscreen">
+        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackgroundFloating">@color/background_device_default_light</item>
+        <item name="layout_gravity">center</item>
+    </style>
+
 </resources>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index b3e33d5..ccaf041 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -1418,24 +1418,4 @@
         <item name="colorSecondary">@color/secondary_material_settings</item>
     </style>
 
-    <!-- @hide -->
-    <style name="Theme.Material.Autofill" parent="Theme.Material">
-        <item name="colorBackground">@color/autofill_background_material_dark</item>
-    </style>
-
-    <!-- @hide -->
-    <style name="Theme.Material.Autofill.Light" parent="Theme.Material.Light">
-        <item name="colorBackground">@color/autofill_background_material_light</item>
-    </style>
-
-    <!-- @hide -->
-    <style name="Theme.Material.Autofill.Save" parent="Theme.Material.Panel">
-        <item name="colorBackground">@color/autofill_background_material_dark</item>
-    </style>
-
-    <!-- @hide -->
-    <style name="Theme.Material.Autofill.Save.Light" parent="Theme.Material.Light.Panel">
-        <item name="colorBackground">@color/autofill_background_material_light</item>
-    </style>
-
 </resources>
diff --git a/core/tests/coretests/src/android/content/ContentProviderTest.java b/core/tests/coretests/src/android/content/ContentProviderTest.java
new file mode 100644
index 0000000..2142f27
--- /dev/null
+++ b/core/tests/coretests/src/android/content/ContentProviderTest.java
@@ -0,0 +1,88 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.withSettings;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ProviderInfo;
+import android.net.Uri;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+
+@RunWith(AndroidJUnit4.class)
+public class ContentProviderTest {
+
+    private Context mContext;
+    private ContentProvider mCp;
+
+    private ApplicationInfo mProviderApp;
+    private ProviderInfo mProvider;
+
+    @Before
+    public void setUp() {
+        mProviderApp = new ApplicationInfo();
+        mProviderApp.uid = 10001;
+
+        mProvider = new ProviderInfo();
+        mProvider.authority = "com.example";
+        mProvider.applicationInfo = mProviderApp;
+
+        mContext = mock(Context.class);
+
+        mCp = mock(ContentProvider.class, withSettings().defaultAnswer(Answers.CALLS_REAL_METHODS));
+        mCp.attachInfo(mContext, mProvider);
+    }
+
+    @Test
+    public void testValidateIncomingUri_Normal() throws Exception {
+        assertEquals(Uri.parse("content://com.example/"),
+                mCp.validateIncomingUri(Uri.parse("content://com.example/")));
+        assertEquals(Uri.parse("content://com.example/foo/bar"),
+                mCp.validateIncomingUri(Uri.parse("content://com.example/foo/bar")));
+        assertEquals(Uri.parse("content://com.example/foo%2Fbar"),
+                mCp.validateIncomingUri(Uri.parse("content://com.example/foo%2Fbar")));
+        assertEquals(Uri.parse("content://com.example/foo%2F%2Fbar"),
+                mCp.validateIncomingUri(Uri.parse("content://com.example/foo%2F%2Fbar")));
+    }
+
+    @Test
+    public void testValidateIncomingUri_Shady() throws Exception {
+        assertEquals(Uri.parse("content://com.example/"),
+                mCp.validateIncomingUri(Uri.parse("content://com.example//")));
+        assertEquals(Uri.parse("content://com.example/foo/bar/"),
+                mCp.validateIncomingUri(Uri.parse("content://com.example//foo//bar//")));
+        assertEquals(Uri.parse("content://com.example/foo/bar/"),
+                mCp.validateIncomingUri(Uri.parse("content://com.example/foo///bar/")));
+        assertEquals(Uri.parse("content://com.example/foo%2F%2Fbar/baz"),
+                mCp.validateIncomingUri(Uri.parse("content://com.example/foo%2F%2Fbar//baz")));
+    }
+
+    @Test
+    public void testValidateIncomingUri_NonPath() throws Exception {
+        // We only touch paths; queries and fragments are left intact
+        assertEquals(Uri.parse("content://com.example/foo/bar?foo=b//ar#foo=b//ar"),
+                mCp.validateIncomingUri(
+                        Uri.parse("content://com.example/foo/bar?foo=b//ar#foo=b//ar")));
+    }
+}
diff --git a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
index 3ce2589..6fdb71f 100644
--- a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
+++ b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
@@ -24,6 +24,7 @@
 import android.content.Context;
 import android.content.res.AssetManager;
 import android.graphics.fonts.Font;
+import android.graphics.fonts.FontCustomizationParser;
 import android.graphics.fonts.FontFamily;
 import android.graphics.fonts.SystemFonts;
 import android.support.test.InstrumentationRegistry;
@@ -36,12 +37,15 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.xmlpull.v1.XmlPullParserException;
 
+import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.StandardCopyOption;
 import java.util.ArrayList;
@@ -62,6 +66,8 @@
     };
     private static final String TEST_FONTS_XML;
     private static final String TEST_FONT_DIR;
+    private static final String TEST_OEM_XML;
+    private static final String TEST_OEM_DIR;
 
     private static final float GLYPH_1EM_WIDTH;
     private static final float GLYPH_2EM_WIDTH;
@@ -73,8 +79,13 @@
         if (!cacheDir.isDirectory()) {
             cacheDir.mkdirs();
         }
-        TEST_FONT_DIR = cacheDir.getAbsolutePath() + "/";
+        TEST_FONT_DIR = cacheDir.getAbsolutePath() + "/fonts/";
         TEST_FONTS_XML = new File(cacheDir, "fonts.xml").getAbsolutePath();
+        TEST_OEM_DIR = cacheDir.getAbsolutePath() + "/oem_fonts/";
+        TEST_OEM_XML = new File(cacheDir, "fonts_customization.xml").getAbsolutePath();
+
+        new File(TEST_FONT_DIR).mkdirs();
+        new File(TEST_OEM_DIR).mkdirs();
 
         final AssetManager am =
                 InstrumentationRegistry.getInstrumentation().getContext().getAssets();
@@ -99,6 +110,12 @@
             } catch (IOException e) {
                 throw new RuntimeException(e);
             }
+            final File outOemInCache = new File(TEST_OEM_DIR, fontFile);
+            try (InputStream is = am.open(sourceInAsset)) {
+                Files.copy(is, outOemInCache.toPath(), StandardCopyOption.REPLACE_EXISTING);
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
         }
     }
 
@@ -107,11 +124,14 @@
         for (final String fontFile : TEST_FONT_FILES) {
             final File outInCache = new File(TEST_FONT_DIR, fontFile);
             outInCache.delete();
+            final File outOemInCache = new File(TEST_OEM_DIR, fontFile);
+            outInCache.delete();
         }
     }
 
     private static void buildSystemFallback(String xml,
-            ArrayMap<String, Typeface> fontMap, ArrayMap<String, FontFamily[]> fallbackMap) {
+            FontCustomizationParser.Result oemCustomization, ArrayMap<String, Typeface> fontMap,
+            ArrayMap<String, FontFamily[]> fallbackMap) {
         final ArrayList<Font> availableFonts = new ArrayList<>();
         try (FileOutputStream fos = new FileOutputStream(TEST_FONTS_XML)) {
             fos.write(xml.getBytes(Charset.forName("UTF-8")));
@@ -119,18 +139,28 @@
             throw new RuntimeException(e);
         }
         final FontConfig.Alias[] aliases = SystemFonts.buildSystemFallback(TEST_FONTS_XML,
-                TEST_FONT_DIR, fallbackMap, availableFonts);
+                TEST_FONT_DIR, oemCustomization, fallbackMap, availableFonts);
         Typeface.initSystemDefaultTypefaces(fontMap, fallbackMap, aliases);
     }
 
+    private static FontCustomizationParser.Result readFontCustomization(String oemXml) {
+        try (InputStream is = new ByteArrayInputStream(oemXml.getBytes(StandardCharsets.UTF_8))) {
+            return FontCustomizationParser.parse(is, TEST_OEM_DIR);
+        } catch (IOException | XmlPullParserException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
     @Test
     public void testBuildSystemFallback() {
         final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
         final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
         final ArrayList<Font> availableFonts = new ArrayList<>();
+        final FontCustomizationParser.Result oemCustomization =
+                new FontCustomizationParser.Result();
 
         final FontConfig.Alias[] aliases = SystemFonts.buildSystemFallback(SYSTEM_FONTS_XML,
-                SYSTEM_FONT_DIR, fallbackMap, availableFonts);
+                SYSTEM_FONT_DIR, oemCustomization, fallbackMap, availableFonts);
 
         assertNotNull(aliases);
         assertFalse(fallbackMap.isEmpty());
@@ -156,8 +186,10 @@
                 + "</familyset>";
         final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
         final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
+        final FontCustomizationParser.Result oemCustomization =
+                new FontCustomizationParser.Result();
 
-        buildSystemFallback(xml, fontMap, fallbackMap);
+        buildSystemFallback(xml, oemCustomization, fontMap, fallbackMap);
 
         assertEquals(1, fontMap.size());
         assertTrue(fontMap.containsKey("sans-serif"));
@@ -184,8 +216,10 @@
                 + "</familyset>";
         final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
         final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
+        final FontCustomizationParser.Result oemCustomization =
+                new FontCustomizationParser.Result();
 
-        buildSystemFallback(xml, fontMap, fallbackMap);
+        buildSystemFallback(xml, oemCustomization, fontMap, fallbackMap);
 
         final Paint paint = new Paint();
 
@@ -230,8 +264,10 @@
                 + "</familyset>";
         final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
         final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
+        final FontCustomizationParser.Result oemCustomization =
+                new FontCustomizationParser.Result();
 
-        buildSystemFallback(xml, fontMap, fallbackMap);
+        buildSystemFallback(xml, oemCustomization, fontMap, fallbackMap);
 
         final Paint paint = new Paint();
 
@@ -275,8 +311,10 @@
                 + "</familyset>";
         final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
         final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
+        final FontCustomizationParser.Result oemCustomization =
+                new FontCustomizationParser.Result();
 
-        buildSystemFallback(xml, fontMap, fallbackMap);
+        buildSystemFallback(xml, oemCustomization, fontMap, fallbackMap);
 
         final Paint paint = new Paint();
 
@@ -325,8 +363,10 @@
                 + "</familyset>";
         final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
         final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
+        final FontCustomizationParser.Result oemCustomization =
+                new FontCustomizationParser.Result();
 
-        buildSystemFallback(xml, fontMap, fallbackMap);
+        buildSystemFallback(xml, oemCustomization, fontMap, fallbackMap);
 
         final Paint paint = new Paint();
 
@@ -371,8 +411,10 @@
                 + "</familyset>";
         final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
         final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
+        final FontCustomizationParser.Result oemCustomization =
+                new FontCustomizationParser.Result();
 
-        buildSystemFallback(xml, fontMap, fallbackMap);
+        buildSystemFallback(xml, oemCustomization, fontMap, fallbackMap);
 
         final Paint paint = new Paint();
 
@@ -410,8 +452,10 @@
                 + "</familyset>";
         final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
         final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
+        final FontCustomizationParser.Result oemCustomization =
+                new FontCustomizationParser.Result();
 
-        buildSystemFallback(xml, fontMap, fallbackMap);
+        buildSystemFallback(xml, oemCustomization, fontMap, fallbackMap);
 
         final Paint paint = new Paint();
 
@@ -449,8 +493,10 @@
                 + "</familyset>";
         final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
         final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
+        final FontCustomizationParser.Result oemCustomization =
+                new FontCustomizationParser.Result();
 
-        buildSystemFallback(xml, fontMap, fallbackMap);
+        buildSystemFallback(xml, oemCustomization, fontMap, fallbackMap);
 
         final Paint paint = new Paint();
 
@@ -497,8 +543,10 @@
                 + "</familyset>";
         final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
         final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
+        final FontCustomizationParser.Result oemCustomization =
+                new FontCustomizationParser.Result();
 
-        buildSystemFallback(xml, fontMap, fallbackMap);
+        buildSystemFallback(xml, oemCustomization, fontMap, fallbackMap);
 
         final Paint paint = new Paint();
         paint.setTypeface(fontMap.get("sans-serif"));
@@ -539,8 +587,10 @@
                 + "</familyset>";
         final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
         final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
+        final FontCustomizationParser.Result oemCustomization =
+                new FontCustomizationParser.Result();
 
-        buildSystemFallback(xml, fontMap, fallbackMap);
+        buildSystemFallback(xml, oemCustomization, fontMap, fallbackMap);
 
         final Paint paint = new Paint();
 
@@ -578,8 +628,10 @@
                 + "</familyset>";
         final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
         final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
+        final FontCustomizationParser.Result oemCustomization =
+                new FontCustomizationParser.Result();
 
-        buildSystemFallback(xml, fontMap, fallbackMap);
+        buildSystemFallback(xml, oemCustomization, fontMap, fallbackMap);
 
         final Paint paint = new Paint();
 
@@ -598,4 +650,191 @@
         assertEquals(GLYPH_1EM_WIDTH, paint.measureText("c"), 0.0f);
     }
 
+    @Test
+    public void testBuildSystemFallback__Customization_new_named_family() {
+        final String xml = "<?xml version='1.0' encoding='UTF-8'?>"
+                + "<familyset>"
+                + "  <family name='sans-serif'>"
+                + "    <font weight='400' style='normal'>a3em.ttf</font>"
+                + "  </family>"
+                + "</familyset>";
+        final String oemXml = "<?xml version='1.0' encoding='UTF-8'?>"
+                + "<fonts-modification version='1'>"
+                + "  <family customizationType='new-named-family' name='google-sans'>"
+                + "    <font weight='400' style='normal'>b3em.ttf</font>"
+                + "  </family>"
+                + "</fonts-modification>";
+        final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
+        final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
+        final FontCustomizationParser.Result oemCustomization =
+                readFontCustomization(oemXml);
+
+        buildSystemFallback(xml, oemCustomization, fontMap, fallbackMap);
+
+        final Paint paint = new Paint();
+
+        Typeface testTypeface = fontMap.get("sans-serif");
+        assertNotNull(testTypeface);
+        paint.setTypeface(testTypeface);
+        assertEquals(GLYPH_3EM_WIDTH, paint.measureText("a"), 0.0f);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("b"), 0.0f);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("c"), 0.0f);
+
+        testTypeface = fontMap.get("google-sans");
+        assertNotNull(testTypeface);
+        paint.setTypeface(testTypeface);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("a"), 0.0f);
+        assertEquals(GLYPH_3EM_WIDTH, paint.measureText("b"), 0.0f);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("c"), 0.0f);
+    }
+
+    @Test
+    public void testBuildSystemFallback__Customization_new_named_family_override() {
+        final String xml = "<?xml version='1.0' encoding='UTF-8'?>"
+                + "<familyset>"
+                + "  <family name='sans-serif'>"
+                + "    <font weight='400' style='normal'>a3em.ttf</font>"
+                + "  </family>"
+                + "</familyset>";
+        final String oemXml = "<?xml version='1.0' encoding='UTF-8'?>"
+                + "<fonts-modification version='1'>"
+                + "  <family customizationType='new-named-family' name='sans-serif'>"
+                + "    <font weight='400' style='normal'>b3em.ttf</font>"
+                + "  </family>"
+                + "</fonts-modification>";
+        final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
+        final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
+        final FontCustomizationParser.Result oemCustomization =
+                readFontCustomization(oemXml);
+
+        buildSystemFallback(xml, oemCustomization, fontMap, fallbackMap);
+
+        final Paint paint = new Paint();
+
+        Typeface testTypeface = fontMap.get("sans-serif");
+        assertNotNull(testTypeface);
+        paint.setTypeface(testTypeface);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("a"), 0.0f);
+        assertEquals(GLYPH_3EM_WIDTH, paint.measureText("b"), 0.0f);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("c"), 0.0f);
+    }
+
+    @Test
+    public void testBuildSystemFallback__Customization_additional_alias() {
+        final String xml = "<?xml version='1.0' encoding='UTF-8'?>"
+                + "<familyset>"
+                + "  <family name='sans-serif'>"
+                + "    <font weight='400' style='normal'>a3em.ttf</font>"
+                + "  </family>"
+                + "</familyset>";
+        final String oemXml = "<?xml version='1.0' encoding='UTF-8'?>"
+                + "<fonts-modification version='1'>"
+                + "  <family customizationType='new-named-family' name='google-sans'>"
+                + "    <font weight='400' style='normal'>b3em.ttf</font>"
+                + "    <font weight='700' style='normal'>c3em.ttf</font>"
+                + "  </family>"
+                + "  <alias name='another-google-sans' to='google-sans' />"
+                + "  <alias name='google-sans-bold' to='google-sans' weight='700' />"
+                + "</fonts-modification>";
+        final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
+        final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
+        final FontCustomizationParser.Result oemCustomization =
+                readFontCustomization(oemXml);
+
+        buildSystemFallback(xml, oemCustomization, fontMap, fallbackMap);
+
+        final Paint paint = new Paint();
+
+        Typeface testTypeface = fontMap.get("sans-serif");
+        assertNotNull(testTypeface);
+        paint.setTypeface(testTypeface);
+        assertEquals(GLYPH_3EM_WIDTH, paint.measureText("a"), 0.0f);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("b"), 0.0f);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("c"), 0.0f);
+
+        testTypeface = fontMap.get("google-sans");
+        assertNotNull(testTypeface);
+        paint.setTypeface(testTypeface);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("a"), 0.0f);
+        assertEquals(GLYPH_3EM_WIDTH, paint.measureText("b"), 0.0f);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("c"), 0.0f);
+
+        testTypeface = fontMap.get("another-google-sans");
+        assertNotNull(testTypeface);
+        paint.setTypeface(testTypeface);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("a"), 0.0f);
+        assertEquals(GLYPH_3EM_WIDTH, paint.measureText("b"), 0.0f);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("c"), 0.0f);
+
+        testTypeface = fontMap.get("google-sans-bold");
+        assertNotNull(testTypeface);
+        paint.setTypeface(testTypeface);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("a"), 0.0f);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("b"), 0.0f);
+        assertEquals(GLYPH_3EM_WIDTH, paint.measureText("c"), 0.0f);
+    }
+
+    @Test
+    public void testBuildSystemFallback__Customization_additional_alias_conflict_with_new_name() {
+        final String xml = "<?xml version='1.0' encoding='UTF-8'?>"
+                + "<familyset>"
+                + "  <family name='named-family'>"
+                + "    <font weight='400' style='normal'>a3em.ttf</font>"
+                + "  </family>"
+                + "  <alias name='named-alias' to='named-family' />"
+                + "</familyset>";
+        final String oemXml = "<?xml version='1.0' encoding='UTF-8'?>"
+                + "<fonts-modification version='1'>"
+                + "  <family customizationType='new-named-family' name='named-alias'>"
+                + "    <font weight='400' style='normal'>b3em.ttf</font>"
+                + "  </family>"
+                + "</fonts-modification>";
+        final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
+        final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
+        final FontCustomizationParser.Result oemCustomization =
+                readFontCustomization(oemXml);
+
+        buildSystemFallback(xml, oemCustomization, fontMap, fallbackMap);
+
+        final Paint paint = new Paint();
+
+        Typeface testTypeface = fontMap.get("named-family");
+        assertNotNull(testTypeface);
+        paint.setTypeface(testTypeface);
+        assertEquals(GLYPH_3EM_WIDTH, paint.measureText("a"), 0.0f);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("b"), 0.0f);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("c"), 0.0f);
+
+        testTypeface = fontMap.get("named-alias");
+        assertNotNull(testTypeface);
+        paint.setTypeface(testTypeface);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("a"), 0.0f);
+        assertEquals(GLYPH_3EM_WIDTH, paint.measureText("b"), 0.0f);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("c"), 0.0f);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testBuildSystemFallback__Customization_new_named_family_no_name_exception() {
+        final String oemXml = "<?xml version='1.0' encoding='UTF-8'?>"
+                + "<fonts-modification version='1'>"
+                + "  <family customizationType='new-named-family'>"
+                + "    <font weight='400' style='normal'>b3em.ttf</font>"
+                + "  </family>"
+                + "</fonts-modification>";
+        readFontCustomization(oemXml);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testBuildSystemFallback__Customization_new_named_family_dup_name_exception() {
+        final String oemXml = "<?xml version='1.0' encoding='UTF-8'?>"
+                + "<fonts-modification version='1'>"
+                + "  <family customizationType='new-named-family' name='google-sans'>"
+                + "    <font weight='400' style='normal'>b3em.ttf</font>"
+                + "  </family>"
+                + "  <family customizationType='new-named-family' name='google-sans'>"
+                + "    <font weight='400' style='normal'>b3em.ttf</font>"
+                + "  </family>"
+                + "</fonts-modification>";
+        readFontCustomization(oemXml);
+    }
 }
diff --git a/core/tests/coretests/src/android/net/LocalSocketTest.java b/core/tests/coretests/src/android/net/LocalSocketTest.java
index 1349844..1286b13 100644
--- a/core/tests/coretests/src/android/net/LocalSocketTest.java
+++ b/core/tests/coretests/src/android/net/LocalSocketTest.java
@@ -22,6 +22,7 @@
 import android.net.LocalSocketAddress;
 import android.test.MoreAsserts;
 import android.test.suitebuilder.annotation.SmallTest;
+
 import junit.framework.TestCase;
 
 import java.io.FileDescriptor;
@@ -39,6 +40,20 @@
 
         ls = new LocalSocket();
 
+        try {
+            ls.connect(new LocalSocketAddress(null));
+            fail("Expected NullPointerException");
+        } catch (NullPointerException e) {
+            // pass
+        }
+
+        try {
+            ls.bind(new LocalSocketAddress(null));
+            fail("Expected NullPointerException");
+        } catch (NullPointerException e) {
+            // pass
+        }
+
         ls.connect(new LocalSocketAddress("android.net.LocalSocketTest"));
 
         ls1 = ss.accept();
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index fee470d..8f0e76b 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -447,6 +447,7 @@
                     Settings.Global.ENABLE_GPU_DEBUG_LAYERS,
                     Settings.Global.GPU_DEBUG_APP,
                     Settings.Global.GPU_DEBUG_LAYERS,
+                    Settings.Global.ANGLE_ENABLED_APP,
                     Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING,
                     Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_PERSISTENT,
                     Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_SLEEP_MILLIS,
diff --git a/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java b/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java
index 8909293..b0d29bd 100644
--- a/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java
@@ -73,7 +73,7 @@
     @Test
     public void testComponentNameValidator() {
         assertTrue(SettingsValidators.COMPONENT_NAME_VALIDATOR.validate(
-                "android/com.android.internal.backup.LocalTransport"));
+                "com.android.localtransport/.LocalTransport"));
         assertFalse(SettingsValidators.COMPONENT_NAME_VALIDATOR.validate("rectangle"));
     }
 
@@ -90,7 +90,7 @@
     @Test
     public void testNullableComponentNameValidator_onValidComponentName_returnsTrue() {
         assertTrue(SettingsValidators.NULLABLE_COMPONENT_NAME_VALIDATOR.validate(
-                "android/com.android.internal.backup.LocalTransport"));
+                "com.android.localtransport/.LocalTransport"));
     }
 
     @Test
@@ -185,7 +185,7 @@
     @Test
     public void testComponentNameListValidator() {
         Validator v = new SettingsValidators.ComponentNameListValidator(",");
-        assertTrue(v.validate("android/com.android.internal.backup.LocalTransport,"
+        assertTrue(v.validate("com.android.localtransport/.LocalTransport,"
                 + "com.google.android.gms/.backup.migrate.service.D2dTransport"));
         assertFalse(v.validate("com.google.5android,android"));
     }
@@ -200,7 +200,7 @@
     @Test
     public void testPackageNameListValidator() {
         Validator v = new SettingsValidators.PackageNameListValidator(",");
-        assertTrue(v.validate("com.android.internal.backup.LocalTransport,com.google.android.gms"));
+        assertTrue(v.validate("com.android.localtransport.LocalTransport,com.google.android.gms"));
         assertFalse(v.validate("5com.android.internal.backup.LocalTransport,android"));
     }
 
diff --git a/core/tests/coretests/src/android/text/FontFallbackSetup.java b/core/tests/coretests/src/android/text/FontFallbackSetup.java
index 898e78c..5592aac 100644
--- a/core/tests/coretests/src/android/text/FontFallbackSetup.java
+++ b/core/tests/coretests/src/android/text/FontFallbackSetup.java
@@ -21,6 +21,7 @@
 import android.content.res.AssetManager;
 import android.graphics.Typeface;
 import android.graphics.fonts.Font;
+import android.graphics.fonts.FontCustomizationParser;
 import android.graphics.fonts.FontFamily;
 import android.graphics.fonts.SystemFonts;
 import android.support.test.InstrumentationRegistry;
@@ -77,8 +78,10 @@
 
         final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
         final ArrayList<Font> availableFonts = new ArrayList<>();
+        final FontCustomizationParser.Result oemCustomization =
+                new FontCustomizationParser.Result();
         final FontConfig.Alias[] aliases = SystemFonts.buildSystemFallback(testFontsXml,
-                mTestFontsDir, fallbackMap, availableFonts);
+                mTestFontsDir, oemCustomization, fallbackMap, availableFonts);
         Typeface.initSystemDefaultTypefaces(mFontMap, fallbackMap, aliases);
     }
 
diff --git a/core/tests/coretests/src/android/view/inputmethod/InputMethodManagerTest.java b/core/tests/coretests/src/android/view/inputmethod/InputMethodManagerTest.java
new file mode 100644
index 0000000..55e5e36
--- /dev/null
+++ b/core/tests/coretests/src/android/view/inputmethod/InputMethodManagerTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.inputmethod;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.WindowManager;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class InputMethodManagerTest {
+    @Test
+    public void testPrivateApiGetInstance() throws Exception {
+        final InputMethodManager globalImm = InputMethodManager.getInstance();
+        assertNotNull("InputMethodManager.getInstance() still needs to work due to"
+                + " @UnsupportedAppUsage", globalImm);
+        assertEquals("InputMethodManager.peekInstance() still needs to work due to"
+                + " @UnsupportedAppUsage", globalImm, InputMethodManager.peekInstance());
+
+        final Context testContext = InstrumentationRegistry.getInstrumentation()
+                .getTargetContext();
+
+        final WindowManager wm = testContext.getSystemService(WindowManager.class);
+        final Context defaultDisplayContext =
+                testContext.createDisplayContext(wm.getDefaultDisplay());
+        final InputMethodManager imm =
+                defaultDisplayContext.getSystemService(InputMethodManager.class);
+        assertEquals("InputMethodManager.getInstance() always returns the instance for the default"
+                + " display.", globalImm, imm);
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuProcReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuProcReaderTest.java
index efdd7e9..8360126 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelCpuProcReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuProcReaderTest.java
@@ -43,7 +43,7 @@
 /**
  * Test class for {@link KernelCpuProcReader}.
  *
- * $ atest FrameworksCoreTests:com.android.internal.os.KernelCpuProcReader
+ * $ atest FrameworksCoreTests:com.android.internal.os.KernelCpuProcReaderTest
  */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
diff --git a/core/tests/coretests/src/com/android/internal/os/StoragedUidIoStatsReaderTest.java b/core/tests/coretests/src/com/android/internal/os/StoragedUidIoStatsReaderTest.java
new file mode 100644
index 0000000..c051a1c
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/StoragedUidIoStatsReaderTest.java
@@ -0,0 +1,171 @@
+/*
+ * 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.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import android.content.Context;
+import android.os.FileUtils;
+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 org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.nio.file.Files;
+
+
+/**
+ * Test class for {@link StoragedUidIoStatsReader}.
+ *
+ * To run it:
+ * atest FrameworksCoreTests:com.android.internal.os.StoragedUidIoStatsReaderTest
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class StoragedUidIoStatsReaderTest {
+
+    private File mRoot;
+    private File mTestDir;
+    private File mTestFile;
+    // private Random mRand = new Random();
+
+    private StoragedUidIoStatsReader mStoragedUidIoStatsReader;
+    @Mock
+    private StoragedUidIoStatsReader.Callback mCallback;
+
+    private Context getContext() {
+        return InstrumentationRegistry.getContext();
+    }
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mTestDir = getContext().getDir("test", Context.MODE_PRIVATE);
+        mRoot = getContext().getFilesDir();
+        mTestFile = new File(mTestDir, "test.file");
+        mStoragedUidIoStatsReader = new StoragedUidIoStatsReader(mTestFile.getAbsolutePath());
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        FileUtils.deleteContents(mTestDir);
+        FileUtils.deleteContents(mRoot);
+    }
+
+
+    /**
+     * Tests that reading will never call the callback.
+     */
+    @Test
+    public void testReadNonexistentFile() throws Exception {
+        mStoragedUidIoStatsReader.readAbsolute(mCallback);
+        verifyZeroInteractions(mCallback);
+
+    }
+
+    /**
+     * Tests that reading a file with 3 uids works as expected.
+     */
+    @Test
+    public void testReadExpected() throws Exception {
+        BufferedWriter bufferedWriter = Files.newBufferedWriter(mTestFile.toPath());
+        int[] uids = {0, 100, 200};
+        long[] fg_chars_read = {1L, 101L, 201L};
+        long[] fg_chars_write = {2L, 102L, 202L};
+        long[] fg_bytes_read = {3L, 103L, 203L};
+        long[] fg_bytes_write = {4L, 104L, 204L};
+        long[] bg_chars_read = {5L, 105L, 205L};
+        long[] bg_chars_write = {6L, 106L, 206L};
+        long[] bg_bytes_read = {7L, 107L, 207L};
+        long[] bg_bytes_write = {8L, 108L, 208L};
+        long[] fg_fsync = {9L, 109L, 209L};
+        long[] bg_fsync = {10L, 110L, 210L};
+
+        for (int i = 0; i < uids.length; i++) {
+            bufferedWriter.write(String
+                    .format("%d %d %d %d %d %d %d %d %d %d %d\n", uids[i], fg_chars_read[i],
+                            fg_chars_write[i], fg_bytes_read[i], fg_bytes_write[i],
+                            bg_chars_read[i], bg_chars_write[i], bg_bytes_read[i],
+                            bg_bytes_write[i], fg_fsync[i], bg_fsync[i]));
+        }
+        bufferedWriter.close();
+
+        mStoragedUidIoStatsReader.readAbsolute(mCallback);
+        for (int i = 0; i < uids.length; i++) {
+            verify(mCallback).onUidStorageStats(uids[i], fg_chars_read[i], fg_chars_write[i],
+                    fg_bytes_read[i], fg_bytes_write[i], bg_chars_read[i], bg_chars_write[i],
+                    bg_bytes_read[i], bg_bytes_write[i], fg_fsync[i], bg_fsync[i]);
+        }
+        verifyNoMoreInteractions(mCallback);
+
+    }
+
+    /**
+     * Tests that a line with less than 11 items is passed over.
+     */
+    @Test
+    public void testLineDoesNotElevenEntries() throws Exception {
+        BufferedWriter bufferedWriter = Files.newBufferedWriter(mTestFile.toPath());
+
+        // Only has 10 numbers.
+        bufferedWriter.write(String
+                .format("%d %d %d %d %d %d %d %d %d %d\n", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
+
+        bufferedWriter.write(String
+                .format("%d %d %d %d %d %d %d %d %d %d %d\n", 10, 11, 12, 13, 14, 15, 16, 17, 18,
+                        19, 20));
+        bufferedWriter.close();
+
+        // Make sure we get the second line, but the first is skipped.
+        mStoragedUidIoStatsReader.readAbsolute(mCallback);
+        verify(mCallback).onUidStorageStats(10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20);
+        verifyNoMoreInteractions(mCallback);
+    }
+
+
+    /**
+     * Tests that a line that is malformed is passed over.
+     */
+    @Test
+    public void testLineIsMalformed() throws Exception {
+        BufferedWriter bufferedWriter = Files.newBufferedWriter(mTestFile.toPath());
+
+        // Line is not formatted properly. It has a string.
+        bufferedWriter.write(String
+                .format("%d %d %d %d %d %s %d %d %d %d %d\n", 0, 1, 2, 3, 4, "NotANumber", 5, 6, 7,
+                        8, 9));
+
+        bufferedWriter.write(String
+                .format("%d %d %d %d %d %d %d %d %d %d %d\n", 10, 11, 12, 13, 14, 15, 16, 17, 18,
+                        19, 20));
+        bufferedWriter.close();
+
+        // Make sure we get the second line, but the first is skipped.
+        mStoragedUidIoStatsReader.readAbsolute(mCallback);
+        verify(mCallback).onUidStorageStats(10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20);
+        verifyNoMoreInteractions(mCallback);
+    }
+}
diff --git a/data/etc/framework-sysconfig.xml b/data/etc/framework-sysconfig.xml
index ae6a7f6..b0d2de1 100644
--- a/data/etc/framework-sysconfig.xml
+++ b/data/etc/framework-sysconfig.xml
@@ -28,7 +28,7 @@
     <!-- Whitelist of what components are permitted as backup data transports.  The
          'service' attribute here is a flattened ComponentName string. -->
     <backup-transport-whitelisted-service
-        service="android/com.android.internal.backup.LocalTransportService" />
+        service="com.android.localtransport/.LocalTransportService" />
 
     <!-- Whitelist of bundled applications which all handle URLs to their websites by default -->
     <app-link package="com.android.carrierdefaultapp" />
diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk
index 76eb4e6..454dceb 100644
--- a/data/fonts/Android.mk
+++ b/data/fonts/Android.mk
@@ -89,23 +89,7 @@
 
 LOCAL_MODULE := fonts.xml
 LOCAL_MODULE_CLASS := ETC
-
-AOSP_FONTS_FILE := frameworks/base/data/fonts/fonts.xml
-
-ifdef ADDITIONAL_FONTS_FILE
-ADDITIONAL_FONTS_SCRIPT := frameworks/base/tools/fonts/add_additional_fonts.py
-ADD_ADDITIONAL_FONTS := $(local-generated-sources-dir)/fonts.xml
-
-$(ADD_ADDITIONAL_FONTS): PRIVATE_SCRIPT := $(ADDITIONAL_FONTS_SCRIPT)
-$(ADD_ADDITIONAL_FONTS): PRIVATE_ADDITIONAL_FONTS_FILE := $(ADDITIONAL_FONTS_FILE)
-$(ADD_ADDITIONAL_FONTS): $(ADDITIONAL_FONTS_SCRIPT) $(AOSP_FONTS_FILE) $(ADDITIONAL_FONTS_FILE)
-	rm -f $@
-	python $(PRIVATE_SCRIPT) $@ $(PRIVATE_ADDITIONAL_FONTS_FILE)
-else
-ADD_ADDITIONAL_FONTS := $(AOSP_FONTS_FILE)
-endif
-
-LOCAL_PREBUILT_MODULE_FILE := $(ADD_ADDITIONAL_FONTS)
+LOCAL_PREBUILT_MODULE_FILE := frameworks/base/data/fonts/fonts.xml
 
 include $(BUILD_PREBUILT)
 
diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java
index 53e9826..fa37bed 100644
--- a/graphics/java/android/graphics/BaseCanvas.java
+++ b/graphics/java/android/graphics/BaseCanvas.java
@@ -28,11 +28,10 @@
 import android.text.SpannableString;
 import android.text.SpannedString;
 import android.text.TextUtils;
-import android.view.RecordingCanvas;
 
 /**
  * This class is a base class for Canvas's drawing operations. Any modifications here
- * should be accompanied by a similar modification to {@link RecordingCanvas}.
+ * should be accompanied by a similar modification to {@link BaseRecordingCanvas}.
  *
  * The purpose of this class is to minimize the cost of deciding between regular JNI
  * and @FastNative JNI to just the virtual call that Canvas already has.
diff --git a/core/java/android/view/RecordingCanvas.java b/graphics/java/android/graphics/BaseRecordingCanvas.java
similarity index 97%
rename from core/java/android/view/RecordingCanvas.java
rename to graphics/java/android/graphics/BaseRecordingCanvas.java
index 3364483..6e93691 100644
--- a/core/java/android/view/RecordingCanvas.java
+++ b/graphics/java/android/graphics/BaseRecordingCanvas.java
@@ -14,25 +14,12 @@
  * limitations under the License.
  */
 
-package android.view;
+package android.graphics;
 
 import android.annotation.ColorInt;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.Size;
-import android.graphics.BaseCanvas;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Matrix;
-import android.graphics.NinePatch;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.Picture;
-import android.graphics.PorterDuff;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.TemporaryBuffer;
 import android.text.GraphicsOperations;
 import android.text.MeasuredParagraph;
 import android.text.PrecomputedText;
@@ -49,9 +36,9 @@
  *
  * @hide
  */
-public class RecordingCanvas extends Canvas {
+public class BaseRecordingCanvas extends Canvas {
 
-    public RecordingCanvas(long nativeCanvas) {
+    public BaseRecordingCanvas(long nativeCanvas) {
         super(nativeCanvas);
     }
 
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index cea6c1c..9cbbf4e 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -1253,6 +1253,7 @@
             final RenderNode node = RenderNode.create("BitmapTemporary", null);
             node.setLeftTopRightBottom(0, 0, width, height);
             node.setClipToBounds(false);
+            node.setAllowForceDark(false);
             final DisplayListCanvas canvas = node.start(width, height);
             if (source.getWidth() != width || source.getHeight() != height) {
                 canvas.scale(width / (float) source.getWidth(),
diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java
index 82435d5..21cc375 100644
--- a/graphics/java/android/graphics/FontListParser.java
+++ b/graphics/java/android/graphics/FontListParser.java
@@ -40,17 +40,25 @@
     /* Parse fallback list (no names) */
     @UnsupportedAppUsage
     public static FontConfig parse(InputStream in) throws XmlPullParserException, IOException {
+        return parse(in, "/system/fonts");
+    }
+
+    /**
+     * Parse the fonts.xml
+     */
+    public static FontConfig parse(InputStream in, String fontDir)
+            throws XmlPullParserException, IOException {
         try {
             XmlPullParser parser = Xml.newPullParser();
             parser.setInput(in, null);
             parser.nextTag();
-            return readFamilies(parser);
+            return readFamilies(parser, fontDir);
         } finally {
             in.close();
         }
     }
 
-    private static FontConfig readFamilies(XmlPullParser parser)
+    private static FontConfig readFamilies(XmlPullParser parser, String fontDir)
             throws XmlPullParserException, IOException {
         List<FontConfig.Family> families = new ArrayList<>();
         List<FontConfig.Alias> aliases = new ArrayList<>();
@@ -60,7 +68,7 @@
             if (parser.getEventType() != XmlPullParser.START_TAG) continue;
             String tag = parser.getName();
             if (tag.equals("family")) {
-                families.add(readFamily(parser));
+                families.add(readFamily(parser, fontDir));
             } else if (tag.equals("alias")) {
                 aliases.add(readAlias(parser));
             } else {
@@ -71,7 +79,10 @@
                 aliases.toArray(new FontConfig.Alias[aliases.size()]));
     }
 
-    private static FontConfig.Family readFamily(XmlPullParser parser)
+    /**
+     * Reads a family element
+     */
+    public static FontConfig.Family readFamily(XmlPullParser parser, String fontDir)
             throws XmlPullParserException, IOException {
         final String name = parser.getAttributeValue(null, "name");
         final String lang = parser.getAttributeValue("", "lang");
@@ -81,7 +92,7 @@
             if (parser.getEventType() != XmlPullParser.START_TAG) continue;
             final String tag = parser.getName();
             if (tag.equals("font")) {
-                fonts.add(readFont(parser));
+                fonts.add(readFont(parser, fontDir));
             } else {
                 skip(parser);
             }
@@ -102,7 +113,7 @@
     private static final Pattern FILENAME_WHITESPACE_PATTERN =
             Pattern.compile("^[ \\n\\r\\t]+|[ \\n\\r\\t]+$");
 
-    private static FontConfig.Font readFont(XmlPullParser parser)
+    private static FontConfig.Font readFont(XmlPullParser parser, String fontDir)
             throws XmlPullParserException, IOException {
         String indexStr = parser.getAttributeValue(null, "index");
         int index = indexStr == null ? 0 : Integer.parseInt(indexStr);
@@ -125,7 +136,7 @@
             }
         }
         String sanitizedName = FILENAME_WHITESPACE_PATTERN.matcher(filename).replaceAll("");
-        return new FontConfig.Font(sanitizedName, index, axes.toArray(
+        return new FontConfig.Font(fontDir + sanitizedName, index, axes.toArray(
                 new FontVariationAxis[axes.size()]), weight, isItalic, fallbackFor);
     }
 
@@ -137,7 +148,10 @@
         return new FontVariationAxis(tagStr, Float.parseFloat(styleValueStr));
     }
 
-    private static FontConfig.Alias readAlias(XmlPullParser parser)
+    /**
+     * Reads alias elements
+     */
+    public static FontConfig.Alias readAlias(XmlPullParser parser)
             throws XmlPullParserException, IOException {
         String name = parser.getAttributeValue(null, "name");
         String toName = parser.getAttributeValue(null, "to");
@@ -152,7 +166,10 @@
         return new FontConfig.Alias(name, toName, weight);
     }
 
-    private static void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
+    /**
+     * Skip until next element
+     */
+    public static void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
         int depth = 1;
         while (depth > 0) {
             switch (parser.next()) {
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index 7bed1ac..6ce66bd 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -187,7 +187,7 @@
      *  {@link OnHeaderDecodedListener OnHeaderDecodedListener} and once with an
      *  implementation of {@link OnHeaderDecodedListener#onHeaderDecoded onHeaderDecoded}
      *  that calls {@link #setTargetSize} with smaller dimensions. One {@code Source}
-     *  even used simultaneously in multiple threads.</p>
+     *  can even be used simultaneously in multiple threads.</p>
      */
     public static abstract class Source {
         private Source() {}
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 33caa00..69ff3bc 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -592,49 +592,6 @@
         mShadowLayerColor = paint.mShadowLayerColor;
     }
 
-    /**
-     * Returns true if all attributes are equal.
-     *
-     * The caller is expected to have checked the trivial cases, like the pointers being equal,
-     * the objects having different classes, or the parameter being null.
-     * @hide
-     */
-    public boolean hasEqualAttributes(@NonNull Paint other) {
-        return mColorFilter == other.mColorFilter
-                && mMaskFilter == other.mMaskFilter
-                && mPathEffect == other.mPathEffect
-                && mShader == other.mShader
-                && mTypeface == other.mTypeface
-                && mXfermode == other.mXfermode
-                && mHasCompatScaling == other.mHasCompatScaling
-                && mCompatScaling == other.mCompatScaling
-                && mInvCompatScaling == other.mInvCompatScaling
-                && mBidiFlags == other.mBidiFlags
-                && mLocales.equals(other.mLocales)
-                && TextUtils.equals(mFontFeatureSettings, other.mFontFeatureSettings)
-                && TextUtils.equals(mFontVariationSettings, other.mFontVariationSettings)
-                && mShadowLayerRadius == other.mShadowLayerRadius
-                && mShadowLayerDx == other.mShadowLayerDx
-                && mShadowLayerDy == other.mShadowLayerDy
-                && mShadowLayerColor == other.mShadowLayerColor
-                && getFlags() == other.getFlags()
-                && getHinting() == other.getHinting()
-                && getStyle() == other.getStyle()
-                && getColor() == other.getColor()
-                && getStrokeWidth() == other.getStrokeWidth()
-                && getStrokeMiter() == other.getStrokeMiter()
-                && getStrokeCap() == other.getStrokeCap()
-                && getStrokeJoin() == other.getStrokeJoin()
-                && getTextAlign() == other.getTextAlign()
-                && isElegantTextHeight() == other.isElegantTextHeight()
-                && getTextSize() == other.getTextSize()
-                && getTextScaleX() == other.getTextScaleX()
-                && getTextSkewX() == other.getTextSkewX()
-                && getLetterSpacing() == other.getLetterSpacing()
-                && getWordSpacing() == other.getWordSpacing()
-                && getHyphenEdit() == other.getHyphenEdit();
-    }
-
     /** @hide */
     @UnsupportedAppUsage
     public void setCompatibilityScaling(float factor) {
@@ -1395,6 +1352,38 @@
     }
 
     /**
+     * Returns the blur radius of the shadow layer.
+     * @see #setShadowLayer(float,float,float,int)
+     */
+    public float getShadowLayerRadius() {
+        return mShadowLayerRadius;
+    }
+
+    /**
+     * Returns the x offset of the shadow layer.
+     * @see #setShadowLayer(float,float,float,int)
+     */
+    public float getShadowLayerDx() {
+        return mShadowLayerDx;
+    }
+
+    /**
+     * Returns the y offset of the shadow layer.
+     * @see #setShadowLayer(float,float,float,int)
+     */
+    public float getShadowLayerDy() {
+        return mShadowLayerDy;
+    }
+
+    /**
+     * Returns the color of the shadow layer.
+     * @see #setShadowLayer(float,float,float,int)
+     */
+    public @ColorInt int getShadowLayerColor() {
+        return mShadowLayerColor;
+    }
+
+    /**
      * Return the paint's Align value for drawing text. This controls how the
      * text is positioned relative to its origin. LEFT align means that all of
      * the text will be drawn to the right of its origin (i.e. the origin
diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java
index 4fec33f..c4dc0ad 100644
--- a/graphics/java/android/graphics/Rect.java
+++ b/graphics/java/android/graphics/Rect.java
@@ -23,8 +23,11 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
+import android.util.proto.ProtoInputStream;
 import android.util.proto.ProtoOutputStream;
+import android.util.proto.WireTypeMismatchException;
 
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -232,6 +235,40 @@
     }
 
     /**
+     * Read from a protocol buffer input stream.
+     * Protocol buffer message definition at {@link android.graphics.RectProto}
+     *
+     * @param proto     Stream to read the Rect object from.
+     * @param fieldId   Field Id of the Rect as defined in the parent message
+     * @hide
+     */
+    public void readFromProto(@NonNull ProtoInputStream proto, long fieldId) throws IOException,
+            WireTypeMismatchException {
+        final long token = proto.start(fieldId);
+        try {
+            while (proto.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+                switch (proto.getFieldNumber()) {
+                    case (int) RectProto.LEFT:
+                        left = proto.readInt(RectProto.LEFT);
+                        break;
+                    case (int) RectProto.TOP:
+                        top = proto.readInt(RectProto.TOP);
+                        break;
+                    case (int) RectProto.RIGHT:
+                        right = proto.readInt(RectProto.RIGHT);
+                        break;
+                    case (int) RectProto.BOTTOM:
+                        bottom = proto.readInt(RectProto.BOTTOM);
+                        break;
+                }
+            }
+        } finally {
+            // Let caller handle any exceptions
+            proto.end(token);
+        }
+    }
+
+    /**
      * Returns true if the rectangle is empty (left >= right or top >= bottom)
      */
     public final boolean isEmpty() {
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 492c236..7ad207f 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -34,7 +34,6 @@
 import android.provider.FontRequest;
 import android.provider.FontsContract;
 import android.text.FontConfig;
-import android.util.ArrayMap;
 import android.util.Base64;
 import android.util.LongSparseArray;
 import android.util.LruCache;
@@ -1104,6 +1103,9 @@
         }
 
         for (FontConfig.Alias alias : aliases) {
+            if (systemFontMap.containsKey(alias.getName())) {
+                continue; // If alias and named family are conflict, use named family.
+            }
             final Typeface base = systemFontMap.get(alias.getToName());
             final int weight = alias.getWeight();
             final Typeface newFace = weight == 400 ? base :
@@ -1112,13 +1114,6 @@
         }
     }
 
-    // Following methods are left for layoutlib
-    // TODO: Remove once layoutlib stop calling buildSystemFallback
-    /** @hide */
-    public static void buildSystemFallback(String xmlPath, String fontDir,
-            ArrayMap<String, Typeface> fontMap, ArrayMap<String, FontFamily[]> fallbackMap) {
-    }
-
     static {
         final HashMap<String, Typeface> systemFontMap = new HashMap<>();
         initSystemDefaultTypefaces(systemFontMap, SystemFonts.getRawSystemFallbackMap(),
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 76f2cfb..6c1372f 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -51,6 +51,7 @@
 import android.util.TimeUtils;
 import android.view.Choreographer;
 import android.view.DisplayListCanvas;
+import android.view.NativeVectorDrawableAnimator;
 import android.view.RenderNode;
 import android.view.RenderNodeAnimatorSetHelper;
 import android.view.View;
@@ -1231,7 +1232,8 @@
     /**
      * @hide
      */
-    public static class VectorDrawableAnimatorRT implements VectorDrawableAnimator {
+    public static class VectorDrawableAnimatorRT implements VectorDrawableAnimator,
+            NativeVectorDrawableAnimator {
         private static final int START_ANIMATION = 1;
         private static final int REVERSE_ANIMATION = 2;
         private static final int RESET_ANIMATION = 3;
@@ -1704,6 +1706,7 @@
             }
         }
 
+        @Override
         public long getAnimatorNativePtr() {
             return mSetPtr;
         }
diff --git a/graphics/java/android/graphics/fonts/Font.java b/graphics/java/android/graphics/fonts/Font.java
index 1458c66..bd1ac25 100644
--- a/graphics/java/android/graphics/fonts/Font.java
+++ b/graphics/java/android/graphics/fonts/Font.java
@@ -422,9 +422,10 @@
                     nAddAxis(builderPtr, axis.getOpenTypeTagValue(), axis.getStyleValue());
                 }
             }
-            final long ptr = nBuild(builderPtr, mBuffer, mWeight, italic, mTtcIndex);
-            final Font font = new Font(ptr, mBuffer, mFile, mWeight, italic, mTtcIndex, mAxes,
-                    mLocaleList);
+            final ByteBuffer readonlyBuffer = mBuffer.asReadOnlyBuffer();
+            final long ptr = nBuild(builderPtr, readonlyBuffer, mWeight, italic, mTtcIndex);
+            final Font font = new Font(ptr, readonlyBuffer, mFile, mWeight, italic, mTtcIndex,
+                    mAxes, mLocaleList);
             sFontRegistory.registerNativeAllocation(font, ptr);
             return font;
         }
@@ -477,7 +478,7 @@
     }
 
     /**
-     * Retuns a font file buffer.
+     * Returns a font file buffer.
      *
      * @return a font buffer
      */
diff --git a/graphics/java/android/graphics/fonts/FontCustomizationParser.java b/graphics/java/android/graphics/fonts/FontCustomizationParser.java
new file mode 100644
index 0000000..0291d74
--- /dev/null
+++ b/graphics/java/android/graphics/fonts/FontCustomizationParser.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.graphics.fonts;
+
+import android.annotation.NonNull;
+import android.graphics.FontListParser;
+import android.text.FontConfig;
+import android.util.Xml;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashSet;
+
+/**
+ * Parser for font customization
+ *
+ * @hide
+ */
+public class FontCustomizationParser {
+    /**
+     * Represents a customization XML
+     */
+    public static class Result {
+        ArrayList<FontConfig.Family> mAdditionalNamedFamilies = new ArrayList<>();
+        ArrayList<FontConfig.Alias> mAdditionalAliases = new ArrayList<>();
+    }
+
+    /**
+     * Parses the customization XML
+     *
+     * Caller must close the input stream
+     */
+    public static Result parse(@NonNull InputStream in, @NonNull String fontDir)
+            throws XmlPullParserException, IOException {
+        XmlPullParser parser = Xml.newPullParser();
+        parser.setInput(in, null);
+        parser.nextTag();
+        return readFamilies(parser, fontDir);
+    }
+
+    private static void validate(Result result) {
+        HashSet<String> familyNames = new HashSet<>();
+        for (int i = 0; i < result.mAdditionalNamedFamilies.size(); ++i) {
+            final FontConfig.Family family = result.mAdditionalNamedFamilies.get(i);
+            final String name = family.getName();
+            if (name == null) {
+                throw new IllegalArgumentException("new-named-family requires name attribute");
+            }
+            if (!familyNames.add(name)) {
+                throw new IllegalArgumentException(
+                        "new-named-family requires unique name attribute");
+            }
+        }
+    }
+
+    private static Result readFamilies(XmlPullParser parser, String fontDir)
+            throws XmlPullParserException, IOException {
+        Result out = new Result();
+        parser.require(XmlPullParser.START_TAG, null, "fonts-modification");
+        while (parser.next() != XmlPullParser.END_TAG) {
+            if (parser.getEventType() != XmlPullParser.START_TAG) continue;
+            String tag = parser.getName();
+            if (tag.equals("family")) {
+                readFamily(parser, fontDir, out);
+            } else if (tag.equals("alias")) {
+                out.mAdditionalAliases.add(FontListParser.readAlias(parser));
+            } else {
+                FontListParser.skip(parser);
+            }
+        }
+        validate(out);
+        return out;
+    }
+
+    private static void readFamily(XmlPullParser parser, String fontDir, Result out)
+            throws XmlPullParserException, IOException {
+        final String customizationType = parser.getAttributeValue(null, "customizationType");
+        if (customizationType == null) {
+            throw new IllegalArgumentException("customizationType must be specified");
+        }
+        if (customizationType.equals("new-named-family")) {
+            out.mAdditionalNamedFamilies.add(FontListParser.readFamily(parser, fontDir));
+        } else {
+            throw new IllegalArgumentException("Unknown customizationType=" + customizationType);
+        }
+    }
+}
diff --git a/graphics/java/android/graphics/fonts/SystemFonts.java b/graphics/java/android/graphics/fonts/SystemFonts.java
index f4a2199..2d21bbb 100644
--- a/graphics/java/android/graphics/fonts/SystemFonts.java
+++ b/graphics/java/android/graphics/fonts/SystemFonts.java
@@ -45,7 +45,7 @@
 /**
  * Provides the system font configurations.
  */
-public class SystemFonts {
+public final class SystemFonts {
     private static final String TAG = "SystemFonts";
     private static final String DEFAULT_FAMILY = "sans-serif";
 
@@ -58,8 +58,7 @@
     /**
      * Returns all available font files in the system.
      *
-     * Note: The order of this font doesn't indicates anything.
-     * @return an array of system fonts
+     * @return a set of system fonts
      */
     public static @NonNull Set<Font> getAvailableFonts() {
         HashSet<Font> set = new HashSet<>();
@@ -114,7 +113,6 @@
     private static void pushFamilyToFallback(@NonNull FontConfig.Family xmlFamily,
             @NonNull ArrayMap<String, ArrayList<FontFamily>> fallbackMap,
             @NonNull Map<String, ByteBuffer> cache,
-            @NonNull String fontDir,
             @NonNull ArrayList<Font> availableFonts) {
 
         final String languageTags = xmlFamily.getLanguages();
@@ -139,8 +137,7 @@
         }
 
         final FontFamily defaultFamily = defaultFonts.isEmpty() ? null : createFontFamily(
-                xmlFamily.getName(), defaultFonts, languageTags, variant, cache, fontDir,
-                availableFonts);
+                xmlFamily.getName(), defaultFonts, languageTags, variant, cache, availableFonts);
 
         // Insert family into fallback map.
         for (int i = 0; i < fallbackMap.size(); i++) {
@@ -152,7 +149,7 @@
                 }
             } else {
                 final FontFamily family = createFontFamily(
-                        xmlFamily.getName(), fallback, languageTags, variant, cache, fontDir,
+                        xmlFamily.getName(), fallback, languageTags, variant, cache,
                         availableFonts);
                 if (family != null) {
                     fallbackMap.valueAt(i).add(family);
@@ -170,7 +167,6 @@
             @NonNull String languageTags,
             @FontConfig.Family.Variant int variant,
             @NonNull Map<String, ByteBuffer> cache,
-            @NonNull String fontDir,
             @NonNull ArrayList<Font> availableFonts) {
         if (fonts.size() == 0) {
             return null;
@@ -179,7 +175,7 @@
         FontFamily.Builder b = null;
         for (int i = 0; i < fonts.size(); i++) {
             final FontConfig.Font fontConfig = fonts.get(i);
-            final String fullPath = fontDir + fontConfig.getFontName();
+            final String fullPath = fontConfig.getFontName();
             ByteBuffer buffer = cache.get(fullPath);
             if (buffer == null) {
                 if (cache.containsKey(fullPath)) {
@@ -214,6 +210,22 @@
         return b == null ? null : b.build(languageTags, variant);
     }
 
+    private static void appendNamedFamily(@NonNull FontConfig.Family xmlFamily,
+            @NonNull HashMap<String, ByteBuffer> bufferCache,
+            @NonNull ArrayMap<String, ArrayList<FontFamily>> fallbackListMap,
+            @NonNull ArrayList<Font> availableFonts) {
+        final String familyName = xmlFamily.getName();
+        final FontFamily family = createFontFamily(
+                familyName, Arrays.asList(xmlFamily.getFonts()),
+                xmlFamily.getLanguages(), xmlFamily.getVariant(), bufferCache, availableFonts);
+        if (family == null) {
+            return;
+        }
+        final ArrayList<FontFamily> fallback = new ArrayList<>();
+        fallback.add(family);
+        fallbackListMap.put(familyName, fallback);
+    }
+
     /**
      * Build the system fallback from xml file.
      *
@@ -227,11 +239,12 @@
     @VisibleForTesting
     public static FontConfig.Alias[] buildSystemFallback(@NonNull String xmlPath,
             @NonNull String fontDir,
+            @NonNull FontCustomizationParser.Result oemCustomization,
             @NonNull ArrayMap<String, FontFamily[]> fallbackMap,
             @NonNull ArrayList<Font> availableFonts) {
         try {
             final FileInputStream fontsIn = new FileInputStream(xmlPath);
-            final FontConfig fontConfig = FontListParser.parse(fontsIn);
+            final FontConfig fontConfig = FontListParser.parse(fontsIn, fontDir);
 
             final HashMap<String, ByteBuffer> bufferCache = new HashMap<String, ByteBuffer>();
             final FontConfig.Family[] xmlFamilies = fontConfig.getFamilies();
@@ -243,16 +256,12 @@
                 if (familyName == null) {
                     continue;
                 }
-                final FontFamily family = createFontFamily(
-                        xmlFamily.getName(), Arrays.asList(xmlFamily.getFonts()),
-                        xmlFamily.getLanguages(), xmlFamily.getVariant(), bufferCache, fontDir,
-                        availableFonts);
-                if (family == null) {
-                    continue;
-                }
-                final ArrayList<FontFamily> fallback = new ArrayList<>();
-                fallback.add(family);
-                fallbackListMap.put(familyName, fallback);
+                appendNamedFamily(xmlFamily, bufferCache, fallbackListMap, availableFonts);
+            }
+
+            for (int i = 0; i < oemCustomization.mAdditionalNamedFamilies.size(); ++i) {
+                appendNamedFamily(oemCustomization.mAdditionalNamedFamilies.get(i),
+                        bufferCache, fallbackListMap, availableFonts);
             }
 
             // Then, add fallback fonts to the each fallback map.
@@ -261,8 +270,7 @@
                 // The first family (usually the sans-serif family) is always placed immediately
                 // after the primary family in the fallback.
                 if (i == 0 || xmlFamily.getName() == null) {
-                    pushFamilyToFallback(xmlFamily, fallbackListMap, bufferCache, fontDir,
-                            availableFonts);
+                    pushFamilyToFallback(xmlFamily, fallbackListMap, bufferCache, availableFonts);
                 }
             }
 
@@ -275,20 +283,36 @@
                 fallbackMap.put(fallbackName, families);
             }
 
-            return fontConfig.getAliases();
+            final ArrayList<FontConfig.Alias> list = new ArrayList<>();
+            list.addAll(Arrays.asList(fontConfig.getAliases()));
+            list.addAll(oemCustomization.mAdditionalAliases);
+            return list.toArray(new FontConfig.Alias[list.size()]);
         } catch (IOException | XmlPullParserException e) {
             Log.e(TAG, "Failed initialize system fallbacks.", e);
             return ArrayUtils.emptyArray(FontConfig.Alias.class);
         }
     }
 
+    private static FontCustomizationParser.Result readFontCustomization(
+            @NonNull String customizeXml, @NonNull String customFontsDir) {
+        try (FileInputStream f = new FileInputStream(customizeXml)) {
+            return FontCustomizationParser.parse(f, customFontsDir);
+        } catch (IOException e) {
+            return new FontCustomizationParser.Result();
+        } catch (XmlPullParserException e) {
+            Log.e(TAG, "Failed to parse font customization XML", e);
+            return new FontCustomizationParser.Result();
+        }
+    }
+
     static {
         final ArrayMap<String, FontFamily[]> systemFallbackMap = new ArrayMap<>();
         final ArrayList<Font> availableFonts = new ArrayList<>();
+        final FontCustomizationParser.Result oemCustomization =
+                readFontCustomization("/product/etc/fonts_customization.xml", "/product/fonts/");
         sAliases = buildSystemFallback("/system/etc/fonts.xml", "/system/fonts/",
-                systemFallbackMap, availableFonts);
+                oemCustomization, systemFallbackMap, availableFonts);
         sSystemFallbackMap = Collections.unmodifiableMap(systemFallbackMap);
         sAvailableFonts = Collections.unmodifiableList(availableFonts);
     }
-
 }
diff --git a/libs/androidfw/include/androidfw/Util.h b/libs/androidfw/include/androidfw/Util.h
index e4cd6a8..6c9eee0 100644
--- a/libs/androidfw/include/androidfw/Util.h
+++ b/libs/androidfw/include/androidfw/Util.h
@@ -47,11 +47,11 @@
   constexpr unique_cptr() : ptr_(nullptr) {}
   constexpr unique_cptr(std::nullptr_t) : ptr_(nullptr) {}
   explicit unique_cptr(pointer ptr) : ptr_(ptr) {}
-  unique_cptr(unique_cptr&& o) : ptr_(o.ptr_) { o.ptr_ = nullptr; }
+  unique_cptr(unique_cptr&& o) noexcept : ptr_(o.ptr_) { o.ptr_ = nullptr; }
 
   ~unique_cptr() { std::free(reinterpret_cast<void*>(ptr_)); }
 
-  inline unique_cptr& operator=(unique_cptr&& o) {
+  inline unique_cptr& operator=(unique_cptr&& o) noexcept {
     if (&o == this) {
       return *this;
     }
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 11dad2e..494e513 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -229,6 +229,7 @@
         "ResourceCache.cpp",
         "SkiaCanvas.cpp",
         "Snapshot.cpp",
+        "TreeInfo.cpp",
         "VectorDrawable.cpp",
         "protos/graphicsstats.proto",
     ],
diff --git a/libs/hwui/CanvasTransform.cpp b/libs/hwui/CanvasTransform.cpp
index a03b317..06e937a 100644
--- a/libs/hwui/CanvasTransform.cpp
+++ b/libs/hwui/CanvasTransform.cpp
@@ -79,7 +79,6 @@
         info.fColors = _colorStorage.data();
         info.fColorOffsets = _offsetStorage.data();
         SkShader::GradientType type = paint.getShader()->asAGradient(&info);
-        ALOGW_IF(type, "Found gradient of type = %d", type);
 
         if (info.fColorCount <= 10) {
             switch (type) {
@@ -108,6 +107,22 @@
     }
 }
 
+static BitmapPalette paletteForColorHSV(SkColor color) {
+    float hsv[3];
+    SkColorToHSV(color, hsv);
+    return hsv[2] >= .5f ? BitmapPalette::Light : BitmapPalette::Dark;
+}
+
+static BitmapPalette filterPalette(const SkPaint* paint, BitmapPalette palette) {
+    if (palette == BitmapPalette::Unknown || !paint || !paint->getColorFilter()) {
+        return palette;
+    }
+
+    SkColor color = palette == BitmapPalette::Light ? SK_ColorWHITE : SK_ColorBLACK;
+    color = paint->getColorFilter()->filterColor(color);
+    return paletteForColorHSV(color);
+}
+
 bool transformPaint(ColorTransform transform, SkPaint* paint) {
     // TODO
     applyColorTransform(transform, *paint);
@@ -115,6 +130,7 @@
 }
 
 bool transformPaint(ColorTransform transform, SkPaint* paint, BitmapPalette palette) {
+    palette = filterPalette(paint, palette);
     bool shouldInvert = false;
     if (palette == BitmapPalette::Light && transform == ColorTransform::Dark) {
         shouldInvert = true;
diff --git a/libs/hwui/DeviceInfo.cpp b/libs/hwui/DeviceInfo.cpp
index 21fbbdc..0b9d82b 100644
--- a/libs/hwui/DeviceInfo.cpp
+++ b/libs/hwui/DeviceInfo.cpp
@@ -61,18 +61,6 @@
     return displayInfo;
 }
 
-void QueryCompositionPreference(ui::Dataspace* dataSpace,
-                                ui::PixelFormat* pixelFormat) {
-    if (Properties::isolatedProcess) {
-        *dataSpace = ui::Dataspace::V0_SRGB;
-        *pixelFormat = ui::PixelFormat::RGBA_8888;
-    }
-
-    status_t status =
-            SurfaceComposerClient::getCompositionPreference(dataSpace, pixelFormat);
-    LOG_ALWAYS_FATAL_IF(status, "Failed to get composition preference, error %d", status);
-}
-
 DeviceInfo::DeviceInfo() {
 #if HWUI_NULL_GPU
         mMaxTextureSize = NULL_GPU_MAX_TEXTURE_SIZE;
@@ -80,7 +68,6 @@
         mMaxTextureSize = -1;
 #endif
     mDisplayInfo = QueryDisplayInfo();
-    QueryCompositionPreference(&mTargetDataSpace, &mTargetPixelFormat);
 }
 
 int DeviceInfo::maxTextureSize() const {
diff --git a/libs/hwui/DeviceInfo.h b/libs/hwui/DeviceInfo.h
index 1d747741..5956215 100644
--- a/libs/hwui/DeviceInfo.h
+++ b/libs/hwui/DeviceInfo.h
@@ -17,7 +17,6 @@
 #define DEVICEINFO_H
 
 #include <ui/DisplayInfo.h>
-#include <ui/GraphicTypes.h>
 
 #include "utils/Macros.h"
 
@@ -37,9 +36,6 @@
     // this value is only valid after the GPU has been initialized and there is a valid graphics
     // context or if you are using the HWUI_NULL_GPU
     int maxTextureSize() const;
-
-    ui::Dataspace getTargetDataSpace() const { return mTargetDataSpace; }
-    ui::PixelFormat getTargetPixelFormat() const { return mTargetPixelFormat; }
     const DisplayInfo& displayInfo() const { return mDisplayInfo; }
 
 private:
@@ -50,10 +46,6 @@
 
     int mMaxTextureSize;
     DisplayInfo mDisplayInfo;
-
-    // TODO(lpy) Replace below with android_ prefix types.
-    ui::Dataspace mTargetDataSpace;
-    ui::PixelFormat mTargetPixelFormat;
 };
 
 } /* namespace uirenderer */
diff --git a/libs/hwui/DisplayListOps.in b/libs/hwui/DisplayListOps.in
index f61c156..04cf611 100644
--- a/libs/hwui/DisplayListOps.in
+++ b/libs/hwui/DisplayListOps.in
@@ -49,4 +49,5 @@
 X(DrawPoints) 
 X(DrawVertices) 
 X(DrawAtlas) 
-X(DrawShadowRec)
\ No newline at end of file
+X(DrawShadowRec)
+X(DrawVectorDrawable)
\ No newline at end of file
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index 17bec19..a699e2f 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -61,6 +61,7 @@
 bool Properties::disableVsync = false;
 bool Properties::skpCaptureEnabled = false;
 bool Properties::forceDarkMode = false;
+bool Properties::enableForceDarkSupport = false;
 bool Properties::enableRTAnimations = true;
 
 bool Properties::runningInEmulator = false;
@@ -149,6 +150,9 @@
 
     forceDarkMode = property_get_bool(PROPERTY_FORCE_DARK, false);
 
+    // TODO: make this on by default
+    enableForceDarkSupport = property_get_bool(PROPERTY_ENABLE_FORCE_DARK, false);
+
     return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw) ||
            (prevDebugStencilClip != debugStencilClip);
 }
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index ea017a7..542bc71 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -192,6 +192,8 @@
 
 #define PROPERTY_FORCE_DARK "debug.hwui.force_dark"
 
+#define PROPERTY_ENABLE_FORCE_DARK "debug.hwui.force_dark_enabled"
+
 ///////////////////////////////////////////////////////////////////////////////
 // Misc
 ///////////////////////////////////////////////////////////////////////////////
@@ -266,6 +268,7 @@
 
     static bool skpCaptureEnabled;
     static bool forceDarkMode;
+    static bool enableForceDarkSupport;
 
     // For experimentation b/68769804
     ANDROID_API static bool enableRTAnimations;
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 5f54c02..c30af84 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -16,6 +16,8 @@
 
 #include "RecordingCanvas.h"
 
+#include "VectorDrawable.h"
+
 #include "SkCanvas.h"
 #include "SkData.h"
 #include "SkDrawShadowInfo.h"
@@ -498,6 +500,27 @@
     SkDrawShadowRec fRec;
     void draw(SkCanvas* c, const SkMatrix&) const { c->private_draw_shadow_rec(fPath, fRec); }
 };
+
+struct DrawVectorDrawable final : Op {
+    static const auto kType = Type::DrawVectorDrawable;
+    DrawVectorDrawable(VectorDrawableRoot* tree)
+            : mRoot(tree)
+            , mBounds(tree->stagingProperties().getBounds())
+            , palette(tree->computePalette()) {
+        // Recording, so use staging properties
+        tree->getPaintFor(&paint, tree->stagingProperties());
+    }
+
+    void draw(SkCanvas* canvas, const SkMatrix&) const {
+        mRoot->draw(canvas, mBounds, paint);
+    }
+
+    sp<VectorDrawableRoot> mRoot;
+    SkRect mBounds;
+    SkPaint paint;
+    BitmapPalette palette;
+};
+
 }
 
 template <typename T, typename... Args>
@@ -698,6 +721,9 @@
 void DisplayListData::drawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) {
     this->push<DrawShadowRec>(0, path, rec);
 }
+void DisplayListData::drawVectorDrawable(VectorDrawableRoot* tree) {
+    this->push<DrawVectorDrawable>(0, tree);
+}
 
 typedef void (*draw_fn)(const void*, SkCanvas*, const SkMatrix&);
 typedef void (*void_fn)(const void*);
@@ -962,5 +988,9 @@
     fDL->drawShadowRec(path, rec);
 }
 
+void RecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
+    fDL->drawVectorDrawable(tree);
+}
+
 };  // namespace uirenderer
 };  // namespace android
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index eecf51c..80c80ca 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -120,6 +120,7 @@
     void drawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[], int,
                    SkBlendMode, const SkRect*, const SkPaint*);
     void drawShadowRec(const SkPath&, const SkDrawShadowRec&);
+    void drawVectorDrawable(VectorDrawableRoot* tree);
 
     template <typename T, typename... Args>
     void* push(size_t, Args&&...);
@@ -205,6 +206,8 @@
                      SkBlendMode, const SkRect*, const SkPaint*) override;
     void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) override;
 
+    void drawVectorDrawable(VectorDrawableRoot* tree);
+
 private:
     typedef SkCanvasVirtualEnforcer<SkNoDrawCanvas> INHERITED;
 
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 06dbb24..d9a7cc3 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -112,7 +112,9 @@
     LOG_ALWAYS_FATAL_IF(!info.damageAccumulator, "DamageAccumulator missing");
     MarkAndSweepRemoved observer(&info);
 
+    const int before = info.disableForceDark;
     prepareTreeImpl(observer, info, false);
+    LOG_ALWAYS_FATAL_IF(before != info.disableForceDark, "Mis-matched force dark");
 }
 
 void RenderNode::addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
@@ -195,6 +197,11 @@
     if (info.mode == TreeInfo::MODE_FULL) {
         pushStagingPropertiesChanges(info);
     }
+
+    if (!mProperties.getAllowForceDark()) {
+        info.disableForceDark++;
+    }
+
     uint32_t animatorDirtyMask = 0;
     if (CC_LIKELY(info.runAnimations)) {
         animatorDirtyMask = mAnimatorManager.animate(info);
@@ -232,6 +239,9 @@
     }
     pushLayerUpdate(info);
 
+    if (!mProperties.getAllowForceDark()) {
+        info.disableForceDark--;
+    }
     info.damageAccumulator->popTransform();
 }
 
@@ -273,7 +283,7 @@
     if (mDisplayList) {
         mDisplayList->syncContents();
 
-        if (CC_UNLIKELY(Properties::forceDarkMode)) {
+        if (CC_UNLIKELY(info && !info->disableForceDark)) {
             auto usage = usageHint();
             if (mDisplayList->hasText()) {
                 usage = UsageHint::Foreground;
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index 7966845..04379ae 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -535,6 +535,14 @@
         return CC_UNLIKELY(promotedToLayer()) ? LayerType::RenderLayer : mLayerProperties.mType;
     }
 
+    bool setAllowForceDark(bool allow) {
+        return RP_SET(mPrimitiveFields.mAllowForceDark, allow);
+    }
+
+    bool getAllowForceDark() const {
+        return mPrimitiveFields.mAllowForceDark;
+    }
+
 private:
     // Rendering properties
     struct PrimitiveFields {
@@ -554,6 +562,7 @@
         bool mMatrixOrPivotDirty = false;
         bool mProjectBackwards = false;
         bool mProjectionReceiver = false;
+        bool mAllowForceDark = true;
         Rect mClipBounds;
         Outline mOutline;
         RevealClip mRevealClip;
diff --git a/libs/hwui/TreeInfo.cpp b/libs/hwui/TreeInfo.cpp
new file mode 100644
index 0000000..808a12a
--- /dev/null
+++ b/libs/hwui/TreeInfo.cpp
@@ -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.
+ */
+
+#include "TreeInfo.h"
+
+#include "renderthread/CanvasContext.h"
+
+namespace android::uirenderer {
+
+TreeInfo::TreeInfo(TraversalMode mode, renderthread::CanvasContext& canvasContext)
+        : mode(mode)
+        , prepareTextures(mode == MODE_FULL)
+        , canvasContext(canvasContext)
+        , disableForceDark(canvasContext.useForceDark() ? 0 : 1) {}
+
+}  // namespace android::uirenderer
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index f2766d6..a0d9605 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include "Properties.h"
 #include "utils/Macros.h"
 
 #include <utils/Timers.h>
@@ -39,7 +40,7 @@
     virtual void onError(const std::string& message) = 0;
 
 protected:
-    virtual ~ErrorHandler() {}
+    virtual ~ErrorHandler() = default;
 };
 
 class TreeObserver {
@@ -51,7 +52,7 @@
     virtual void onMaybeRemovedFromTree(RenderNode* node) = 0;
 
 protected:
-    virtual ~TreeObserver() {}
+    virtual ~TreeObserver() = default;
 };
 
 // This would be a struct, but we want to PREVENT_COPY_AND_ASSIGN
@@ -70,8 +71,7 @@
         MODE_RT_ONLY,
     };
 
-    TreeInfo(TraversalMode mode, renderthread::CanvasContext& canvasContext)
-            : mode(mode), prepareTextures(mode == MODE_FULL), canvasContext(canvasContext) {}
+    TreeInfo(TraversalMode mode, renderthread::CanvasContext& canvasContext);
 
     TraversalMode mode;
     // TODO: Remove this? Currently this is used to signal to stop preparing
@@ -93,6 +93,8 @@
 
     bool updateWindowPositions = false;
 
+    int disableForceDark;
+
     struct Out {
         bool hasFunctors = false;
         // This is only updated if evaluateAnimations is true
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index 9f82d0f..dbbe9f3 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -458,29 +458,22 @@
         mStagingCache.dirty = false;
     }
 
-    SkPaint tmpPaint;
-    SkPaint* paint = updatePaint(&tmpPaint, &mStagingProperties);
+    SkPaint paint;
+    getPaintFor(&paint, mStagingProperties);
     outCanvas->drawBitmap(*mStagingCache.bitmap, 0, 0, mStagingCache.bitmap->width(),
                           mStagingCache.bitmap->height(), mStagingProperties.getBounds().left(),
                           mStagingProperties.getBounds().top(),
                           mStagingProperties.getBounds().right(),
-                          mStagingProperties.getBounds().bottom(), paint);
+                          mStagingProperties.getBounds().bottom(), &paint);
 }
 
-SkPaint* Tree::getPaint() {
-    return updatePaint(&mPaint, &mProperties);
-}
-
-// Update the given paint with alpha and color filter. Return nullptr if no color filter is
-// specified and root alpha is 1. Otherwise, return updated paint.
-SkPaint* Tree::updatePaint(SkPaint* outPaint, TreeProperties* prop) {
+void Tree::getPaintFor(SkPaint* outPaint, const TreeProperties &prop) const {
     // HWUI always draws VD with bilinear filtering.
     outPaint->setFilterQuality(kLow_SkFilterQuality);
-    if (prop->getRootAlpha() < 1.0f || prop->getColorFilter() != nullptr) {
-        outPaint->setColorFilter(sk_ref_sp(prop->getColorFilter()));
-        outPaint->setAlpha(prop->getRootAlpha() * 255);
+    if (prop.getRootAlpha() < 1.0f || prop.getColorFilter() != nullptr) {
+        outPaint->setColorFilter(sk_ref_sp(prop.getColorFilter()));
+        outPaint->setAlpha(prop.getRootAlpha() * 255);
     }
-    return outPaint;
 }
 
 Bitmap& Tree::getBitmapUpdateIfDirty() {
@@ -553,11 +546,15 @@
     mAtlasKey = INVALID_ATLAS_KEY;
 }
 
-void Tree::draw(SkCanvas* canvas, const SkRect& bounds) {
+void Tree::draw(SkCanvas* canvas, const SkRect& bounds, const SkPaint& inPaint) {
+    // Update the paint for any animatable properties
+    SkPaint paint = inPaint;
+    paint.setAlpha(mProperties.getRootAlpha() * 255);
+
     SkRect src;
     sk_sp<SkSurface> vdSurface = mCache.getSurface(&src);
     if (vdSurface) {
-        canvas->drawImageRect(vdSurface->makeImageSnapshot().get(), src, bounds, getPaint(),
+        canvas->drawImageRect(vdSurface->makeImageSnapshot().get(), src, bounds, &paint,
                               SkCanvas::kFast_SrcRectConstraint);
     } else {
         // Handle the case when VectorDrawableAtlas has been destroyed, because of memory pressure.
@@ -570,7 +567,7 @@
         int scaledWidth = SkScalarCeilToInt(mProperties.getScaledWidth());
         int scaledHeight = SkScalarCeilToInt(mProperties.getScaledHeight());
         canvas->drawBitmapRect(skiaBitmap, SkRect::MakeWH(scaledWidth, scaledHeight), bounds,
-                               getPaint(), SkCanvas::kFast_SrcRectConstraint);
+                               &paint, SkCanvas::kFast_SrcRectConstraint);
         mCache.clear();
         markDirty();
     }
@@ -620,6 +617,80 @@
     }
 }
 
+class MinMaxAverage {
+public:
+    void add(float sample) {
+        if (mCount == 0) {
+            mMin = sample;
+            mMax = sample;
+        } else {
+            mMin = std::min(mMin, sample);
+            mMax = std::max(mMax, sample);
+        }
+        mTotal += sample;
+        mCount++;
+    }
+
+    float average() { return mTotal / mCount; }
+
+    float min() { return mMin; }
+
+    float max() { return mMax; }
+
+    float delta() { return mMax - mMin; }
+
+private:
+    float mMin = 0.0f;
+    float mMax = 0.0f;
+    float mTotal = 0.0f;
+    int mCount = 0;
+};
+
+BitmapPalette Tree::computePalette() {
+    // TODO Cache this and share the code with Bitmap.cpp
+
+    ATRACE_CALL();
+
+    // TODO: This calculation of converting to HSV & tracking min/max is probably overkill
+    // Experiment with something simpler since we just want to figure out if it's "color-ful"
+    // and then the average perceptual lightness.
+
+    MinMaxAverage hue, saturation, value;
+    int sampledCount = 0;
+
+    // Sample a grid of 100 pixels to get an overall estimation of the colors in play
+    mRootNode->forEachFillColor([&](SkColor color) {
+        if (SkColorGetA(color) < 75) {
+            return;
+        }
+        sampledCount++;
+        float hsv[3];
+        SkColorToHSV(color, hsv);
+        hue.add(hsv[0]);
+        saturation.add(hsv[1]);
+        value.add(hsv[2]);
+    });
+
+    if (sampledCount == 0) {
+        ALOGV("VectorDrawable is mostly translucent");
+        return BitmapPalette::Unknown;
+    }
+
+    ALOGV("samples = %d, hue [min = %f, max = %f, avg = %f]; saturation [min = %f, max = %f, avg = "
+          "%f]; value [min = %f, max = %f, avg = %f]",
+          sampledCount, hue.min(), hue.max(), hue.average(), saturation.min(), saturation.max(),
+          saturation.average(), value.min(), value.max(), value.average());
+
+    if (hue.delta() <= 20 && saturation.delta() <= .1f) {
+        if (value.average() >= .5f) {
+            return BitmapPalette::Light;
+        } else {
+            return BitmapPalette::Dark;
+        }
+    }
+    return BitmapPalette::Unknown;
+}
+
 };  // namespace VectorDrawable
 
 };  // namespace uirenderer
diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h
index af0ae05..9c0bb16 100644
--- a/libs/hwui/VectorDrawable.h
+++ b/libs/hwui/VectorDrawable.h
@@ -120,6 +120,8 @@
     virtual void syncProperties() = 0;
     virtual void setAntiAlias(bool aa) = 0;
 
+    virtual void forEachFillColor(const std::function<void(SkColor)>& func) const { }
+
 protected:
     std::string mName;
     PropertyChangedListener* mPropertyChangedListener = nullptr;
@@ -349,6 +351,9 @@
         }
     }
     virtual void setAntiAlias(bool aa) { mAntiAlias = aa; }
+    void forEachFillColor(const std::function<void(SkColor)>& func) const override {
+        func(mStagingProperties.getFillColor());
+    }
 
 protected:
     const SkPath& getUpdatedPath(bool useStagingData, SkPath* tempStagingPath) override;
@@ -480,6 +485,12 @@
         }
     }
 
+    void forEachFillColor(const std::function<void(SkColor)>& func) const override {
+        for (auto& child : mChildren) {
+            child->forEachFillColor(func);
+        }
+    }
+
 private:
     GroupProperties mProperties = GroupProperties(this);
     GroupProperties mStagingProperties = GroupProperties(this);
@@ -495,8 +506,8 @@
 
     // Copy properties from the tree and use the give node as the root node
     Tree(const Tree* copy, Group* rootNode) : Tree(rootNode) {
-        mStagingProperties.syncAnimatableProperties(*copy->stagingProperties());
-        mStagingProperties.syncNonAnimatableProperties(*copy->stagingProperties());
+        mStagingProperties.syncAnimatableProperties(copy->stagingProperties());
+        mStagingProperties.syncNonAnimatableProperties(copy->stagingProperties());
     }
     // Draws the VD onto a bitmap cache, then the bitmap cache will be rendered onto the input
     // canvas. Returns the number of pixels needed for the bitmap cache.
@@ -506,7 +517,6 @@
 
     Bitmap& getBitmapUpdateIfDirty();
     void setAllowCaching(bool allowCaching) { mAllowCaching = allowCaching; }
-    SkPaint* getPaint();
     void syncProperties() {
         if (mStagingProperties.mNonAnimatablePropertiesDirty) {
             mCache.dirty |= (mProperties.mNonAnimatableProperties.viewportWidth !=
@@ -618,7 +628,7 @@
     };
     void onPropertyChanged(TreeProperties* prop);
     TreeProperties* mutateStagingProperties() { return &mStagingProperties; }
-    const TreeProperties* stagingProperties() const { return &mStagingProperties; }
+    const TreeProperties& stagingProperties() const { return mStagingProperties; }
 
     // This should only be called from animations on RT
     TreeProperties* mutateProperties() { return &mProperties; }
@@ -636,7 +646,10 @@
      * Draws VD cache into a canvas. This should always be called from RT and it works with Skia
      * pipelines only.
      */
-    void draw(SkCanvas* canvas, const SkRect& bounds);
+    void draw(SkCanvas* canvas, const SkRect& bounds, const SkPaint& paint);
+
+    void getPaintFor(SkPaint* outPaint, const TreeProperties &props) const;
+    BitmapPalette computePalette();
 
     /**
      * Draws VD into a GPU backed surface.
@@ -680,7 +693,6 @@
         skiapipeline::AtlasKey mAtlasKey = INVALID_ATLAS_KEY;
     };
 
-    SkPaint* updatePaint(SkPaint* outPaint, TreeProperties* prop);
     bool allocateBitmapIfNeeded(Cache& cache, int width, int height);
     bool canReuseBitmap(Bitmap*, int width, int height);
     void updateBitmapCache(Bitmap& outCache, bool useStagingData);
@@ -696,8 +708,6 @@
     TreeProperties mProperties = TreeProperties(this);
     TreeProperties mStagingProperties = TreeProperties(this);
 
-    SkPaint mPaint;
-
     Cache mStagingCache;
     Cache mCache;
 
diff --git a/libs/hwui/hwui/AnimatedImageDrawable.h b/libs/hwui/hwui/AnimatedImageDrawable.h
index 8a44b8b..f0aa35a 100644
--- a/libs/hwui/hwui/AnimatedImageDrawable.h
+++ b/libs/hwui/hwui/AnimatedImageDrawable.h
@@ -106,7 +106,7 @@
     Snapshot decodeNextFrame();
     Snapshot reset();
 
-    size_t byteSize() const { return sizeof(this) + mBytesUsed; }
+    size_t byteSize() const { return sizeof(*this) + mBytesUsed; }
 
 protected:
     virtual void onDraw(SkCanvas* canvas) override;
diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h
index 170335d..43d457a 100644
--- a/libs/hwui/hwui/Bitmap.h
+++ b/libs/hwui/hwui/Bitmap.h
@@ -34,6 +34,8 @@
     Hardware,
 };
 
+// TODO: Find a better home for this. It's here because hwui/Bitmap is exported and CanvasTransform
+// isn't, but cleanup should be done
 enum class BitmapPalette {
     Unknown,
     Light,
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index e8bf492..d401b38 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -167,6 +167,12 @@
         mEglSurface = mEglManager.createSurface(surface, colorMode);
     }
 
+    if (colorMode == ColorMode::SRGB) {
+        mSurfaceColorType = SkColorType::kN32_SkColorType;
+    } else if (colorMode == ColorMode::WideColorGamut) {
+        mSurfaceColorType = SkColorType::kRGBA_F16_SkColorType;
+    }
+
     if (mEglSurface != EGL_NO_SURFACE) {
         const bool preserveBuffer = (swapBehavior != SwapBehavior::kSwap_discardBuffer);
         mBufferPreserved = mEglManager.setPreserveBuffer(mEglSurface, preserveBuffer);
@@ -184,14 +190,6 @@
     return CC_LIKELY(mEglManager.hasEglContext());
 }
 
-SkColorType SkiaOpenGLPipeline::getSurfaceColorType() const {
-    return mEglManager.getSurfaceColorType();
-}
-
-sk_sp<SkColorSpace> SkiaOpenGLPipeline::getSurfaceColorSpace() {
-    return mEglManager.getSurfaceColorSpace();
-}
-
 void SkiaOpenGLPipeline::invokeFunctor(const RenderThread& thread, Functor* functor) {
     DrawGlInfo::Mode mode = DrawGlInfo::kModeProcessNoContext;
     if (thread.eglManager().hasEglContext()) {
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
index 086a760..4ab3541 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
@@ -47,8 +47,6 @@
     void onStop() override;
     bool isSurfaceReady() override;
     bool isContextReady() override;
-    SkColorType getSurfaceColorType() const override;
-    sk_sp<SkColorSpace> getSurfaceColorSpace() override;
 
     static void invokeFunctor(const renderthread::RenderThread& thread, Functor* functor);
 
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.h b/libs/hwui/pipeline/skia/SkiaPipeline.h
index ee9158c..42a411a 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.h
@@ -48,6 +48,9 @@
     bool createOrUpdateLayer(RenderNode* node, const DamageAccumulator& damageAccumulator,
                              ErrorHandler* errorHandler) override;
 
+    SkColorType getSurfaceColorType() const { return mSurfaceColorType; }
+    sk_sp<SkColorSpace> getSurfaceColorSpace() override { return mSurfaceColorSpace; }
+
     void renderFrame(const LayerUpdateQueue& layers, const SkRect& clip,
                      const std::vector<sp<RenderNode>>& nodes, bool opaque,
                      const Rect& contentDrawBounds, sk_sp<SkSurface> surface);
@@ -106,6 +109,8 @@
     void dumpResourceCacheUsage() const;
 
     renderthread::RenderThread& mRenderThread;
+    SkColorType mSurfaceColorType;
+    sk_sp<SkColorSpace> mSurfaceColorSpace;
 
 private:
     void renderFrameImpl(const LayerUpdateQueue& layers, const SkRect& clip,
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index 3042006e..fac07d7 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -130,25 +130,8 @@
     drawDrawable(functorDrawable);
 }
 
-class VectorDrawable : public SkDrawable {
-public:
-    VectorDrawable(VectorDrawableRoot* tree)
-            : mRoot(tree)
-            , mBounds(tree->stagingProperties()->getBounds()) {}
-
-protected:
-    virtual SkRect onGetBounds() override { return mBounds; }
-    virtual void onDraw(SkCanvas* canvas) override {
-        mRoot->draw(canvas, mBounds);
-    }
-
-private:
-    sp<VectorDrawableRoot> mRoot;
-    SkRect mBounds;
-};
-
 void SkiaRecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
-    drawDrawable(mDisplayList->allocateDrawable<VectorDrawable>(tree));
+    mRecorder.drawVectorDrawable(tree);
     mDisplayList->mVectorDrawables.push_back(tree);
 }
 
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index e34f160..a2d8119 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -123,8 +123,7 @@
     }
 
     if (surface) {
-        // TODO: handle color mode
-        mVkSurface = mVkManager.createSurface(surface);
+        mVkSurface = mVkManager.createSurface(surface, colorMode);
     }
 
     return mVkSurface != nullptr;
@@ -138,14 +137,6 @@
     return CC_LIKELY(mVkManager.hasVkContext());
 }
 
-SkColorType SkiaVulkanPipeline::getSurfaceColorType() const {
-    return mVkManager.getSurfaceColorType();
-}
-
-sk_sp<SkColorSpace> SkiaVulkanPipeline::getSurfaceColorSpace() {
-    return mVkManager.getSurfaceColorSpace();
-}
-
 void SkiaVulkanPipeline::invokeFunctor(const RenderThread& thread, Functor* functor) {
     VkFunctorDrawable::vkInvokeFunctor(functor);
 }
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
index 6e723a8..14c0d69 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
@@ -43,8 +43,6 @@
     void onStop() override;
     bool isSurfaceReady() override;
     bool isContextReady() override;
-    SkColorType getSurfaceColorType() const override;
-    sk_sp<SkColorSpace> getSurfaceColorSpace() override;
 
     static void invokeFunctor(const renderthread::RenderThread& thread, Functor* functor);
     static sk_sp<Bitmap> allocateHardwareBitmap(renderthread::RenderThread& thread,
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index c8c394a..92a749f 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -144,8 +144,7 @@
 
     mNativeSurface = std::move(surface);
 
-    // TODO(b/111436479) Introduce a way for app to specify DisplayColorGamut mode.
-    ColorMode colorMode = mWideColorGamut ? ColorMode::WideColorGamut : ColorMode::Legacy;
+    ColorMode colorMode = mWideColorGamut ? ColorMode::WideColorGamut : ColorMode::SRGB;
     bool hasSurface = mRenderPipeline->setSurface(mNativeSurface.get(), mSwapBehavior, colorMode);
 
     mFrameNumber = -1;
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 2315cb9..2307ee4 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -182,6 +182,23 @@
         mFrameCompleteCallbacks.push_back(std::move(func));
     }
 
+    void setForceDark(bool enable) {
+        mUseForceDark = enable;
+    }
+
+    bool useForceDark() {
+        // The force-dark override has the highest priority, followed by the disable setting
+        // for the feature as a whole, followed last by whether or not this context has had
+        // force dark set (typically automatically done via UIMode)
+        if (Properties::forceDarkMode) {
+            return true;
+        }
+        if (!Properties::enableForceDarkSupport) {
+            return false;
+        }
+        return mUseForceDark;
+    }
+
 private:
     CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
                   IContextFactory* contextFactory, std::unique_ptr<IRenderPipeline> renderPipeline);
@@ -228,6 +245,7 @@
 
     bool mOpaque;
     bool mWideColorGamut = false;
+    bool mUseForceDark = false;
     LightInfo mLightInfo;
     LightGeometry mLightGeometry = {{0, 0, 0}, 0};
 
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 0cb23e5..d4ffddd 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -126,17 +126,6 @@
     createContext();
     createPBufferSurface();
     makeCurrent(mPBufferSurface, nullptr, /* force */ true);
-
-    mSurfaceColorGamut = DataSpaceToColorGamut(
-        static_cast<android_dataspace>(DeviceInfo::get()->getTargetDataSpace()));
-
-    LOG_ALWAYS_FATAL_IF(mSurfaceColorGamut == SkColorSpace::kDCIP3_D65_Gamut &&
-                        !EglExtensions.displayP3, "EGL doesn't support Display P3.");
-
-    mSurfaceColorType = PixelFormatToColorType(
-        static_cast<android_pixel_format>(DeviceInfo::get()->getTargetPixelFormat()));
-    mSurfaceColorSpace = DataSpaceToColorSpace(
-        static_cast<android_dataspace>(DeviceInfo::get()->getTargetDataSpace()));
 }
 
 void EglManager::initExtensions() {
@@ -309,21 +298,13 @@
         if (wideColorGamut) {
             attribs[1] = EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT;
         } else {
-            if (mSurfaceColorGamut == SkColorSpace::kDCIP3_D65_Gamut) {
-                attribs[1] = EGL_GL_COLORSPACE_DISPLAY_P3_EXT;
-            } else {
-                attribs[1] = EGL_GL_COLORSPACE_SRGB_KHR;
-            }
+            attribs[1] = EGL_GL_COLORSPACE_SRGB_KHR;
         }
 #else
         if (wideColorGamut) {
             attribs[1] = EGL_GL_COLORSPACE_SCRGB_EXT;
         } else {
-            if (mSurfaceColorGamut == SkColorSpace::kDCIP3_D65_Gamut) {
-                attribs[1] = EGL_GL_COLORSPACE_DISPLAY_P3_EXT;
-            } else {
-                attribs[1] = EGL_GL_COLORSPACE_LINEAR_KHR;
-            }
+            attribs[1] = EGL_GL_COLORSPACE_LINEAR_KHR;
         }
 #endif
     }
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index e97228c..55c81d4 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -78,9 +78,6 @@
     // Depending on installed extensions, the result is either Android native fence or EGL fence.
     status_t createReleaseFence(bool useFenceSync, EGLSyncKHR* eglFence, sp<Fence>& nativeFence);
 
-    SkColorType getSurfaceColorType() const { return mSurfaceColorType; }
-    sk_sp<SkColorSpace> getSurfaceColorSpace() { return mSurfaceColorSpace; }
-
 private:
 
     void initExtensions();
@@ -95,9 +92,6 @@
     EGLContext mEglContext;
     EGLSurface mPBufferSurface;
     EGLSurface mCurrentSurface;
-    SkColorSpace::Gamut mSurfaceColorGamut;
-    SkColorType mSurfaceColorType;
-    sk_sp<SkColorSpace> mSurfaceColorSpace;
 
     enum class SwapBehavior {
         Discard,
diff --git a/libs/hwui/renderthread/IRenderPipeline.h b/libs/hwui/renderthread/IRenderPipeline.h
index 0297c9c..4972554 100644
--- a/libs/hwui/renderthread/IRenderPipeline.h
+++ b/libs/hwui/renderthread/IRenderPipeline.h
@@ -43,15 +43,8 @@
 enum class MakeCurrentResult { AlreadyCurrent, Failed, Succeeded };
 
 enum class ColorMode {
-    // Legacy means HWUI will produce buffer with whatever platform prefers
-    // HWUI to produce, however, HWUI doesn't accurately convert color from
-    // source color space to destination color space, instead HWUI will take
-    // the pixel value directly and interpret it destination color space.
-    Legacy,
-    // DisplayColorGamut means HWUI will produce buffer with whatever platform
-    // prefers HWUI to produce and accurately convert color from source color
-    // space to destination color space.
-    DisplayColorGamut,
+    // SRGB means HWUI will produce buffer in SRGB color space.
+    SRGB,
     // WideColorGamut means HWUI would support rendering scRGB non-linear into
     // a signed buffer with enough range to support the wide color gamut of the
     // display.
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 6106e24..54219b5 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -298,6 +298,12 @@
     });
 }
 
+void RenderProxy::setForceDark(bool enable) {
+    mRenderThread.queue().post([this, enable]() {
+        mContext->setForceDark(enable);
+    });
+}
+
 int RenderProxy::copySurfaceInto(sp<Surface>& surface, int left, int top, int right, int bottom,
                                  SkBitmap* bitmap) {
     auto& thread = RenderThread::getInstance();
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index d22f56e..d29fcc4 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -119,7 +119,7 @@
 
     ANDROID_API void addFrameMetricsObserver(FrameMetricsObserver* observer);
     ANDROID_API void removeFrameMetricsObserver(FrameMetricsObserver* observer);
-    ANDROID_API long getDroppedFrameReportCount();
+    ANDROID_API void setForceDark(bool enable);
 
     ANDROID_API static int copySurfaceInto(sp<Surface>& surface, int left, int top, int right,
                                            int bottom, SkBitmap* bitmap);
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index e60d43e..83e9db3 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -16,6 +16,8 @@
 
 #include "VulkanManager.h"
 
+#include <private/gui/SyncFeatures.h>
+
 #include "Properties.h"
 #include "RenderThread.h"
 #include "renderstate/RenderState.h"
@@ -41,6 +43,10 @@
 void VulkanManager::destroy() {
     mRenderThread.setGrContext(nullptr);
 
+    // We don't need to explicitly free the command buffer since it automatically gets freed when we
+    // delete the VkCommandPool below.
+    mDummyCB = VK_NULL_HANDLE;
+
     if (VK_NULL_HANDLE != mCommandPool) {
         mDestroyCommandPool(mDevice, mCommandPool, nullptr);
         mCommandPool = VK_NULL_HANDLE;
@@ -226,6 +232,11 @@
     grExtensions.init(getProc, mInstance, mPhysicalDevice, instanceExtensions.size(),
             instanceExtensions.data(), deviceExtensions.size(), deviceExtensions.data());
 
+    if (!grExtensions.hasExtension(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, 1)) {
+        this->destroy();
+        return false;
+    }
+
     memset(&features, 0, sizeof(VkPhysicalDeviceFeatures2));
     features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
     features.pNext = nullptr;
@@ -313,6 +324,8 @@
     GET_DEV_PROC(DeviceWaitIdle);
     GET_DEV_PROC(CreateSemaphore);
     GET_DEV_PROC(DestroySemaphore);
+    GET_DEV_PROC(ImportSemaphoreFdKHR);
+    GET_DEV_PROC(GetSemaphoreFdKHR);
     GET_DEV_PROC(CreateFence);
     GET_DEV_PROC(DestroyFence);
     GET_DEV_PROC(WaitForFences);
@@ -384,6 +397,14 @@
                 &mCommandPool);
         SkASSERT(VK_SUCCESS == res);
     }
+    LOG_ALWAYS_FATAL_IF(mCommandPool == VK_NULL_HANDLE);
+
+    if (!setupDummyCommandBuffer()) {
+        this->destroy();
+        return;
+    }
+    LOG_ALWAYS_FATAL_IF(mDummyCB == VK_NULL_HANDLE);
+
 
     mGetDeviceQueue(mDevice, mPresentQueueIndex, 0, &mPresentQueue);
 
@@ -597,7 +618,8 @@
         VulkanSurface::ImageInfo& imageInfo = surface->mImageInfos[i];
         imageInfo.mSurface = SkSurface::MakeFromBackendRenderTarget(
                 mRenderThread.getGrContext(), backendRT, kTopLeft_GrSurfaceOrigin,
-                kRGBA_8888_SkColorType, nullptr, &props);
+                surface->mColorMode == ColorMode::WideColorGamut ? kRGBA_F16_SkColorType
+                : kRGBA_8888_SkColorType, nullptr, &props);
     }
 
     SkASSERT(mCommandPool != VK_NULL_HANDLE);
@@ -712,24 +734,22 @@
                     ? VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR
                     : VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
 
-    // Pick our surface format. For now, just make sure it matches our sRGB request:
-    VkFormat surfaceFormat = VK_FORMAT_UNDEFINED;
+    VkFormat surfaceFormat = VK_FORMAT_R8G8B8A8_UNORM;
     VkColorSpaceKHR colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
-
-    bool wantSRGB = false;
-#ifdef ANDROID_ENABLE_LINEAR_BLENDING
-    wantSRGB = true;
-#endif
+    if (surface->mColorMode == ColorMode::WideColorGamut) {
+        surfaceFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
+        colorSpace = VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT;
+    }
+    bool foundSurfaceFormat = false;
     for (uint32_t i = 0; i < surfaceFormatCount; ++i) {
-        // We are assuming we can get either R8G8B8A8_UNORM or R8G8B8A8_SRGB
-        VkFormat desiredFormat = wantSRGB ? VK_FORMAT_R8G8B8A8_SRGB : VK_FORMAT_R8G8B8A8_UNORM;
-        if (desiredFormat == surfaceFormats[i].format) {
-            surfaceFormat = surfaceFormats[i].format;
-            colorSpace = surfaceFormats[i].colorSpace;
+        if (surfaceFormat == surfaceFormats[i].format
+                && colorSpace == surfaceFormats[i].colorSpace) {
+            foundSurfaceFormat = true;
+            break;
         }
     }
 
-    if (VK_FORMAT_UNDEFINED == surfaceFormat) {
+    if (!foundSurfaceFormat) {
         return false;
     }
 
@@ -791,14 +811,14 @@
     return true;
 }
 
-VulkanSurface* VulkanManager::createSurface(ANativeWindow* window) {
+VulkanSurface* VulkanManager::createSurface(ANativeWindow* window, ColorMode colorMode) {
     initialize();
 
     if (!window) {
         return nullptr;
     }
 
-    VulkanSurface* surface = new VulkanSurface();
+    VulkanSurface* surface = new VulkanSurface(colorMode);
 
     VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo;
     memset(&surfaceCreateInfo, 0, sizeof(VkAndroidSurfaceCreateInfoKHR));
@@ -976,19 +996,176 @@
     return surface->mCurrentTime - lastUsed;
 }
 
+bool VulkanManager::setupDummyCommandBuffer() {
+    if (mDummyCB != VK_NULL_HANDLE) {
+        return true;
+    }
+
+    VkCommandBufferAllocateInfo commandBuffersInfo;
+    memset(&commandBuffersInfo, 0, sizeof(VkCommandBufferAllocateInfo));
+    commandBuffersInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+    commandBuffersInfo.pNext = nullptr;
+    commandBuffersInfo.commandPool = mCommandPool;
+    commandBuffersInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+    commandBuffersInfo.commandBufferCount = 1;
+
+    VkResult err = mAllocateCommandBuffers(mDevice, &commandBuffersInfo, &mDummyCB);
+    if (err != VK_SUCCESS) {
+        // It is probably unnecessary to set this back to VK_NULL_HANDLE, but we set it anyways to
+        // make sure the driver didn't set a value and then return a failure.
+        mDummyCB = VK_NULL_HANDLE;
+        return false;
+    }
+
+    VkCommandBufferBeginInfo beginInfo;
+    memset(&beginInfo, 0, sizeof(VkCommandBufferBeginInfo));
+    beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+    beginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
+
+    mBeginCommandBuffer(mDummyCB, &beginInfo);
+    mEndCommandBuffer(mDummyCB);
+    return true;
+}
+
 status_t VulkanManager::fenceWait(sp<Fence>& fence) {
-    //TODO: Insert a wait on fence command into the Vulkan command buffer.
-    // Block CPU on the fence.
-    status_t err = fence->waitForever("VulkanManager::fenceWait");
-    if (err != NO_ERROR) {
-        ALOGE("VulkanManager::fenceWait: error waiting for fence: %d", err);
-        return err;
+    if (!hasVkContext()) {
+        ALOGE("VulkanManager::fenceWait: VkDevice not initialized");
+        return INVALID_OPERATION;
+    }
+
+    if (SyncFeatures::getInstance().useWaitSync() &&
+        SyncFeatures::getInstance().useNativeFenceSync()) {
+        // Block GPU on the fence.
+        int fenceFd = fence->dup();
+        if (fenceFd == -1) {
+            ALOGE("VulkanManager::fenceWait: error dup'ing fence fd: %d", errno);
+            return -errno;
+        }
+
+        VkSemaphoreCreateInfo semaphoreInfo;
+        semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+        semaphoreInfo.pNext = nullptr;
+        semaphoreInfo.flags = 0;
+        VkSemaphore semaphore;
+        VkResult err = mCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore);
+        if (VK_SUCCESS != err) {
+            ALOGE("Failed to create import semaphore, err: %d", err);
+            return UNKNOWN_ERROR;
+        }
+        VkImportSemaphoreFdInfoKHR importInfo;
+        importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR;
+        importInfo.pNext = nullptr;
+        importInfo.semaphore = semaphore;
+        importInfo.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT;
+        importInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
+        importInfo.fd = fenceFd;
+
+        err = mImportSemaphoreFdKHR(mDevice, &importInfo);
+        if (VK_SUCCESS != err) {
+            ALOGE("Failed to import semaphore, err: %d", err);
+            return UNKNOWN_ERROR;
+        }
+
+        LOG_ALWAYS_FATAL_IF(mDummyCB == VK_NULL_HANDLE);
+
+        VkPipelineStageFlags waitDstStageFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+
+        VkSubmitInfo submitInfo;
+        memset(&submitInfo, 0, sizeof(VkSubmitInfo));
+        submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+        submitInfo.waitSemaphoreCount = 1;
+        // Wait to make sure aquire semaphore set above has signaled.
+        submitInfo.pWaitSemaphores = &semaphore;
+        submitInfo.pWaitDstStageMask = &waitDstStageFlags;
+        submitInfo.commandBufferCount = 1;
+        submitInfo.pCommandBuffers = &mDummyCB;
+        submitInfo.signalSemaphoreCount = 0;
+
+        mQueueSubmit(mGraphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
+
+        // On Android when we import a semaphore, it is imported using temporary permanence. That
+        // means as soon as we queue the semaphore for a wait it reverts to its previous permanent
+        // state before importing. This means it will now be in an idle state with no pending
+        // signal or wait operations, so it is safe to immediately delete it.
+        mDestroySemaphore(mDevice, semaphore, nullptr);
+    } else {
+        // Block CPU on the fence.
+        status_t err = fence->waitForever("VulkanManager::fenceWait");
+        if (err != NO_ERROR) {
+            ALOGE("VulkanManager::fenceWait: error waiting for fence: %d", err);
+            return err;
+        }
     }
     return OK;
 }
 
 status_t VulkanManager::createReleaseFence(sp<Fence>& nativeFence) {
-    //TODO: Create a fence that is signaled, when all the pending Vulkan commands are flushed.
+    if (!hasVkContext()) {
+        ALOGE("VulkanManager::createReleaseFence: VkDevice not initialized");
+        return INVALID_OPERATION;
+    }
+
+    if (SyncFeatures::getInstance().useFenceSync()) {
+        ALOGE("VulkanManager::createReleaseFence: Vk backend doesn't support non-native fences");
+        return INVALID_OPERATION;
+    }
+
+    if (!SyncFeatures::getInstance().useNativeFenceSync()) {
+        return OK;
+    }
+
+    VkExportSemaphoreCreateInfo exportInfo;
+    exportInfo.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO;
+    exportInfo.pNext = nullptr;
+    exportInfo.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
+
+    VkSemaphoreCreateInfo semaphoreInfo;
+    semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+    semaphoreInfo.pNext = &exportInfo;
+    semaphoreInfo.flags = 0;
+    VkSemaphore semaphore;
+    VkResult err = mCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore);
+    if (VK_SUCCESS != err) {
+        ALOGE("VulkanManager::createReleaseFence: Failed to create semaphore");
+        return INVALID_OPERATION;
+    }
+
+    LOG_ALWAYS_FATAL_IF(mDummyCB == VK_NULL_HANDLE);
+
+    VkSubmitInfo submitInfo;
+    memset(&submitInfo, 0, sizeof(VkSubmitInfo));
+    submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+    submitInfo.waitSemaphoreCount = 0;
+    submitInfo.pWaitSemaphores = nullptr;
+    submitInfo.pWaitDstStageMask = nullptr;
+    submitInfo.commandBufferCount = 1;
+    submitInfo.pCommandBuffers = &mDummyCB;
+    submitInfo.signalSemaphoreCount = 1;
+    submitInfo.pSignalSemaphores = &semaphore;
+
+    mQueueSubmit(mGraphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
+
+    VkSemaphoreGetFdInfoKHR getFdInfo;
+    getFdInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR;
+    getFdInfo.pNext = nullptr;
+    getFdInfo.semaphore = semaphore;
+    getFdInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
+
+    int fenceFd = 0;
+
+    err = mGetSemaphoreFdKHR(mDevice, &getFdInfo, &fenceFd);
+    if (VK_SUCCESS != err) {
+        ALOGE("VulkanManager::createReleaseFence: Failed to get semaphore Fd");
+        return INVALID_OPERATION;
+    }
+    nativeFence = new Fence(fenceFd);
+
+    // Exporting a semaphore with copy transference via vkGetSemahporeFdKHR, has the same effect of
+    // destroying the semaphore and creating a new one with the same handle, and the payloads
+    // ownership is move to the Fd we created. Thus the semahpore is in a state that we can delete
+    // it and we don't need to wait on the command buffer we submitted to finish.
+    mDestroySemaphore(mDevice, semaphore, nullptr);
+
     return OK;
 }
 
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index 7a539ae..7c59b6d 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -26,6 +26,7 @@
 #include <ui/Fence.h>
 #include <utils/StrongPointer.h>
 #include <vk/GrVkBackendContext.h>
+#include "IRenderPipeline.h"
 
 class GrVkExtensions;
 
@@ -37,7 +38,7 @@
 
 class VulkanSurface {
 public:
-    VulkanSurface() {}
+    VulkanSurface(ColorMode colorMode) : mColorMode(colorMode) {}
 
     sk_sp<SkSurface> getBackBufferSurface() { return mBackbuffer; }
 
@@ -73,6 +74,7 @@
     VkImage* mImages = nullptr;
     ImageInfo* mImageInfos;
     uint16_t mCurrentTime = 0;
+    ColorMode mColorMode;
 };
 
 // This class contains the shared global Vulkan objects, such as VkInstance, VkDevice and VkQueue,
@@ -90,7 +92,7 @@
 
     // Given a window this creates a new VkSurfaceKHR and VkSwapchain and stores them inside a new
     // VulkanSurface object which is returned.
-    VulkanSurface* createSurface(ANativeWindow* window);
+    VulkanSurface* createSurface(ANativeWindow* window, ColorMode colorMode);
 
     // Destroy the VulkanSurface and all associated vulkan objects.
     void destroySurface(VulkanSurface* surface);
@@ -118,10 +120,6 @@
     // Creates a fence that is signaled, when all the pending Vulkan commands are flushed.
     status_t createReleaseFence(sp<Fence>& nativeFence);
 
-    // TODO(b/115636873): Handle composition preference.
-    SkColorType getSurfaceColorType() const { return SkColorType::kN32_SkColorType; }
-    sk_sp<SkColorSpace> getSurfaceColorSpace() { return SkColorSpace::MakeSRGB(); }
-
 private:
     friend class RenderThread;
 
@@ -139,6 +137,8 @@
 
     VulkanSurface::BackbufferInfo* getAvailableBackbuffer(VulkanSurface* surface);
 
+    bool setupDummyCommandBuffer();
+
     // simple wrapper class that exists only to initialize a pointer to NULL
     template <typename FNPTR_TYPE>
     class VkPtr {
@@ -199,6 +199,8 @@
 
     VkPtr<PFN_vkCreateSemaphore> mCreateSemaphore;
     VkPtr<PFN_vkDestroySemaphore> mDestroySemaphore;
+    VkPtr<PFN_vkImportSemaphoreFdKHR> mImportSemaphoreFdKHR;
+    VkPtr<PFN_vkGetSemaphoreFdKHR> mGetSemaphoreFdKHR;
     VkPtr<PFN_vkCreateFence> mCreateFence;
     VkPtr<PFN_vkDestroyFence> mDestroyFence;
     VkPtr<PFN_vkWaitForFences> mWaitForFences;
@@ -216,6 +218,8 @@
     VkQueue mPresentQueue = VK_NULL_HANDLE;
     VkCommandPool mCommandPool = VK_NULL_HANDLE;
 
+    VkCommandBuffer mDummyCB = VK_NULL_HANDLE;
+
     enum class SwapBehavior {
         Discard,
         BufferAge,
diff --git a/libs/hwui/tests/unit/SkiaPipelineTests.cpp b/libs/hwui/tests/unit/SkiaPipelineTests.cpp
index 680fcb3..cdf31da 100644
--- a/libs/hwui/tests/unit/SkiaPipelineTests.cpp
+++ b/libs/hwui/tests/unit/SkiaPipelineTests.cpp
@@ -386,7 +386,7 @@
 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, context_lost) {
     auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
     EXPECT_FALSE(pipeline->isSurfaceReady());
-    EXPECT_TRUE(pipeline->setSurface((Surface*)0x01, SwapBehavior::kSwap_default, ColorMode::Legacy));
+    EXPECT_TRUE(pipeline->setSurface((Surface*)0x01, SwapBehavior::kSwap_default, ColorMode::SRGB));
     EXPECT_TRUE(pipeline->isSurfaceReady());
     renderThread.destroyGlContext();
     EXPECT_FALSE(pipeline->isSurfaceReady());
diff --git a/libs/hwui/utils/Color.cpp b/libs/hwui/utils/Color.cpp
index 9f71e91..3fb6a31 100644
--- a/libs/hwui/utils/Color.cpp
+++ b/libs/hwui/utils/Color.cpp
@@ -57,21 +57,6 @@
     return false;
 }
 
-SkColorType PixelFormatToColorType(android_pixel_format pixelFormat) {
-    switch (pixelFormat) {
-        case HAL_PIXEL_FORMAT_RGBA_8888:
-        case HAL_PIXEL_FORMAT_BGRA_8888:
-            return SkColorType::kN32_SkColorType;
-        case HAL_PIXEL_FORMAT_RGBA_FP16:
-            return SkColorType::kRGBA_F16_SkColorType;
-        case HAL_PIXEL_FORMAT_RGBA_1010102:
-            return SkColorType::kRGBA_1010102_SkColorType;
-        default:
-            ALOGW("Unsupported pixel format: %d, return kN32 by default", pixelFormat);
-            return SkColorType::kN32_SkColorType;
-    }
-}
-
 android::PixelFormat ColorTypeToPixelFormat(SkColorType colorType) {
     switch (colorType) {
         case kRGBA_8888_SkColorType:
@@ -92,30 +77,6 @@
     }
 }
 
-SkColorSpace::Gamut DataSpaceToColorGamut(android_dataspace dataSpace) {
-    switch (dataSpace & HAL_DATASPACE_STANDARD_MASK) {
-        case HAL_DATASPACE_STANDARD_BT709:
-            return SkColorSpace::kSRGB_Gamut;
-        case HAL_DATASPACE_STANDARD_BT2020:
-            return SkColorSpace::kRec2020_Gamut;
-        case HAL_DATASPACE_STANDARD_DCI_P3:
-            return SkColorSpace::kDCIP3_D65_Gamut;
-        case HAL_DATASPACE_STANDARD_ADOBE_RGB:
-            return SkColorSpace::kAdobeRGB_Gamut;
-        case HAL_DATASPACE_STANDARD_UNSPECIFIED:
-        case HAL_DATASPACE_STANDARD_BT601_625:
-        case HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED:
-        case HAL_DATASPACE_STANDARD_BT601_525:
-        case HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED:
-        case HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE:
-        case HAL_DATASPACE_STANDARD_BT470M:
-        case HAL_DATASPACE_STANDARD_FILM:
-        default:
-            ALOGW("Unsupported Gamut: %d, return SRGB gamut by default", dataSpace);
-            return SkColorSpace::kSRGB_Gamut;
-    }
-}
-
 sk_sp<SkColorSpace> DataSpaceToColorSpace(android_dataspace dataspace) {
 
     SkColorSpace::Gamut gamut;
diff --git a/libs/hwui/utils/Color.h b/libs/hwui/utils/Color.h
index e935a0d..4daccda 100644
--- a/libs/hwui/utils/Color.h
+++ b/libs/hwui/utils/Color.h
@@ -115,12 +115,8 @@
 // returns true for sRGB, gamma 2.2 and Display P3 for instance
 bool transferFunctionCloseToSRGB(const SkColorSpace* colorSpace);
 
-SkColorType PixelFormatToColorType(android_pixel_format pixelFormat);
-
 android::PixelFormat ColorTypeToPixelFormat(SkColorType colorType);
 
-SkColorSpace::Gamut DataSpaceToColorGamut(android_dataspace dataSpace);
-
 sk_sp<SkColorSpace> DataSpaceToColorSpace(android_dataspace dataspace);
 
 struct Lab {
diff --git a/location/lib/Android.bp b/location/lib/Android.bp
index 447195d..b09335c 100644
--- a/location/lib/Android.bp
+++ b/location/lib/Android.bp
@@ -18,4 +18,5 @@
     name: "com.android.location.provider",
     srcs: ["java/**/*.java"],
     api_packages: ["com.android.location.provider"],
+    metalava_enabled: false,
 }
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index ed4da22..340f279 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -336,7 +336,7 @@
  *
  * <table border="0" cellspacing="0" cellpadding="0">
  * <tr><td>Method Name </p></td>
- *     <td>Valid Sates </p></td>
+ *     <td>Valid States </p></td>
  *     <td>Invalid States </p></td>
  *     <td>Comments </p></td></tr>
  * <tr><td>attachAuxEffect </p></td>
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index 6187900..dfcbabe 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -36,8 +36,6 @@
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Message;
-import android.os.Parcel;
-import android.os.Parcelable;
 import android.os.PersistableBundle;
 import android.os.PowerManager;
 import android.os.Process;
@@ -60,7 +58,6 @@
 import dalvik.system.CloseGuard;
 
 import libcore.io.IoBridge;
-import libcore.io.Streams;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -86,6 +83,7 @@
 import java.util.UUID;
 import java.util.Vector;
 import java.util.concurrent.Executor;
+import java.util.concurrent.RejectedExecutionException;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
@@ -253,21 +251,6 @@
             void process() {
                 stayAwake(false);
 
-                // TODO: remove this block when native code allows prepared -> pause
-                // and sends MEDIA_INFO_DATA_SOURCE_START when pipeline is created.
-                if (getState() == PLAYER_STATE_PREPARED) {
-                    final DataSourceDesc dsd;
-                    synchronized (mSrcLock) {
-                        dsd = mCurrentDSD;
-                    }
-                    synchronized (mEventCbLock) {
-                        for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
-                            cb.first.execute(() -> cb.second.onInfo(
-                                    MediaPlayer2Impl.this, dsd, MEDIA_INFO_DATA_SOURCE_START, 0));
-                        }
-                    }
-                }
-
                 _pause();
             }
         });
@@ -285,7 +268,10 @@
         addTask(new Task(CALL_COMPLETED_SKIP_TO_NEXT, false) {
             @Override
             void process() {
-                // TODO: switch to next data source and play
+                if (getState() == PLAYER_STATE_PLAYING) {
+                    pause();
+                }
+                playNextDataSource();
             }
         });
     }
@@ -346,19 +332,14 @@
                     final String msg = "Cannot set AudioAttributes to null";
                     throw new IllegalArgumentException(msg);
                 }
-                Parcel pattributes = Parcel.obtain();
-                attributes.writeToParcel(pattributes, AudioAttributes.FLATTEN_TAGS);
-                setParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES, pattributes);
-                pattributes.recycle();
+                setParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES, attributes);
             }
         });
     }
 
     @Override
     public @NonNull AudioAttributes getAudioAttributes() {
-        Parcel pattributes = getParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES);
-        AudioAttributes attributes = AudioAttributes.CREATOR.createFromParcel(pattributes);
-        pattributes.recycle();
+        AudioAttributes attributes = (AudioAttributes) getParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES);
         return attributes;
     }
 
@@ -572,12 +553,13 @@
         addTask(new Task(CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED, false) {
             @Override
             void process() {
-                synchronized (mEventCbLock) {
-                    for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
-                        cb.first.execute(() -> cb.second.onCommandLabelReached(
-                                MediaPlayer2Impl.this, label));
+                sendEvent(new EventNotifier() {
+                    @Override
+                    public void notify(EventCallback callback) {
+                        callback.onCommandLabelReached(
+                                MediaPlayer2Impl.this, label);
                     }
-                }
+                });
             }
         });
     }
@@ -995,12 +977,13 @@
         }
 
         if (!hasNextDSD) {
-            synchronized (mEventCbLock) {
-                for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
-                    cb.first.execute(() -> cb.second.onInfo(
-                            MediaPlayer2Impl.this, null, MEDIA_INFO_DATA_SOURCE_LIST_END, 0));
+            sendEvent(new EventNotifier() {
+                @Override
+                public void notify(EventCallback callback) {
+                    callback.onInfo(
+                            MediaPlayer2Impl.this, null, MEDIA_INFO_DATA_SOURCE_LIST_END, 0);
                 }
-            }
+            });
         }
     }
 
@@ -1597,9 +1580,9 @@
      * @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, Parcel value);
+    private native boolean setParameter(int key, Object value);
 
-    private native Parcel getParameter(int key);
+    private native Object getParameter(int key);
 
 
     /**
@@ -2583,12 +2566,13 @@
                 }
 
                 if (dsd != null) {
-                    synchronized (mEventCbLock) {
-                        for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
-                            cb.first.execute(() -> cb.second.onInfo(
-                                    mMediaPlayer, dsd, MEDIA_INFO_PREPARED, 0));
+                    sendEvent(new EventNotifier() {
+                        @Override
+                        public void notify(EventCallback callback) {
+                            callback.onInfo(
+                                    mMediaPlayer, dsd, MEDIA_INFO_PREPARED, 0);
                         }
-                    }
+                    });
                 }
 
                 synchronized (mSrcLock) {
@@ -2636,12 +2620,13 @@
 
                     // notifying the client outside the lock
                     if (drmInfo != null) {
-                        synchronized (mEventCbLock) {
-                            for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) {
-                                cb.first.execute(() -> cb.second.onDrmInfo(
-                                        mMediaPlayer, dsd, drmInfo));
+                        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);
@@ -2652,12 +2637,13 @@
             case MEDIA_PLAYBACK_COMPLETE:
             {
                 if (isCurrentSrcId) {
-                    synchronized (mEventCbLock) {
-                        for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
-                            cb.first.execute(() -> cb.second.onInfo(
-                                    mMediaPlayer, dsd, MEDIA_INFO_DATA_SOURCE_END, 0));
+                    sendEvent(new EventNotifier() {
+                        @Override
+                        public void notify(EventCallback callback) {
+                            callback.onInfo(
+                                    mMediaPlayer, dsd, MEDIA_INFO_DATA_SOURCE_END, 0);
                         }
-                    }
+                    });
                     stayAwake(false);
 
                     synchronized (mSrcLock) {
@@ -2695,13 +2681,13 @@
             case MEDIA_BUFFERING_UPDATE:
             {
                 final int percent = msg.arg1;
-                synchronized (mEventCbLock) {
-                    for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
-                        cb.first.execute(() -> cb.second.onInfo(
-                                mMediaPlayer, dsd, MEDIA_INFO_BUFFERING_UPDATE,
-                                percent));
+                sendEvent(new EventNotifier() {
+                    @Override
+                    public void notify(EventCallback callback) {
+                        callback.onInfo(
+                                mMediaPlayer, dsd, MEDIA_INFO_BUFFERING_UPDATE, percent);
                     }
-                }
+                });
 
                 synchronized (mSrcLock) {
                     if (isCurrentSrcId) {
@@ -2740,26 +2726,33 @@
             {
                 final int width = msg.arg1;
                 final int height = msg.arg2;
-                synchronized (mEventCbLock) {
-                    for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
-                        cb.first.execute(() -> cb.second.onVideoSizeChanged(
-                                mMediaPlayer, dsd, width, height));
+                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 + ")");
-                synchronized (mEventCbLock) {
-                    for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
-                        cb.first.execute(() -> cb.second.onError(
-                                mMediaPlayer, dsd, what, extra));
-                        cb.first.execute(() -> cb.second.onInfo(
-                                mMediaPlayer, dsd, MEDIA_INFO_DATA_SOURCE_END, 0));
+                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;
             }
@@ -2799,12 +2792,13 @@
                         break;
                 }
 
-                synchronized (mEventCbLock) {
-                    for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
-                        cb.first.execute(() -> cb.second.onInfo(
-                                mMediaPlayer, dsd, what, extra));
+                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) {
@@ -2841,12 +2835,13 @@
                     text = null;
                 }
 
-                synchronized (mEventCbLock) {
-                    for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
-                        cb.first.execute(() -> cb.second.onTimedText(
-                                mMediaPlayer, dsd, text));
+                sendEvent(new EventNotifier() {
+                    @Override
+                    public void notify(EventCallback callback) {
+                        callback.onTimedText(
+                                mMediaPlayer, dsd, text);
                     }
-                }
+                });
                 return;
             }
 
@@ -2866,12 +2861,13 @@
                             in.next().getInt64Value(),  // startTimeUs
                             in.next().getInt64Value(),  // durationUs
                             in.next().getBytesValue().toByteArray());  // data
-                    synchronized (mEventCbLock) {
-                        for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
-                            cb.first.execute(() -> cb.second.onSubtitleData(
-                                    mMediaPlayer, dsd, data));
+                    sendEvent(new EventNotifier() {
+                        @Override
+                        public void notify(EventCallback callback) {
+                            callback.onSubtitleData(
+                                    mMediaPlayer, dsd, data);
                         }
-                    }
+                    });
                 }
                 return;
             }
@@ -2895,12 +2891,13 @@
                     data = null;
                 }
 
-                synchronized (mEventCbLock) {
-                    for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
-                        cb.first.execute(() -> cb.second.onTimedMetaDataAvailable(
-                                mMediaPlayer, dsd, data));
+                sendEvent(new EventNotifier() {
+                    @Override
+                    public void notify(EventCallback callback) {
+                        callback.onTimedMetaDataAvailable(
+                                mMediaPlayer, dsd, data);
                     }
-                }
+                });
                 return;
             }
 
@@ -3033,6 +3030,40 @@
         }
     }
 
+    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
 
     /**
@@ -3283,12 +3314,13 @@
 
         // if finished successfully without provisioning, call the callback outside the lock
         if (allDoneWithoutProvisioning) {
-            synchronized (mDrmEventCbLock) {
-                for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) {
-                    cb.first.execute(() -> cb.second.onDrmPrepared(
-                            this, mCurrentDSD, PREPARE_DRM_STATUS_SUCCESS));
+            sendDrmEvent(new DrmEventNotifier() {
+                @Override
+                public void notify(DrmEventCallback callback) {
+                    callback.onDrmPrepared(
+                            MediaPlayer2Impl.this, mCurrentDSD, PREPARE_DRM_STATUS_SUCCESS);
                 }
-            }
+            });
         }
 
     }
@@ -3649,7 +3681,7 @@
                       supportedSchemes[i]);
             }
 
-            Log.v(TAG, "DrmInfoImpl() Parcel psshsize: " + pssh.length +
+            Log.v(TAG, "DrmInfoImpl() psshsize: " + pssh.length +
                   " supportedDRMsCount: " + supportedDRMsCount);
         }
 
@@ -3914,7 +3946,7 @@
                     connection.setReadTimeout(TIMEOUT_MS);
 
                     connection.connect();
-                    response = Streams.readFully(connection.getInputStream());
+                    response = readInputStreamFully(connection.getInputStream());
 
                     Log.v(TAG, "HandleProvisioninig: Thread run: response " +
                             response.length + " " + response);
@@ -3968,12 +4000,13 @@
                 } // synchronized
 
                 // calling the callback outside the lock
-                synchronized (mDrmEventCbLock) {
-                    for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) {
-                        cb.first.execute(() -> cb.second.onDrmPrepared(
-                                mediaPlayer, mCurrentDSD, status));
+                sendDrmEvent(new DrmEventNotifier() {
+                    @Override
+                    public void notify(DrmEventCallback callback) {
+                        callback.onDrmPrepared(
+                                mediaPlayer, mCurrentDSD, status);
                     }
-                }
+                });
             } else {   // blocking mode already has the lock
 
                 // continuing with prepareDrm
@@ -3993,6 +4026,29 @@
             finished = true;
         }   // run()
 
+        /**
+         * 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) {
@@ -4632,12 +4688,13 @@
             if (mMediaCallType == CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED) {
                 return;
             }
-            synchronized (mEventCbLock) {
-                for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
-                    cb.first.execute(() -> cb.second.onCallCompleted(
-                            MediaPlayer2Impl.this, mDSD, mMediaCallType, status));
+            sendEvent(new EventNotifier() {
+                @Override
+                public void notify(EventCallback callback) {
+                    callback.onCallCompleted(
+                            MediaPlayer2Impl.this, mDSD, mMediaCallType, status);
                 }
-            }
+            });
         }
     };
 
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 0ff2d8f..c537945 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -160,8 +160,9 @@
 
     public static final String SCANNED_BUILD_PREFS_NAME = "MediaScanBuild";
     public static final String LAST_INTERNAL_SCAN_FINGERPRINT = "lastScanFingerprint";
-    private static final String SYSTEM_SOUNDS_DIR = "/system/media/audio";
-    private static final String PRODUCT_SOUNDS_DIR = "/product/media/audio";
+    private static final String SYSTEM_SOUNDS_DIR = Environment.getRootDirectory() + "/media/audio";
+    private static final String OEM_SOUNDS_DIR = Environment.getOemDirectory() + "/media/audio";
+    private static final String PRODUCT_SOUNDS_DIR = Environment.getProductDirectory() + "/media/audio";
     private static String sLastInternalScanFingerprint;
 
     private static final String[] ID3_GENRES = {
@@ -1193,6 +1194,9 @@
         if (path.startsWith(SYSTEM_SOUNDS_DIR + ALARMS_DIR)
                 || path.startsWith(SYSTEM_SOUNDS_DIR + RINGTONES_DIR)
                 || path.startsWith(SYSTEM_SOUNDS_DIR + NOTIFICATIONS_DIR)
+                || path.startsWith(OEM_SOUNDS_DIR + ALARMS_DIR)
+                || path.startsWith(OEM_SOUNDS_DIR + RINGTONES_DIR)
+                || path.startsWith(OEM_SOUNDS_DIR + NOTIFICATIONS_DIR)
                 || path.startsWith(PRODUCT_SOUNDS_DIR + ALARMS_DIR)
                 || path.startsWith(PRODUCT_SOUNDS_DIR + RINGTONES_DIR)
                 || path.startsWith(PRODUCT_SOUNDS_DIR + NOTIFICATIONS_DIR)) {
diff --git a/media/jni/android_media_MediaPlayer2.cpp b/media/jni/android_media_MediaPlayer2.cpp
index 1a844cc..693a3d0 100644
--- a/media/jni/android_media_MediaPlayer2.cpp
+++ b/media/jni/android_media_MediaPlayer2.cpp
@@ -1490,8 +1490,8 @@
     {"_release",            "()V",                              (void *)android_media_MediaPlayer2_release},
     {"_reset",              "()V",                              (void *)android_media_MediaPlayer2_reset},
     {"_getAudioStreamType", "()I",                              (void *)android_media_MediaPlayer2_getAudioStreamType},
-    {"setParameter",        "(ILandroid/os/Parcel;)Z",          (void *)android_media_MediaPlayer2_setParameter},
-    {"getParameter",        "(I)Landroid/os/Parcel;",           (void *)android_media_MediaPlayer2_getParameter},
+    {"setParameter",        "(ILjava/lang/Object;)Z",          (void *)android_media_MediaPlayer2_setParameter},
+    {"getParameter",        "(I)Ljava/lang/Object;",           (void *)android_media_MediaPlayer2_getParameter},
     {"setLooping",          "(Z)V",                             (void *)android_media_MediaPlayer2_setLooping},
     {"isLooping",           "()Z",                              (void *)android_media_MediaPlayer2_isLooping},
     {"_setVolume",          "(FF)V",                            (void *)android_media_MediaPlayer2_setVolume},
diff --git a/media/lib/remotedisplay/Android.bp b/media/lib/remotedisplay/Android.bp
index 1e9320d..5f4b930 100644
--- a/media/lib/remotedisplay/Android.bp
+++ b/media/lib/remotedisplay/Android.bp
@@ -14,22 +14,8 @@
 // limitations under the License.
 //
 
-droiddoc {
-    name: "com.android.media.remotedisplay.stubs-gen-docs",
-    srcs: [
-        "java/**/*.java",
-    ],
-    args: " -hide 111 -hide 113 -hide 125 -hide 126 -hide 127 -hide 128 " +
-          " -stubpackages com.android.media.remotedisplay " +
-          " -nodocs ",
-    custom_template: "droiddoc-templates-sdk",
-    installable: false,
-}
-
-java_library_static {
-    name: "com.android.media.remotedisplay.stubs",
-    srcs: [
-        ":com.android.media.remotedisplay.stubs-gen-docs",
-    ],
-    sdk_version: "current",
+java_sdk_library {
+    name: "com.android.media.remotedisplay",
+    srcs: ["java/**/*.java"],
+    api_packages: ["com.android.media.remotedisplay"],
 }
diff --git a/media/lib/remotedisplay/Android.mk b/media/lib/remotedisplay/Android.mk
deleted file mode 100644
index e88c0f1..0000000
--- a/media/lib/remotedisplay/Android.mk
+++ /dev/null
@@ -1,44 +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)
-
-# the remotedisplay library
-# ============================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE:= com.android.media.remotedisplay
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-java-files-under, java)
-
-include $(BUILD_JAVA_LIBRARY)
-
-
-# ====  com.android.media.remotedisplay.xml lib def  ========================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := com.android.media.remotedisplay.xml
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE_CLASS := ETC
-
-# This will install the file in /system/etc/permissions
-#
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions
-
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
-
-include $(BUILD_PREBUILT)
diff --git a/media/lib/remotedisplay/OWNERS b/media/lib/remotedisplay/OWNERS
new file mode 100644
index 0000000..7e7335d
--- /dev/null
+++ b/media/lib/remotedisplay/OWNERS
@@ -0,0 +1 @@
+michaelwr@google.com
diff --git a/media/lib/remotedisplay/api/current.txt b/media/lib/remotedisplay/api/current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/lib/remotedisplay/api/current.txt
diff --git a/media/lib/remotedisplay/api/removed.txt b/media/lib/remotedisplay/api/removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/lib/remotedisplay/api/removed.txt
diff --git a/media/lib/remotedisplay/api/system-current.txt b/media/lib/remotedisplay/api/system-current.txt
new file mode 100644
index 0000000..69bbd35
--- /dev/null
+++ b/media/lib/remotedisplay/api/system-current.txt
@@ -0,0 +1,52 @@
+package com.android.media.remotedisplay {
+
+  public class RemoteDisplay {
+    ctor public RemoteDisplay(java.lang.String, java.lang.String);
+    method public java.lang.String getDescription();
+    method public java.lang.String getId();
+    method public java.lang.String getName();
+    method public int getPresentationDisplayId();
+    method public int getStatus();
+    method public int getVolume();
+    method public int getVolumeHandling();
+    method public int getVolumeMax();
+    method public void setDescription(java.lang.String);
+    method public void setName(java.lang.String);
+    method public void setPresentationDisplayId(int);
+    method public void setStatus(int);
+    method public void setVolume(int);
+    method public void setVolumeHandling(int);
+    method public void setVolumeMax(int);
+    field public static final int PLAYBACK_VOLUME_FIXED = 0; // 0x0
+    field public static final int PLAYBACK_VOLUME_VARIABLE = 1; // 0x1
+    field public static final int STATUS_AVAILABLE = 2; // 0x2
+    field public static final int STATUS_CONNECTED = 4; // 0x4
+    field public static final int STATUS_CONNECTING = 3; // 0x3
+    field public static final int STATUS_IN_USE = 1; // 0x1
+    field public static final int STATUS_NOT_AVAILABLE = 0; // 0x0
+  }
+
+  public abstract class RemoteDisplayProvider {
+    ctor public RemoteDisplayProvider(android.content.Context);
+    method public void addDisplay(com.android.media.remotedisplay.RemoteDisplay);
+    method public com.android.media.remotedisplay.RemoteDisplay findRemoteDisplay(java.lang.String);
+    method public android.os.IBinder getBinder();
+    method public final android.content.Context getContext();
+    method public int getDiscoveryMode();
+    method public java.util.Collection<com.android.media.remotedisplay.RemoteDisplay> getDisplays();
+    method public android.app.PendingIntent getSettingsPendingIntent();
+    method public void onAdjustVolume(com.android.media.remotedisplay.RemoteDisplay, int);
+    method public void onConnect(com.android.media.remotedisplay.RemoteDisplay);
+    method public void onDisconnect(com.android.media.remotedisplay.RemoteDisplay);
+    method public void onDiscoveryModeChanged(int);
+    method public void onSetVolume(com.android.media.remotedisplay.RemoteDisplay, int);
+    method public void removeDisplay(com.android.media.remotedisplay.RemoteDisplay);
+    method public void updateDisplay(com.android.media.remotedisplay.RemoteDisplay);
+    field public static final int DISCOVERY_MODE_ACTIVE = 2; // 0x2
+    field public static final int DISCOVERY_MODE_NONE = 0; // 0x0
+    field public static final int DISCOVERY_MODE_PASSIVE = 1; // 0x1
+    field public static final java.lang.String SERVICE_INTERFACE = "com.android.media.remotedisplay.RemoteDisplayProvider";
+  }
+
+}
+
diff --git a/media/lib/remotedisplay/api/system-removed.txt b/media/lib/remotedisplay/api/system-removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/lib/remotedisplay/api/system-removed.txt
diff --git a/media/lib/remotedisplay/api/test-current.txt b/media/lib/remotedisplay/api/test-current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/lib/remotedisplay/api/test-current.txt
diff --git a/media/lib/remotedisplay/api/test-removed.txt b/media/lib/remotedisplay/api/test-removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/lib/remotedisplay/api/test-removed.txt
diff --git a/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplay.java b/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplay.java
index dc9dd79..8de414b 100644
--- a/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplay.java
+++ b/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplay.java
@@ -16,6 +16,7 @@
 
 package com.android.media.remotedisplay;
 
+import android.annotation.SystemApi;
 import android.media.RemoteDisplayState.RemoteDisplayInfo;
 import android.text.TextUtils;
 
@@ -23,7 +24,10 @@
 
 /**
  * Represents a remote display that has been discovered.
+ *
+ * @hide
  */
+@SystemApi
 public class RemoteDisplay {
     private final RemoteDisplayInfo mMutableInfo;
     private RemoteDisplayInfo mImmutableInfo;
diff --git a/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplayProvider.java b/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplayProvider.java
index 4d3edb8..7017e44 100644
--- a/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplayProvider.java
+++ b/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplayProvider.java
@@ -16,6 +16,7 @@
 
 package com.android.media.remotedisplay;
 
+import android.annotation.SystemApi;
 import android.app.PendingIntent;
 import android.app.Service;
 import android.content.Context;
@@ -88,7 +89,10 @@
  * IMPORTANT: This class is effectively a public API for unbundled applications, and
  * must remain API stable. See README.txt in the root of this package for more information.
  * </p>
+ *
+ * @hide
  */
+@SystemApi
 public abstract class RemoteDisplayProvider {
     private static final int MSG_SET_CALLBACK = 1;
     private static final int MSG_SET_DISCOVERY_MODE = 2;
diff --git a/media/lib/signer/Android.bp b/media/lib/signer/Android.bp
index 3b25787..8c43683 100644
--- a/media/lib/signer/Android.bp
+++ b/media/lib/signer/Android.bp
@@ -18,4 +18,5 @@
     name: "com.android.mediadrm.signer",
     srcs: ["java/**/*.java"],
     api_packages: ["com.android.mediadrm.signer"],
+    metalava_enabled: false,
 }
diff --git a/packages/CarSystemUI/Android.bp b/packages/CarSystemUI/Android.bp
index 86f9032..1b1bf8d 100644
--- a/packages/CarSystemUI/Android.bp
+++ b/packages/CarSystemUI/Android.bp
@@ -30,6 +30,7 @@
         "SystemUIPluginLib",
         "SystemUISharedLib",
         "SettingsLib",
+        "android.car.user",
         "androidx.car_car",
         "androidx.legacy_legacy-support-v4",
         "androidx.recyclerview_recyclerview",
@@ -51,7 +52,6 @@
     libs: [
         "telephony-common",
         "android.car",
-        "android.car.user",
     ],
 
     manifest: "AndroidManifest.xml",
diff --git a/packages/LocalTransport/Android.mk b/packages/LocalTransport/Android.mk
new file mode 100644
index 0000000..3484b0f
--- /dev/null
+++ b/packages/LocalTransport/Android.mk
@@ -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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PROGUARD_FLAG_FILES := proguard.flags
+
+LOCAL_PACKAGE_NAME := LocalTransport
+LOCAL_PRIVATE_PLATFORM_APIS := true
+LOCAL_CERTIFICATE := platform
+LOCAL_PRIVILEGED_MODULE := true
+
+include $(BUILD_PACKAGE)
+
+########################
+include $(call all-makefiles-under,$(LOCAL_PATH))
+
diff --git a/packages/LocalTransport/AndroidManifest.xml b/packages/LocalTransport/AndroidManifest.xml
new file mode 100644
index 0000000..196be1e
--- /dev/null
+++ b/packages/LocalTransport/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (c) 2018 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="com.android.localtransport"
+      android:sharedUserId="android.uid.system" >
+
+
+    <application android:allowBackup="false" >
+        <!-- This service does not need to be exported because it shares uid with the system server
+        which is the only client. -->
+        <service android:name=".LocalTransportService"
+                 android:permission="android.permission.CONFIRM_FULL_BACKUP"
+                 android:exported="false">
+            <intent-filter>
+                <action android:name="android.backup.TRANSPORT_HOST" />
+            </intent-filter>
+        </service>
+
+    </application>
+</manifest>
diff --git a/packages/LocalTransport/proguard.flags b/packages/LocalTransport/proguard.flags
new file mode 100644
index 0000000..c1f51b8
--- /dev/null
+++ b/packages/LocalTransport/proguard.flags
@@ -0,0 +1,5 @@
+-keep class com.android.localTransport.LocalTransport
+-keep class com.android.localTransport.LocalTransportParameters
+-keep class com.android.localTransport.LocalTransportService
+
+
diff --git a/core/java/com/android/internal/backup/LocalTransport.java b/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
similarity index 97%
rename from core/java/com/android/internal/backup/LocalTransport.java
rename to packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
index d0f0272..0bf8bc1 100644
--- a/core/java/com/android/internal/backup/LocalTransport.java
+++ b/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.backup;
+package com.android.localtransport;
 
 import android.app.backup.BackupAgent;
 import android.app.backup.BackupDataInput;
@@ -26,7 +26,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageInfo;
-import android.os.Environment;
 import android.os.ParcelFileDescriptor;
 import android.system.ErrnoException;
 import android.system.Os;
@@ -56,7 +55,7 @@
     private static final boolean DEBUG = false;
 
     private static final String TRANSPORT_DIR_NAME
-            = "com.android.internal.backup.LocalTransport";
+            = "com.android.localtransport.LocalTransport";
 
     private static final String TRANSPORT_DESTINATION_STRING
             = "Backing up to debug-only private cache";
@@ -75,10 +74,10 @@
     private static final long KEY_VALUE_BACKUP_SIZE_QUOTA = 5 * 1024 * 1024;
 
     private Context mContext;
-    private File mDataDir = new File(Environment.getDownloadCacheDirectory(), "backup");
-    private File mCurrentSetDir = new File(mDataDir, Long.toString(CURRENT_SET_TOKEN));
-    private File mCurrentSetIncrementalDir = new File(mCurrentSetDir, INCREMENTAL_DIR);
-    private File mCurrentSetFullDir = new File(mCurrentSetDir, FULL_DATA_DIR);
+    private File mDataDir;
+    private File mCurrentSetDir;
+    private File mCurrentSetIncrementalDir;
+    private File mCurrentSetFullDir;
 
     private PackageInfo[] mRestorePackages = null;
     private int mRestorePackage = -1;  // Index into mRestorePackages
@@ -101,6 +100,11 @@
     private final LocalTransportParameters mParameters;
 
     private void makeDataDirs() {
+        mDataDir = mContext.getFilesDir();
+        mCurrentSetDir = new File(mDataDir, Long.toString(CURRENT_SET_TOKEN));
+        mCurrentSetIncrementalDir = new File(mCurrentSetDir, INCREMENTAL_DIR);
+        mCurrentSetFullDir = new File(mCurrentSetDir, FULL_DATA_DIR);
+
         mCurrentSetDir.mkdirs();
         mCurrentSetFullDir.mkdir();
         mCurrentSetIncrementalDir.mkdir();
diff --git a/core/java/com/android/internal/backup/LocalTransportParameters.java b/packages/LocalTransport/src/com/android/localtransport/LocalTransportParameters.java
similarity index 97%
rename from core/java/com/android/internal/backup/LocalTransportParameters.java
rename to packages/LocalTransport/src/com/android/localtransport/LocalTransportParameters.java
index 2427d39..784be22 100644
--- a/core/java/com/android/internal/backup/LocalTransportParameters.java
+++ b/packages/LocalTransport/src/com/android/localtransport/LocalTransportParameters.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.internal.backup;
+package com.android.localtransport;
 
 import android.util.KeyValueSettingObserver;
 import android.content.ContentResolver;
diff --git a/core/java/com/android/internal/backup/LocalTransportService.java b/packages/LocalTransport/src/com/android/localtransport/LocalTransportService.java
similarity index 96%
rename from core/java/com/android/internal/backup/LocalTransportService.java
rename to packages/LocalTransport/src/com/android/localtransport/LocalTransportService.java
index 69c48e2..ac4f418 100644
--- a/core/java/com/android/internal/backup/LocalTransportService.java
+++ b/packages/LocalTransport/src/com/android/localtransport/LocalTransportService.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.backup;
+package com.android.localtransport;
 
 import android.app.Service;
 import android.content.Intent;
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
index 580308a..8c29a25 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
@@ -430,9 +430,14 @@
             // Check for unknown sources restriction
             final int unknownSourcesRestrictionSource = mUserManager.getUserRestrictionSource(
                     UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, Process.myUserHandle());
-            if ((unknownSourcesRestrictionSource & UserManager.RESTRICTION_SOURCE_SYSTEM) != 0) {
+            final int unknownSourcesGlobalRestrictionSource = mUserManager.getUserRestrictionSource(
+                    UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY, Process.myUserHandle());
+            final int systemRestriction = UserManager.RESTRICTION_SOURCE_SYSTEM
+                    & (unknownSourcesRestrictionSource | unknownSourcesGlobalRestrictionSource);
+            if (systemRestriction != 0) {
                 showDialogInner(DLG_UNKNOWN_SOURCES_RESTRICTED_FOR_USER);
-            } else if (unknownSourcesRestrictionSource != UserManager.RESTRICTION_NOT_SET) {
+            } else if (unknownSourcesRestrictionSource != UserManager.RESTRICTION_NOT_SET
+                    || unknownSourcesGlobalRestrictionSource != UserManager.RESTRICTION_NOT_SET) {
                 startActivity(new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS));
                 finish();
             } else {
diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp
index 943dd84..89438e5 100644
--- a/packages/SettingsLib/Android.bp
+++ b/packages/SettingsLib/Android.bp
@@ -14,6 +14,8 @@
     static_libs: [
         "SettingsLibHelpUtils",
         "SettingsLibRestrictedLockUtils",
+        "SettingsLibAppPreference",
+        "SettingsLibSearchWidget",
     ],
 
     // ANDROIDMK TRANSLATION ERROR: unsupported assignment to LOCAL_SHARED_JAVA_LIBRARIES
diff --git a/packages/SettingsLib/AppPreference/Android.bp b/packages/SettingsLib/AppPreference/Android.bp
new file mode 100644
index 0000000..b56181d
--- /dev/null
+++ b/packages/SettingsLib/AppPreference/Android.bp
@@ -0,0 +1,13 @@
+android_library {
+    name: "SettingsLibAppPreference",
+
+    srcs: ["src/**/*.java"],
+    resource_dirs: ["res"],
+
+    libs: [
+        "androidx.annotation_annotation",
+        "androidx.preference_preference",
+    ],
+    sdk_version: "system_current",
+    min_sdk_version: "21",
+}
diff --git a/packages/SettingsLib/AppPreference/AndroidManifest.xml b/packages/SettingsLib/AppPreference/AndroidManifest.xml
new file mode 100644
index 0000000..7e71308
--- /dev/null
+++ b/packages/SettingsLib/AppPreference/AndroidManifest.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.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.settingslib.widget.apppreference">
+
+    <uses-sdk android:minSdkVersion="21" />
+
+</manifest>
diff --git a/packages/SettingsLib/AppPreference/res/layout/preference_app.xml b/packages/SettingsLib/AppPreference/res/layout/preference_app.xml
new file mode 100644
index 0000000..6d35550
--- /dev/null
+++ b/packages/SettingsLib/AppPreference/res/layout/preference_app.xml
@@ -0,0 +1,100 @@
+<?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:background="?android:attr/selectableItemBackground"
+    android:gravity="center_vertical"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+
+    <LinearLayout
+        android:id="@+id/icon_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:gravity="start|center_vertical"
+        android:minWidth="56dp"
+        android:orientation="horizontal"
+        android:paddingEnd="8dp"
+        android:paddingTop="4dp"
+        android:paddingBottom="4dp">
+        <ImageView
+            android:id="@android:id/icon"
+            android:layout_width="@dimen/secondary_app_icon_size"
+            android:layout_height="@dimen/secondary_app_icon_size"/>
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:orientation="vertical"
+        android:paddingTop="16dp"
+        android:paddingBottom="16dp">
+
+        <TextView android:id="@android:id/title"
+                  android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:singleLine="true"
+                  android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+                  android:ellipsize="marquee"
+                  android:fadingEdge="horizontal"/>
+
+        <LinearLayout
+            android:id="@+id/summary_container"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:visibility="gone">
+            <TextView android:id="@android:id/summary"
+                      android:layout_width="0dp"
+                      android:layout_height="wrap_content"
+                      android:layout_weight="1"
+                      android:textAppearance="@android:style/TextAppearance.Material.Small"
+                      android:textAlignment="viewStart"
+                      android:textColor="?android:attr/textColorSecondary"/>
+
+            <TextView android:id="@+id/appendix"
+                      android:layout_width="0dp"
+                      android:layout_height="wrap_content"
+                      android:layout_weight="1"
+                      android:textAppearance="@android:style/TextAppearance.Material.Small"
+                      android:textAlignment="viewEnd"
+                      android:textColor="?android:attr/textColorSecondary"
+                      android:maxLines="1"
+                      android:ellipsize="end"/>
+        </LinearLayout>
+        <ProgressBar
+            android:id="@android:id/progress"
+            style="?android:attr/progressBarStyleHorizontal"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="4dp"
+            android:max="100"
+            android:visibility="gone"/>
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@android:id/widget_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:gravity="center"
+        android:minWidth="64dp"
+        android:orientation="vertical"/>
+
+</LinearLayout>
diff --git a/packages/SettingsLib/AppPreference/res/values/dimens.xml b/packages/SettingsLib/AppPreference/res/values/dimens.xml
new file mode 100644
index 0000000..e2a7a19
--- /dev/null
+++ b/packages/SettingsLib/AppPreference/res/values/dimens.xml
@@ -0,0 +1,20 @@
+<?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>
+    <dimen name="secondary_app_icon_size">32dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/AppPreference/src/com/android/settingslib/widget/apppreference/AppPreference.java b/packages/SettingsLib/AppPreference/src/com/android/settingslib/widget/apppreference/AppPreference.java
new file mode 100644
index 0000000..593b6f5
--- /dev/null
+++ b/packages/SettingsLib/AppPreference/src/com/android/settingslib/widget/apppreference/AppPreference.java
@@ -0,0 +1,63 @@
+/*
+ * 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.settingslib.widget.apppreference;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ProgressBar;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+
+public class AppPreference extends Preference {
+
+    private int mProgress;
+    private boolean mProgressVisible;
+
+    public AppPreference(Context context) {
+        super(context);
+        setLayoutResource(R.layout.preference_app);
+    }
+
+    public AppPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        setLayoutResource(R.layout.preference_app);
+    }
+
+    public void setProgress(int amount) {
+        mProgress = amount;
+        mProgressVisible = true;
+        notifyChanged();
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder view) {
+        super.onBindViewHolder(view);
+
+        view.findViewById(R.id.summary_container)
+                .setVisibility(TextUtils.isEmpty(getSummary()) ? View.GONE : View.VISIBLE);
+        final ProgressBar progress = (ProgressBar) view.findViewById(android.R.id.progress);
+        if (mProgressVisible) {
+            progress.setProgress(mProgress);
+            progress.setVisibility(View.VISIBLE);
+        } else {
+            progress.setVisibility(View.GONE);
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/HelpUtils/res/values-nl/strings.xml b/packages/SettingsLib/HelpUtils/res/values-nl/strings.xml
index a034d29..2f576e6 100644
--- a/packages/SettingsLib/HelpUtils/res/values-nl/strings.xml
+++ b/packages/SettingsLib/HelpUtils/res/values-nl/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="help_feedback_label" msgid="4550436169116444686">"Help en feedback"</string>
+    <string name="help_feedback_label" msgid="4550436169116444686">"Hulp en feedback"</string>
 </resources>
diff --git a/packages/SettingsLib/SearchWidget/Android.bp b/packages/SettingsLib/SearchWidget/Android.bp
new file mode 100644
index 0000000..7541ca45
--- /dev/null
+++ b/packages/SettingsLib/SearchWidget/Android.bp
@@ -0,0 +1,8 @@
+android_library {
+    name: "SettingsLibSearchWidget",
+
+    srcs: ["src/**/*.java"],
+    resource_dirs: ["res"],
+    sdk_version: "system_current",
+    min_sdk_version: "21",
+}
diff --git a/packages/SettingsLib/SearchWidget/AndroidManifest.xml b/packages/SettingsLib/SearchWidget/AndroidManifest.xml
new file mode 100644
index 0000000..b86544e
--- /dev/null
+++ b/packages/SettingsLib/SearchWidget/AndroidManifest.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.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.settingslib.search">
+
+    <uses-sdk android:minSdkVersion="21" />
+
+</manifest>
diff --git a/packages/SettingsLib/SearchWidget/res/drawable/ic_search_24dp.xml b/packages/SettingsLib/SearchWidget/res/drawable/ic_search_24dp.xml
new file mode 100644
index 0000000..7e65848
--- /dev/null
+++ b/packages/SettingsLib/SearchWidget/res/drawable/ic_search_24dp.xml
@@ -0,0 +1,27 @@
+<?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.
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24"
+        android:tint="?android:attr/colorControlNormal">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M20.49,19l-5.73,-5.73C15.53,12.2 16,10.91 16,9.5C16,5.91 13.09,3 9.5,3S3,5.91 3,9.5C3,13.09 5.91,16 9.5,16c1.41,0 2.7,-0.47 3.77,-1.24L19,20.49L20.49,19zM5,9.5C5,7.01 7.01,5 9.5,5S14,7.01 14,9.5S11.99,14 9.5,14S5,11.99 5,9.5z"/>
+</vector>
diff --git a/packages/SettingsLib/SearchWidget/res/values/strings.xml b/packages/SettingsLib/SearchWidget/res/values/strings.xml
new file mode 100644
index 0000000..0b12810
--- /dev/null
+++ b/packages/SettingsLib/SearchWidget/res/values/strings.xml
@@ -0,0 +1,20 @@
+<!--
+  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">
+    <!-- Text used as a search hint into the search box [CHAR_LIMIT=60]-->
+    <string name="search_menu">Search settings</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 3859092..bd9a6ec 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -446,7 +446,6 @@
     <string name="alarm_template_far" msgid="3779172822607461675">"अलार्म <xliff:g id="WHEN">%1$s</xliff:g> को बजेगा"</string>
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"अवधि"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"हर बार पूछें"</string>
-    <!-- no translation found for zen_mode_forever (2704305038191592967) -->
-    <skip />
+    <string name="zen_mode_forever" msgid="2704305038191592967">"जब तक आप इसे बंद नहीं करते"</string>
     <string name="time_unit_just_now" msgid="6363336622778342422">"अभी-अभी"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 332ced6..508adbd 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1116,4 +1116,6 @@
     <!-- time label for event have that happened very recently [CHAR LIMIT=60] -->
     <string name="time_unit_just_now">Just now</string>
 
-  </resources>
+    <!-- The notice header of Third-party licenses. not translatable -->
+    <string name="notice_header" translatable="false"></string>
+</resources>
diff --git a/packages/SettingsLib/search/Android.mk b/packages/SettingsLib/search/Android.mk
index cb19891..14f9626 100644
--- a/packages/SettingsLib/search/Android.mk
+++ b/packages/SettingsLib/search/Android.mk
@@ -5,6 +5,9 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
+LOCAL_RESOURCE_DIR := \
+    $(LOCAL_PATH)/main/res
+
 include $(BUILD_STATIC_JAVA_LIBRARY)
 
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
index a710410..58feef5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
@@ -102,7 +102,7 @@
                 BluetoothProfile.A2DP);
     }
 
-    public boolean isConnectable() {
+    public boolean accessProfileEnabled() {
         return true;
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java
index e13e566..988062d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java
@@ -96,7 +96,7 @@
                 BluetoothProfile.A2DP_SINK);
     }
 
-    public boolean isConnectable() {
+    public boolean accessProfileEnabled() {
         return true;
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index b9f7323..750a843 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -29,16 +29,15 @@
 import android.text.TextUtils;
 import android.util.Log;
 
-import androidx.annotation.VisibleForTesting;
-
 import com.android.settingslib.R;
 
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
 
+import androidx.annotation.VisibleForTesting;
+
 /**
  * CachedBluetoothDevice represents a remote Bluetooth device. It contains
  * attributes of the device (such as the address, name, RSSI, etc.) and
@@ -48,6 +47,10 @@
 public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> {
     private static final String TAG = "CachedBluetoothDevice";
 
+    // See mConnectAttempted
+    private static final long MAX_UUID_DELAY_FOR_AUTO_CONNECT = 5000;
+    private static final long MAX_HOGP_DELAY_FOR_AUTO_CONNECT = 30000;
+
     private final Context mContext;
     private final BluetoothAdapter mLocalAdapter;
     private final LocalBluetoothProfileManager mProfileManager;
@@ -55,7 +58,6 @@
     private long mHiSyncId;
     // Need this since there is no method for getting RSSI
     private short mRssi;
-    private HashMap<LocalBluetoothProfile, Integer> mProfileConnectionState;
 
     private final List<LocalBluetoothProfile> mProfiles =
             new ArrayList<LocalBluetoothProfile>();
@@ -78,17 +80,6 @@
 
     private final static String MESSAGE_REJECTION_COUNT_PREFS_NAME = "bluetooth_message_reject";
 
-    public long getHiSyncId() {
-        return mHiSyncId;
-    }
-
-    public void setHiSyncId(long id) {
-        if (BluetoothUtils.D) {
-            Log.d(TAG, "setHiSyncId: mDevice " + mDevice + ", id " + id);
-        }
-        mHiSyncId = id;
-    }
-
     /**
      * Last time a bt profile auto-connect was attempted.
      * If an ACTION_UUID intent comes in within
@@ -97,14 +88,21 @@
      */
     private long mConnectAttempted;
 
-    // See mConnectAttempted
-    private static final long MAX_UUID_DELAY_FOR_AUTO_CONNECT = 5000;
-    private static final long MAX_HOGP_DELAY_FOR_AUTO_CONNECT = 30000;
-
     // Active device state
     private boolean mIsActiveDeviceA2dp = false;
     private boolean mIsActiveDeviceHeadset = false;
     private boolean mIsActiveDeviceHearingAid = false;
+
+    CachedBluetoothDevice(Context context, LocalBluetoothProfileManager profileManager,
+            BluetoothDevice device) {
+        mContext = context;
+        mLocalAdapter = BluetoothAdapter.getDefaultAdapter();
+        mProfileManager = profileManager;
+        mDevice = device;
+        fillData();
+        mHiSyncId = BluetoothHearingAid.HI_SYNC_ID_INVALID;
+    }
+
     /**
      * Describes the current device and profile for logging.
      *
@@ -133,7 +131,6 @@
             }
             return;
         }
-        mProfileConnectionState.put(profile, newProfileState);
         if (newProfileState == BluetoothProfile.STATE_CONNECTED) {
             if (profile instanceof MapProfile) {
                 profile.setPreferred(mDevice, true);
@@ -161,18 +158,6 @@
         fetchActiveDevices();
     }
 
-    CachedBluetoothDevice(Context context,
-                          LocalBluetoothProfileManager profileManager,
-                          BluetoothDevice device) {
-        mContext = context;
-        mLocalAdapter = BluetoothAdapter.getDefaultAdapter();
-        mProfileManager = profileManager;
-        mDevice = device;
-        mProfileConnectionState = new HashMap<LocalBluetoothProfile, Integer>();
-        fillData();
-        mHiSyncId = BluetoothHearingAid.HI_SYNC_ID_INVALID;
-    }
-
     public void disconnect() {
         for (LocalBluetoothProfile profile : mProfiles) {
             disconnect(profile);
@@ -204,6 +189,17 @@
         connectWithoutResettingTimer(connectAllProfiles);
     }
 
+    public long getHiSyncId() {
+        return mHiSyncId;
+    }
+
+    public void setHiSyncId(long id) {
+        if (BluetoothUtils.D) {
+            Log.d(TAG, "setHiSyncId: mDevice " + mDevice + ", id " + id);
+        }
+        mHiSyncId = id;
+    }
+
     void onBondingDockConnect() {
         // Attempt to connect if UUIDs are available. Otherwise,
         // we will connect when the ACTION_UUID intent arrives.
@@ -226,7 +222,7 @@
 
         int preferredProfiles = 0;
         for (LocalBluetoothProfile profile : mProfiles) {
-            if (connectAllProfiles ? profile.isConnectable() : profile.isAutoConnectable()) {
+            if (connectAllProfiles ? profile.accessProfileEnabled() : profile.isAutoConnectable()) {
                 if (profile.isPreferred(mDevice)) {
                     ++preferredProfiles;
                     connectInt(profile);
@@ -300,14 +296,6 @@
         return true;
     }
 
-    /**
-     * Return true if user initiated pairing on this device. The message text is
-     * slightly different for local vs. remote initiated pairing dialogs.
-     */
-    boolean isUserInitiatedPairing() {
-        return mDevice.isBondingInitiatedLocally();
-    }
-
     public void unpair() {
         int state = getBondState();
 
@@ -332,22 +320,9 @@
     }
 
     public int getProfileConnectionState(LocalBluetoothProfile profile) {
-        if (mProfileConnectionState.get(profile) == null) {
-            // If cache is empty make the binder call to get the state
-            int state = profile.getConnectionStatus(mDevice);
-            mProfileConnectionState.put(profile, state);
-        }
-        return mProfileConnectionState.get(profile);
-    }
-
-    public void clearProfileConnectionState ()
-    {
-        if (BluetoothUtils.D) {
-            Log.d(TAG," Clearing all connection state for dev:" + mDevice.getName());
-        }
-        for (LocalBluetoothProfile profile :getProfiles()) {
-            mProfileConnectionState.put(profile, BluetoothProfile.STATE_DISCONNECTED);
-        }
+        return profile != null
+                ? profile.getConnectionStatus(mDevice)
+                : BluetoothProfile.STATE_DISCONNECTED;
     }
 
     // TODO: do any of these need to run async on a background thread?
@@ -669,7 +644,7 @@
         List<LocalBluetoothProfile> connectableProfiles =
                 new ArrayList<LocalBluetoothProfile>();
         for (LocalBluetoothProfile profile : mProfiles) {
-            if (profile.isConnectable()) {
+            if (profile.accessProfileEnabled()) {
                 connectableProfiles.add(profile);
             }
         }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
index 5a64e02..21cf0c2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
@@ -285,11 +285,6 @@
                     {
                         mCachedDevicesMapForHearingAids.remove(cachedDevice.getHiSyncId());
                     }
-                } else {
-                    // For bonded devices, we need to clear the connection status so that
-                    // when BT is enabled next time, device connection status shall be retrieved
-                    // by making a binder call.
-                    cachedDevice.clearProfileConnectionState();
                 }
             }
             for (int i = mHearingAidDevicesNotAddedInCache.size() - 1; i >= 0; i--) {
@@ -297,11 +292,6 @@
                 if (notCachedDevice.getBondState() != BluetoothDevice.BOND_BONDED) {
                     notCachedDevice.setJustDiscovered(false);
                     mHearingAidDevicesNotAddedInCache.remove(i);
-                } else {
-                    // For bonded devices, we need to clear the connection status so that
-                    // when BT is enabled next time, device connection status shall be retrieved
-                    // by making a binder call.
-                    notCachedDevice.clearProfileConnectionState();
                 }
             }
         }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
index 2dd8eaf..62507f5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
@@ -103,7 +103,7 @@
                 BluetoothProfile.HEADSET);
     }
 
-    public boolean isConnectable() {
+    public boolean accessProfileEnabled() {
         return true;
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
index 1eeb4f0..8bc0acf 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
@@ -100,7 +100,7 @@
                 new HearingAidServiceListener(), BluetoothProfile.HEARING_AID);
     }
 
-    public boolean isConnectable() {
+    public boolean accessProfileEnabled() {
         return false;
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
index 4b6a22c..4879144 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
@@ -104,7 +104,7 @@
     }
 
     @Override
-    public boolean isConnectable() {
+    public boolean accessProfileEnabled() {
         return true;
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidDeviceProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidDeviceProfile.java
index c8d4fc8..61e5b6b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidDeviceProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidDeviceProfile.java
@@ -94,7 +94,7 @@
     }
 
     @Override
-    public boolean isConnectable() {
+    public boolean accessProfileEnabled() {
         return true;
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
index fe6b222..75d16db 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
@@ -93,7 +93,7 @@
                 BluetoothProfile.HID_HOST);
     }
 
-    public boolean isConnectable() {
+    public boolean accessProfileEnabled() {
         return true;
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfile.java
index 0447f37..4b0ca74 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfile.java
@@ -26,9 +26,9 @@
 public interface LocalBluetoothProfile {
 
     /**
-     * Returns true if the user can initiate a connection, false otherwise.
+     * Return {@code true} if the user can initiate a connection for this profile in UI.
      */
-    boolean isConnectable();
+    boolean accessProfileEnabled();
 
     /**
      * Returns true if the user can enable auto connection for this profile.
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 7000f9d..9653972 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -30,6 +30,7 @@
 import android.bluetooth.BluetoothPan;
 import android.bluetooth.BluetoothPbap;
 import android.bluetooth.BluetoothPbapClient;
+import android.bluetooth.BluetoothSap;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothUuid;
 import android.content.Context;
@@ -98,6 +99,7 @@
     private PbapClientProfile mPbapClientProfile;
     private PbapServerProfile mPbapProfile;
     private HearingAidProfile mHearingAidProfile;
+    private SapProfile mSapProfile;
 
     /**
      * Mapping from profile name, e.g. "HEADSET" to profile object.
@@ -210,6 +212,13 @@
             addProfile(mPbapClientProfile, PbapClientProfile.NAME,
                     BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED);
         }
+        if (mSapProfile == null && supportedList.contains(BluetoothProfile.SAP)) {
+            if (DEBUG) {
+                Log.d(TAG, "Adding local SAP profile");
+            }
+            mSapProfile = new SapProfile(mContext, mDeviceManager, this);
+            addProfile(mSapProfile, SapProfile.NAME, BluetoothSap.ACTION_CONNECTION_STATE_CHANGED);
+        }
         mEventManager.registerProfileIntentReceiver();
     }
 
@@ -290,10 +299,11 @@
                 }
             }
 
-            mEventManager.dispatchProfileConnectionStateChanged(cachedDevice, newState,
-                    mProfile.getProfileId());
             cachedDevice.onProfileStateChanged(mProfile, newState);
             cachedDevice.refresh();
+            // Dispatch profile changed after device update
+            mEventManager.dispatchProfileConnectionStateChanged(cachedDevice, newState,
+                    mProfile.getProfileId());
         }
     }
 
@@ -549,6 +559,11 @@
             removedProfiles.remove(mHearingAidProfile);
         }
 
+        if (mSapProfile != null && BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.SAP)) {
+            profiles.add(mSapProfile);
+            removedProfiles.remove(mSapProfile);
+        }
+
         if (DEBUG) {
             Log.d(TAG,"New Profiles" + profiles.toString());
         }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java
index 7ad2e28c..1e22f44 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java
@@ -105,7 +105,7 @@
                 new MapClientServiceListener(), BluetoothProfile.MAP_CLIENT);
     }
 
-    public boolean isConnectable() {
+    public boolean accessProfileEnabled() {
         return true;
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java
index caea04f..7582024 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java
@@ -104,7 +104,7 @@
                 BluetoothProfile.MAP);
     }
 
-    public boolean isConnectable() {
+    public boolean accessProfileEnabled() {
         return true;
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/OppProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/OppProfile.java
index dfd1622..e1e5dbe 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/OppProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/OppProfile.java
@@ -32,7 +32,7 @@
     // Order of this profile in device profiles list
     private static final int ORDINAL = 2;
 
-    public boolean isConnectable() {
+    public boolean accessProfileEnabled() {
         return false;
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PanProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PanProfile.java
index 02afe8d..7b81162 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PanProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PanProfile.java
@@ -78,7 +78,7 @@
             BluetoothProfile.PAN);
     }
 
-    public boolean isConnectable() {
+    public boolean accessProfileEnabled() {
         return true;
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
index 8fefb2f..1f15601 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
@@ -107,7 +107,7 @@
                 new PbapClientServiceListener(), BluetoothProfile.PBAP_CLIENT);
     }
 
-    public boolean isConnectable() {
+    public boolean accessProfileEnabled() {
         return true;
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapServerProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapServerProfile.java
index e9d8cb5..adef0841 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapServerProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapServerProfile.java
@@ -80,7 +80,7 @@
         BluetoothPbap pbap = new BluetoothPbap(context, new PbapServiceListener());
     }
 
-    public boolean isConnectable() {
+    public boolean accessProfileEnabled() {
         return true;
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java
index 61602c6..b4acc48 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java
@@ -36,12 +36,10 @@
  */
 final class SapProfile implements LocalBluetoothProfile {
     private static final String TAG = "SapProfile";
-    private static boolean V = true;
 
     private BluetoothSap mService;
     private boolean mIsProfileReady;
 
-    private final LocalBluetoothAdapter mLocalAdapter;
     private final CachedBluetoothDeviceManager mDeviceManager;
     private final LocalBluetoothProfileManager mProfileManager;
 
@@ -59,7 +57,7 @@
             implements BluetoothProfile.ServiceListener {
 
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            if (V) Log.d(TAG,"Bluetooth service connected");
+            Log.d(TAG, "Bluetooth service connected, profile:" + profile);
             mService = (BluetoothSap) proxy;
             // We just bound to the service, so refresh the UI for any connected SAP devices.
             List<BluetoothDevice> deviceList = mService.getConnectedDevices();
@@ -81,7 +79,7 @@
         }
 
         public void onServiceDisconnected(int profile) {
-            if (V) Log.d(TAG,"Bluetooth service disconnected");
+            Log.d(TAG, "Bluetooth service disconnected, profile:" + profile);
             mProfileManager.callServiceDisconnectedListeners();
             mIsProfileReady=false;
         }
@@ -96,17 +94,15 @@
         return BluetoothProfile.SAP;
     }
 
-    SapProfile(Context context, LocalBluetoothAdapter adapter,
-            CachedBluetoothDeviceManager deviceManager,
+    SapProfile(Context context, CachedBluetoothDeviceManager deviceManager,
             LocalBluetoothProfileManager profileManager) {
-        mLocalAdapter = adapter;
         mDeviceManager = deviceManager;
         mProfileManager = profileManager;
-        mLocalAdapter.getProfileProxy(context, new SapServiceListener(),
+        BluetoothAdapter.getDefaultAdapter().getProfileProxy(context, new SapServiceListener(),
                 BluetoothProfile.SAP);
     }
 
-    public boolean isConnectable() {
+    public boolean accessProfileEnabled() {
         return true;
     }
 
@@ -115,50 +111,47 @@
     }
 
     public boolean connect(BluetoothDevice device) {
-        if (mService == null) return false;
-        List<BluetoothDevice> sinks = mService.getConnectedDevices();
-        if (sinks != null) {
-            for (BluetoothDevice sink : sinks) {
-                mService.disconnect(sink);
-            }
+        if (mService == null) {
+            return false;
         }
         return mService.connect(device);
     }
 
     public boolean disconnect(BluetoothDevice device) {
-        if (mService == null) return false;
-        List<BluetoothDevice> deviceList = mService.getConnectedDevices();
-        if (!deviceList.isEmpty() && deviceList.get(0).equals(device)) {
-            if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
-                mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
-            }
-            return mService.disconnect(device);
-        } else {
+        if (mService == null) {
             return false;
         }
+        if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
+            mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+        }
+        return mService.disconnect(device);
     }
 
     public int getConnectionStatus(BluetoothDevice device) {
-        if (mService == null) return BluetoothProfile.STATE_DISCONNECTED;
-        List<BluetoothDevice> deviceList = mService.getConnectedDevices();
-
-        return !deviceList.isEmpty() && deviceList.get(0).equals(device)
-                ? mService.getConnectionState(device)
-                : BluetoothProfile.STATE_DISCONNECTED;
+        if (mService == null) {
+            return BluetoothProfile.STATE_DISCONNECTED;
+        }
+        return mService.getConnectionState(device);
     }
 
     public boolean isPreferred(BluetoothDevice device) {
-        if (mService == null) return false;
+        if (mService == null) {
+            return false;
+        }
         return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
     }
 
     public int getPreferred(BluetoothDevice device) {
-        if (mService == null) return BluetoothProfile.PRIORITY_OFF;
+        if (mService == null) {
+            return BluetoothProfile.PRIORITY_OFF;
+        }
         return mService.getPriority(device);
     }
 
     public void setPreferred(BluetoothDevice device, boolean preferred) {
-        if (mService == null) return;
+        if (mService == null) {
+            return;
+        }
         if (preferred) {
             if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
                 mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
@@ -169,7 +162,9 @@
     }
 
     public List<BluetoothDevice> getConnectedDevices() {
-        if (mService == null) return new ArrayList<BluetoothDevice>(0);
+        if (mService == null) {
+            return new ArrayList<BluetoothDevice>(0);
+        }
         return mService.getDevicesMatchingConnectionStates(
               new int[] {BluetoothProfile.STATE_CONNECTED,
                          BluetoothProfile.STATE_CONNECTING,
@@ -207,11 +202,11 @@
     }
 
     protected void finalize() {
-        if (V) Log.d(TAG, "finalize()");
+        Log.d(TAG, "finalize()");
         if (mService != null) {
             try {
                 BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.SAP,
-                                                                       mService);
+                        mService);
                 mService = null;
             }catch (Throwable t) {
                 Log.w(TAG, "Error cleaning up SAP proxy", t);
diff --git a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java
index 42306f6..9db4a35 100644
--- a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java
+++ b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java
@@ -46,7 +46,7 @@
  * TODO: Remove duplicate codes once backward support ends.
  */
 class LicenseHtmlGeneratorFromXml {
-    private static final String TAG = "LicenseHtmlGeneratorFromXml";
+    private static final String TAG = "LicenseGeneratorFromXml";
 
     private static final String TAG_ROOT = "licenses";
     private static final String TAG_FILE_NAME = "file-name";
@@ -107,12 +107,13 @@
         mXmlFiles = xmlFiles;
     }
 
-    public static boolean generateHtml(List<File> xmlFiles, File outputFile) {
+    public static boolean generateHtml(List<File> xmlFiles, File outputFile,
+            String noticeHeader) {
         LicenseHtmlGeneratorFromXml genertor = new LicenseHtmlGeneratorFromXml(xmlFiles);
-        return genertor.generateHtml(outputFile);
+        return genertor.generateHtml(outputFile, noticeHeader);
     }
 
-    private boolean generateHtml(File outputFile) {
+    private boolean generateHtml(File outputFile, String noticeHeader) {
         for (File xmlFile : mXmlFiles) {
             parse(xmlFile);
         }
@@ -125,7 +126,8 @@
         try {
             writer = new PrintWriter(outputFile);
 
-            generateHtml(mFileNameToContentIdMap, mContentIdToFileContentMap, writer);
+            generateHtml(mFileNameToContentIdMap, mContentIdToFileContentMap, writer,
+                noticeHeader);
 
             writer.flush();
             writer.close();
@@ -239,13 +241,18 @@
 
     @VisibleForTesting
     static void generateHtml(Map<String, String> fileNameToContentIdMap,
-            Map<String, String> contentIdToFileContentMap, PrintWriter writer) {
+            Map<String, String> contentIdToFileContentMap, PrintWriter writer,
+            String noticeHeader) {
         List<String> fileNameList = new ArrayList();
         fileNameList.addAll(fileNameToContentIdMap.keySet());
         Collections.sort(fileNameList);
 
         writer.println(HTML_HEAD_STRING);
 
+        if (!TextUtils.isEmpty(noticeHeader)) {
+            writer.println(noticeHeader);
+        }
+
         int count = 0;
         Map<String, Integer> contentIdToOrderMap = new HashMap();
         List<ContentIdAndFileNames> contentIdAndFileNamesList = new ArrayList();
diff --git a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoader.java b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoader.java
index 3930069..78e807c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoader.java
+++ b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoader.java
@@ -60,7 +60,7 @@
 
         File cachedHtmlFile = getCachedHtmlFile(mContext);
         if (!isCachedHtmlFileOutdated(xmlFiles, cachedHtmlFile)
-                || generateHtmlFile(xmlFiles, cachedHtmlFile)) {
+                || generateHtmlFile(mContext, xmlFiles, cachedHtmlFile)) {
             return cachedHtmlFile;
         }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoaderCompat.java b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoaderCompat.java
index 360c19c..ca62485 100644
--- a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoaderCompat.java
+++ b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoaderCompat.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.util.Log;
 
+import com.android.settingslib.R;
 import com.android.settingslib.utils.AsyncLoaderCompat;
 
 import java.io.File;
@@ -65,7 +66,7 @@
 
         File cachedHtmlFile = getCachedHtmlFile(mContext);
         if (!isCachedHtmlFileOutdated(xmlFiles, cachedHtmlFile)
-                || generateHtmlFile(xmlFiles, cachedHtmlFile)) {
+                || generateHtmlFile(mContext, xmlFiles, cachedHtmlFile)) {
             return cachedHtmlFile;
         }
 
@@ -101,7 +102,8 @@
         return outdated;
     }
 
-    static boolean generateHtmlFile(List<File> xmlFiles, File htmlFile) {
-        return LicenseHtmlGeneratorFromXml.generateHtml(xmlFiles, htmlFile);
+    static boolean generateHtmlFile(Context context, List<File> xmlFiles, File htmlFile) {
+        return LicenseHtmlGeneratorFromXml.generateHtml(xmlFiles, htmlFile,
+                context.getString(R.string.notice_header));
     }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoaderCompat.java b/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoaderCompat.java
index c3241bb..e9c5238 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoaderCompat.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoaderCompat.java
@@ -36,7 +36,13 @@
 
 /**
  * Loader for historical chart data for both network and UID details.
+ *
+ * Deprecated in favor of {@link NetworkCycleChartDataLoader} and
+ * {@link NetworkCycleDataForUidLoader}
+ *
+ * @deprecated
  */
+@Deprecated
 public class ChartDataLoaderCompat extends AsyncTaskLoader<ChartData> {
     private static final String KEY_TEMPLATE = "template";
     private static final String KEY_APP = "app";
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleChartData.java b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleChartData.java
new file mode 100644
index 0000000..9b3ff8b
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleChartData.java
@@ -0,0 +1,56 @@
+/*
+ * 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.settingslib.net;
+
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Usage data in a billing cycle with bucketized data for plotting the usage chart.
+ */
+public class NetworkCycleChartData extends NetworkCycleData {
+    public static final long BUCKET_DURATION_MS = TimeUnit.DAYS.toMillis(1);
+
+    private List<NetworkCycleData> mUsageBuckets;
+
+    private NetworkCycleChartData() {
+    }
+
+    public List<NetworkCycleData> getUsageBuckets() {
+        return mUsageBuckets;
+    }
+
+    public static class Builder extends NetworkCycleData.Builder {
+        private NetworkCycleChartData mObject = new NetworkCycleChartData();
+
+        public Builder setUsageBuckets(List<NetworkCycleData> buckets) {
+            getObject().mUsageBuckets = buckets;
+            return this;
+        }
+
+        @Override
+        protected NetworkCycleChartData getObject() {
+            return mObject;
+        }
+
+        @Override
+        public NetworkCycleChartData build() {
+            return getObject();
+        }
+    }
+
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleChartDataLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleChartDataLoader.java
new file mode 100644
index 0000000..7ae3398
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleChartDataLoader.java
@@ -0,0 +1,106 @@
+/*
+ * 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.settingslib.net;
+
+import android.app.usage.NetworkStats;
+import android.content.Context;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Loader for network data usage history. It returns a list of usage data per billing cycle with
+ * bucketized usages.
+ */
+public class NetworkCycleChartDataLoader
+        extends NetworkCycleDataLoader<List<NetworkCycleChartData>> {
+
+    private static final String TAG = "NetworkCycleChartLoader";
+
+    private final List<NetworkCycleChartData> mData;
+
+    private NetworkCycleChartDataLoader(Builder builder) {
+        super(builder);
+        mData = new ArrayList<NetworkCycleChartData>();
+    }
+
+    @Override
+    void recordUsage(long start, long end) {
+        try {
+            final NetworkStats stats = mNetworkStatsManager.querySummary(
+                mNetworkType, mSubId, start, end);
+            final long total = getTotalUsage(stats);
+            if (total > 0L) {
+                final NetworkCycleChartData.Builder builder = new NetworkCycleChartData.Builder();
+                builder.setUsageBuckets(getUsageBuckets(start, end))
+                    .setStartTime(start)
+                    .setEndTime(end)
+                    .setTotalUsage(total);
+                mData.add(builder.build());
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Exception querying network detail.", e);
+        }
+    }
+
+    @Override
+    List<NetworkCycleChartData> getCycleUsage() {
+        return mData;
+    }
+
+    public static Builder<?> builder(Context context) {
+        return new Builder<NetworkCycleChartDataLoader>(context) {
+            @Override
+            public NetworkCycleChartDataLoader build() {
+                return new NetworkCycleChartDataLoader(this);
+            }
+        };
+    }
+
+    private List<NetworkCycleData> getUsageBuckets(long start, long end) {
+        final List<NetworkCycleData> data = new ArrayList<>();
+        long bucketStart = start;
+        long bucketEnd = start + NetworkCycleChartData.BUCKET_DURATION_MS;
+        while (bucketEnd <= end) {
+            long usage = 0L;
+            try {
+                final NetworkStats stats = mNetworkStatsManager.querySummary(
+                    mNetworkType, mSubId, bucketStart, bucketEnd);
+                usage = getTotalUsage(stats);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Exception querying network detail.", e);
+            }
+            data.add(new NetworkCycleData.Builder()
+                .setStartTime(bucketStart).setEndTime(bucketEnd).setTotalUsage(usage).build());
+            bucketStart = bucketEnd;
+            bucketEnd += NetworkCycleChartData.BUCKET_DURATION_MS;
+        }
+        return data;
+    }
+
+    public static abstract class Builder<T extends NetworkCycleChartDataLoader>
+            extends NetworkCycleDataLoader.Builder<T> {
+
+        public Builder(Context context) {
+            super(context);
+        }
+
+    }
+
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleData.java b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleData.java
new file mode 100644
index 0000000..26c65a2
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleData.java
@@ -0,0 +1,70 @@
+/*
+ * 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.settingslib.net;
+
+/**
+ * Base data structure representing usage data in a billing cycle.
+ */
+public class NetworkCycleData {
+
+    private long mStartTime;
+    private long mEndTime;
+    private long mTotalUsage;
+
+    protected NetworkCycleData() {
+    }
+
+    public long getStartTime() {
+        return mStartTime;
+    }
+
+    public long getEndTime() {
+        return mEndTime;
+    }
+
+    public long getTotalUsage() {
+        return mTotalUsage;
+    }
+
+    public static class Builder {
+
+        private NetworkCycleData mObject = new NetworkCycleData();
+
+        public Builder setStartTime(long start) {
+            getObject().mStartTime = start;
+            return this;
+        }
+
+        public Builder setEndTime(long end) {
+            getObject().mEndTime = end;
+            return this;
+        }
+
+        public Builder setTotalUsage(long total) {
+            getObject().mTotalUsage = total;
+            return this;
+        }
+
+        protected NetworkCycleData getObject() {
+            return mObject;
+        }
+
+        public NetworkCycleData build() {
+            return getObject();
+        }
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUid.java b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUid.java
new file mode 100644
index 0000000..9d13717
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUid.java
@@ -0,0 +1,65 @@
+/*
+ * 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.settingslib.net;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Usage data in a billing cycle for a specific Uid.
+ */
+public class NetworkCycleDataForUid extends NetworkCycleData {
+
+    private long mBackgroudUsage;
+    private long mForegroudUsage;
+
+    private NetworkCycleDataForUid() {
+    }
+
+    public long getBackgroudUsage() {
+        return mBackgroudUsage;
+    }
+
+    public long getForegroudUsage() {
+        return mForegroudUsage;
+    }
+
+    public static class Builder extends NetworkCycleData.Builder {
+
+        private NetworkCycleDataForUid mObject = new NetworkCycleDataForUid();
+
+        public Builder setBackgroundUsage(long backgroundUsage) {
+            getObject().mBackgroudUsage = backgroundUsage;
+            return this;
+        }
+
+        public Builder setForegroundUsage(long foregroundUsage) {
+            getObject().mForegroudUsage = foregroundUsage;
+            return this;
+        }
+
+        @Override
+        public NetworkCycleDataForUid getObject() {
+            return mObject;
+        }
+
+        @Override
+        public NetworkCycleDataForUid build() {
+            return getObject();
+        }
+    }
+
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java
new file mode 100644
index 0000000..95efb4c
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.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 com.android.settingslib.net;
+
+import static android.app.usage.NetworkStats.Bucket.STATE_FOREGROUND;
+import static android.net.NetworkStats.TAG_NONE;
+
+import android.app.usage.NetworkStats;
+import android.content.Context;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Loader for network data usage history. It returns a list of usage data per billing cycle for a
+ * specific Uid.
+ */
+public class NetworkCycleDataForUidLoader extends
+        NetworkCycleDataLoader<List<NetworkCycleDataForUid>> {
+    private static final String TAG = "NetworkDataForUidLoader";
+
+    private final List<NetworkCycleDataForUid> mData;
+    private final int mUid;
+
+    private NetworkCycleDataForUidLoader(Builder builder) {
+        super(builder);
+        mUid = builder.mUid;
+        mData = new ArrayList<NetworkCycleDataForUid>();
+    }
+
+    @Override
+    void recordUsage(long start, long end) {
+        try {
+            final NetworkStats stats = mNetworkStatsManager.queryDetailsForUid(
+                mNetworkType, mSubId, start, end, mUid);
+            final long total = getTotalUsage(stats);
+            if (total > 0L) {
+                final long foreground = getForegroundUsage(start, end);
+                final NetworkCycleDataForUid.Builder builder = new NetworkCycleDataForUid.Builder();
+                builder.setBackgroundUsage(total - foreground)
+                    .setForegroundUsage(foreground)
+                    .setStartTime(start)
+                    .setEndTime(end)
+                    .setTotalUsage(total);
+                mData.add(builder.build());
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "Exception querying network detail.", e);
+        }
+    }
+
+    @Override
+    List<NetworkCycleDataForUid> getCycleUsage() {
+        return mData;
+    }
+
+    public static Builder<?> builder(Context context) {
+        return new Builder<NetworkCycleDataForUidLoader>(context) {
+            @Override
+            public NetworkCycleDataForUidLoader build() {
+                return new NetworkCycleDataForUidLoader(this);
+            }
+        };
+    }
+
+    private long getForegroundUsage(long start, long end) {
+        final NetworkStats stats = mNetworkStatsManager.queryDetailsForUidTagState(
+            mNetworkType, mSubId, start, end, mUid, TAG_NONE, STATE_FOREGROUND);
+        return getTotalUsage(stats);
+    }
+
+    public static abstract class Builder<T extends NetworkCycleDataForUidLoader>
+            extends NetworkCycleDataLoader.Builder<T> {
+
+        private int mUid;
+
+        public Builder(Context context) {
+            super(context);
+        }
+
+        public Builder<T> setUid(int uid) {
+            mUid = uid;
+            return this;
+        }
+    }
+
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataLoader.java
new file mode 100644
index 0000000..cc936d2
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataLoader.java
@@ -0,0 +1,189 @@
+/*
+ * 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.settingslib.net;
+
+import static android.net.NetworkStatsHistory.FIELD_RX_BYTES;
+import static android.net.NetworkStatsHistory.FIELD_TX_BYTES;
+
+import android.app.usage.NetworkStats;
+import android.app.usage.NetworkStatsManager;
+import android.content.Context;
+import android.net.INetworkStatsService;
+import android.net.INetworkStatsSession;
+import android.net.NetworkPolicy;
+import android.net.NetworkPolicyManager;
+import android.net.NetworkStatsHistory;
+import android.net.NetworkTemplate;
+import android.net.TrafficStats;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.text.format.DateUtils;
+import android.util.Pair;
+
+import java.time.ZonedDateTime;
+import java.util.Iterator;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.loader.content.AsyncTaskLoader;
+
+/**
+ * Loader for network data usage history. It returns a list of usage data per billing cycle.
+ */
+public abstract class NetworkCycleDataLoader<D> extends AsyncTaskLoader<D> {
+    private static final String TAG = "NetworkCycleDataLoader";
+    protected final NetworkStatsManager mNetworkStatsManager;
+    protected final String mSubId;
+    protected final int mNetworkType;
+    private final NetworkPolicy mPolicy;
+    private final NetworkTemplate mNetworkTemplate;
+    @VisibleForTesting
+    final INetworkStatsService mNetworkStatsService;
+
+    protected NetworkCycleDataLoader(Builder<?> builder) {
+        super(builder.mContext);
+        mPolicy = builder.mPolicy;
+        mSubId = builder.mSubId;
+        mNetworkType = builder.mNetworkType;
+        mNetworkTemplate = builder.mNetworkTemplate;
+        mNetworkStatsManager = (NetworkStatsManager)
+            builder.mContext.getSystemService(Context.NETWORK_STATS_SERVICE);
+        mNetworkStatsService = INetworkStatsService.Stub.asInterface(
+            ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
+    }
+
+    @Override
+    protected void onStartLoading() {
+        super.onStartLoading();
+        forceLoad();
+    }
+
+    public D loadInBackground() {
+        if (mPolicy == null) {
+            loadFourWeeksData();
+        } else {
+            loadPolicyData();
+        }
+        return getCycleUsage();
+    }
+
+    @VisibleForTesting
+    void loadPolicyData() {
+        final Iterator<Pair<ZonedDateTime, ZonedDateTime>> iterator =
+            NetworkPolicyManager.cycleIterator(mPolicy);
+        while (iterator.hasNext()) {
+            final Pair<ZonedDateTime, ZonedDateTime> cycle = iterator.next();
+            final long cycleStart = cycle.first.toInstant().toEpochMilli();
+            final long cycleEnd = cycle.second.toInstant().toEpochMilli();
+            recordUsage(cycleStart, cycleEnd);
+        }
+    }
+
+    @Override
+    protected void onStopLoading() {
+        super.onStopLoading();
+        cancelLoad();
+    }
+
+    @Override
+    protected void onReset() {
+        super.onReset();
+        cancelLoad();
+    }
+
+    @VisibleForTesting
+    void loadFourWeeksData() {
+        try {
+            final INetworkStatsSession networkSession = mNetworkStatsService.openSession();
+            final NetworkStatsHistory networkHistory = networkSession.getHistoryForNetwork(
+                mNetworkTemplate, FIELD_RX_BYTES | FIELD_TX_BYTES);
+            final long historyStart = networkHistory.getStart();
+            final long historyEnd = networkHistory.getEnd();
+
+            long cycleEnd = historyEnd;
+            while (cycleEnd > historyStart) {
+                final long cycleStart = cycleEnd - (DateUtils.WEEK_IN_MILLIS * 4);
+                recordUsage(cycleStart, cycleEnd);
+                cycleEnd = cycleStart;
+            }
+
+            TrafficStats.closeQuietly(networkSession);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @VisibleForTesting
+    abstract void recordUsage(long start, long end);
+
+    abstract D getCycleUsage();
+
+    public static Builder<?> builder(Context context) {
+        return new Builder<NetworkCycleDataLoader>(context) {
+            @Override
+            public NetworkCycleDataLoader build() {
+                return null;
+            }
+        };
+    }
+
+    protected long getTotalUsage(NetworkStats stats) {
+        long bytes = 0L;
+        if (stats != null) {
+            final NetworkStats.Bucket bucket = new NetworkStats.Bucket();
+            while (stats.hasNextBucket() && stats.getNextBucket(bucket)) {
+                bytes += bucket.getRxBytes() + bucket.getTxBytes();
+            }
+            stats.close();
+        }
+        return bytes;
+    }
+
+    public static abstract class Builder<T extends NetworkCycleDataLoader> {
+        private final Context mContext;
+        private NetworkPolicy mPolicy;
+        private String mSubId;
+        private int mNetworkType;
+        private NetworkTemplate mNetworkTemplate;
+
+        public Builder (Context context) {
+            mContext = context;
+        }
+
+        public Builder<T> setNetworkPolicy(NetworkPolicy policy) {
+            mPolicy = policy;
+            return this;
+        }
+
+        public Builder<T> setSubscriberId(String subId) {
+            mSubId = subId;
+            return this;
+        }
+
+        public Builder<T> setNetworkType(int networkType) {
+            mNetworkType = networkType;
+            return this;
+        }
+
+        public Builder<T> setNetworkTemplate(NetworkTemplate template) {
+            mNetworkTemplate = template;
+            return this;
+        }
+
+        public abstract T build();
+    }
+
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/NetworkStatsDetailLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/NetworkStatsSummaryLoader.java
similarity index 77%
rename from packages/SettingsLib/src/com/android/settingslib/net/NetworkStatsDetailLoader.java
rename to packages/SettingsLib/src/com/android/settingslib/net/NetworkStatsSummaryLoader.java
index a070b2a..34e6097 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/NetworkStatsDetailLoader.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/NetworkStatsSummaryLoader.java
@@ -20,25 +20,23 @@
 import android.app.usage.NetworkStats;
 import android.content.Context;
 import android.os.RemoteException;
-import android.telephony.TelephonyManager;
 import android.util.Log;
 
 import androidx.loader.content.AsyncTaskLoader;
 
 /**
- * Loader for retrieving the network stats details for all UIDs.
+ * Loader for retrieving the network stats summary for all UIDs.
  */
-public class NetworkStatsDetailLoader extends AsyncTaskLoader<NetworkStats> {
+public class NetworkStatsSummaryLoader extends AsyncTaskLoader<NetworkStats> {
 
     private static final String TAG = "NetworkDetailLoader";
     private final NetworkStatsManager mNetworkStatsManager;
-    private final TelephonyManager mTelephonyManager;
     private final long mStart;
     private final long mEnd;
-    private final int mSubId;
+    private final String mSubId;
     private final int mNetworkType;
 
-    private NetworkStatsDetailLoader(Builder builder) {
+    private NetworkStatsSummaryLoader(Builder builder) {
         super(builder.mContext);
         mStart = builder.mStart;
         mEnd = builder.mEnd;
@@ -46,8 +44,6 @@
         mNetworkType = builder.mNetworkType;
         mNetworkStatsManager = (NetworkStatsManager)
                 builder.mContext.getSystemService(Context.NETWORK_STATS_SERVICE);
-        mTelephonyManager =
-                (TelephonyManager) builder.mContext.getSystemService(Context.TELEPHONY_SERVICE);
     }
 
     @Override
@@ -59,8 +55,7 @@
     @Override
     public NetworkStats loadInBackground() {
         try {
-            return mNetworkStatsManager.queryDetails(
-                    mNetworkType, mTelephonyManager.getSubscriberId(mSubId), mStart, mEnd);
+            return mNetworkStatsManager.querySummary(mNetworkType, mSubId, mStart, mEnd);
         } catch (RemoteException e) {
             Log.e(TAG, "Exception querying network detail.", e);
             return null;
@@ -83,7 +78,7 @@
         private final Context mContext;
         private long mStart;
         private long mEnd;
-        private int mSubId;
+        private String mSubId;
         private int mNetworkType;
 
         public Builder(Context context) {
@@ -100,7 +95,7 @@
             return this;
         }
 
-        public Builder setSubscriptionId(int subId) {
+        public Builder setSubscriberId(String subId) {
             mSubId = subId;
             return this;
         }
@@ -110,8 +105,8 @@
             return this;
         }
 
-        public NetworkStatsDetailLoader build() {
-            return new NetworkStatsDetailLoader(this);
+        public NetworkStatsSummaryLoader build() {
+            return new NetworkStatsSummaryLoader(this);
         }
     }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index fe0b35b..089f773 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -163,6 +163,12 @@
                 ? null : AccessPoint.getSpeedLabel(mContext, scoredNetwork, rssi);
     }
 
+    /** Refresh the status label on Locale changed. */
+    public void refreshLocale() {
+        updateStatusLabel();
+        mCallback.run();
+    }
+
     private String getValidSsid(WifiInfo info) {
         String ssid = info.getSSID();
         if (ssid != null && !WifiSsid.NONE.equals(ssid)) {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingsLibRobolectricTestRunner.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingsLibRobolectricTestRunner.java
index 0ca2e87..ede248b 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingsLibRobolectricTestRunner.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingsLibRobolectricTestRunner.java
@@ -52,6 +52,7 @@
                 @Override
                 public List<ResourcePath> getIncludedResourcePaths() {
                     final List<ResourcePath> paths = super.getIncludedResourcePaths();
+                    paths.add(resourcePath("file:frameworks/base/packages/SettingsLib/AppPreference/res"));
                     paths.add(resourcePath("file:frameworks/base/packages/SettingsLib/HelpUtils/res"));
                     paths.add(resourcePath("file:frameworks/base/packages/SettingsLib/RestrictedLockUtils/res"));
                     paths.add(resourcePath("file:frameworks/base/packages/SettingsLib/res"));
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
index 7baded8..62b5688 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
@@ -118,7 +118,7 @@
      * Test to verify addDevice().
      */
     @Test
-    public void testAddDevice_validCachedDevices_devicesAdded() {
+    public void addDevice_validCachedDevices_devicesAdded() {
         CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
         CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
@@ -136,7 +136,7 @@
      * Test to verify getName().
      */
     @Test
-    public void testGetName_validCachedDevice_nameFound() {
+    public void getName_validCachedDevice_nameFound() {
         CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
         assertThat(mCachedDeviceManager.getName(mDevice1)).isEqualTo(DEVICE_ALIAS_1);
@@ -146,7 +146,7 @@
      * Test to verify onDeviceNameUpdated().
      */
     @Test
-    public void testOnDeviceNameUpdated_validName_nameUpdated() {
+    public void onDeviceNameUpdated_validName_nameUpdated() {
         CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
         assertThat(cachedDevice1.getName()).isEqualTo(DEVICE_ALIAS_1);
@@ -161,7 +161,7 @@
      * Test to verify clearNonBondedDevices().
      */
     @Test
-    public void testClearNonBondedDevices_bondedAndNonBondedDevices_nonBondedDevicesCleared() {
+    public void clearNonBondedDevices_bondedAndNonBondedDevices_nonBondedDevicesCleared() {
         CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
         CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
@@ -193,7 +193,7 @@
      * Test to verify clearNonBondedDevices() for hearing aids.
      */
     @Test
-    public void testClearNonBondedDevices_HearingAids_nonBondedHAsClearedFromCachedDevicesMap() {
+    public void clearNonBondedDevices_HearingAids_nonBondedHAsClearedFromCachedDevicesMap() {
         when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
         when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
 
@@ -214,7 +214,7 @@
      * Test to verify onHiSyncIdChanged() for hearing aid devices with same HiSyncId.
      */
     @Test
-    public void testOnHiSyncIdChanged_sameHiSyncId_populateInDifferentLists() {
+    public void onHiSyncIdChanged_sameHiSyncId_populateInDifferentLists() {
         CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
         CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
@@ -247,7 +247,7 @@
      * device is connected and other is disconnected. The connected device should be chosen.
      */
     @Test
-    public void testOnHiSyncIdChanged_sameHiSyncIdAndOneConnected_chooseConnectedDevice() {
+    public void onHiSyncIdChanged_sameHiSyncIdAndOneConnected_chooseConnectedDevice() {
         CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
         CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
@@ -282,7 +282,7 @@
      * Test to verify onHiSyncIdChanged() for hearing aid devices with different HiSyncId.
      */
     @Test
-    public void testOnHiSyncIdChanged_differentHiSyncId_populateInSameList() {
+    public void onHiSyncIdChanged_differentHiSyncId_populateInSameList() {
         CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
         CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
@@ -316,7 +316,7 @@
      * Test to verify onProfileConnectionStateChanged() for single hearing aid device connection.
      */
     @Test
-    public void testOnProfileConnectionStateChanged_singleDeviceConnected_visible() {
+    public void onProfileConnectionStateChanged_singleDeviceConnected_visible() {
         CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
         cachedDevice1.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
@@ -353,7 +353,7 @@
      * devices are disconnected and they get connected.
      */
     @Test
-    public void testOnProfileConnectionStateChanged_twoDevicesConnected_oneDeviceVisible() {
+    public void onProfileConnectionStateChanged_twoDevicesConnected_oneDeviceVisible() {
         CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
         CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
@@ -405,7 +405,7 @@
      * devices are connected and they get disconnected.
      */
     @Test
-    public void testOnProfileConnectionStateChanged_twoDevicesDisconnected_oneDeviceVisible() {
+    public void onProfileConnectionStateChanged_twoDevicesDisconnected_oneDeviceVisible() {
         CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
         CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
@@ -458,7 +458,7 @@
      * Test to verify OnDeviceUnpaired() for a paired hearing Aid device pair.
      */
     @Test
-    public void testOnDeviceUnpaired_bothHearingAidsPaired_removesItsPairFromList() {
+    public void onDeviceUnpaired_bothHearingAidsPaired_removesItsPairFromList() {
         CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
         CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
@@ -488,7 +488,7 @@
      * Test to verify OnDeviceUnpaired() for paired hearing Aid devices which are not a pair.
      */
     @Test
-    public void testOnDeviceUnpaired_bothHearingAidsNotPaired_doesNotRemoveAnyDeviceFromList() {
+    public void onDeviceUnpaired_bothHearingAidsNotPaired_doesNotRemoveAnyDeviceFromList() {
         CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
         CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
@@ -532,7 +532,7 @@
      * Test to verify addDevice() for hearing aid devices with same HiSyncId.
      */
     @Test
-    public void testAddDevice_hearingAidDevicesWithSameHiSyncId_populateInDifferentLists() {
+    public void addDevice_hearingAidDevicesWithSameHiSyncId_populateInDifferentLists() {
         doAnswer((invocation) -> mHearingAidProfile).when(mLocalProfileManager)
             .getHearingAidProfile();
         doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice1);
@@ -560,7 +560,7 @@
      * Test to verify addDevice() for hearing aid devices with different HiSyncId.
      */
     @Test
-    public void testAddDevice_hearingAidDevicesWithDifferentHiSyncId_populateInSameList() {
+    public void addDevice_hearingAidDevicesWithDifferentHiSyncId_populateInSameList() {
         doAnswer((invocation) -> mHearingAidProfile).when(mLocalProfileManager)
             .getHearingAidProfile();
         doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice1);
@@ -592,7 +592,7 @@
      * Test to verify getHearingAidPairDeviceSummary() for hearing aid devices with same HiSyncId.
      */
     @Test
-    public void testGetHearingAidPairDeviceSummary_bothHearingAidsPaired_returnsSummaryOfPair() {
+    public void getHearingAidPairDeviceSummary_bothHearingAidsPaired_returnsSummaryOfPair() {
         mCachedDevice1.setHiSyncId(HISYNCID1);
         mCachedDevice2.setHiSyncId(HISYNCID1);
         mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
@@ -609,7 +609,7 @@
      * HiSyncId.
      */
     @Test
-    public void testGetHearingAidPairDeviceSummary_bothHearingAidsNotPaired_returnsNull() {
+    public void getHearingAidPairDeviceSummary_bothHearingAidsNotPaired_returnsNull() {
         mCachedDevice1.setHiSyncId(HISYNCID1);
         mCachedDevice2.setHiSyncId(HISYNCID2);
         mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
@@ -625,7 +625,7 @@
      * Test to verify updateHearingAidsDevices().
      */
     @Test
-    public void testUpdateHearingAidDevices_hiSyncIdAvailable_setsHiSyncId() {
+    public void updateHearingAidDevices_hiSyncIdAvailable_setsHiSyncId() {
         doAnswer((invocation) -> mHearingAidProfile).when(mLocalProfileManager)
             .getHearingAidProfile();
         doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice1);
@@ -643,7 +643,7 @@
      * Test to verify onBtClassChanged().
      */
     @Test
-    public void testOnBtClassChanged_validBtClass_classChanged() {
+    public void onBtClassChanged_validBtClass_classChanged() {
         CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
         assertThat(cachedDevice1.getBtClass()).isEqualTo(DEVICE_CLASS_1);
@@ -658,7 +658,7 @@
      * Test to verify onDeviceDisappeared().
      */
     @Test
-    public void testOnDeviceDisappeared_deviceBondedUnbonded_unbondedDeviceDisappeared() {
+    public void onDeviceDisappeared_deviceBondedUnbonded_unbondedDeviceDisappeared() {
         CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
 
@@ -673,7 +673,7 @@
      * Test to verify onActiveDeviceChanged().
      */
     @Test
-    public void testOnActiveDeviceChanged_connectedDevices_activeDeviceChanged() {
+    public void onActiveDeviceChanged_connectedDevices_activeDeviceChanged() {
         CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
         CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
@@ -736,7 +736,7 @@
      * Test to verify onActiveDeviceChanged() with A2DP and Hearing Aid.
      */
     @Test
-    public void testOnActiveDeviceChanged_withA2dpAndHearingAid() {
+    public void onActiveDeviceChanged_withA2dpAndHearingAid() {
         CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
         CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
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 c18db11..f6201dd 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
@@ -20,6 +20,7 @@
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
@@ -79,74 +80,74 @@
     }
 
     @Test
-    public void testGetConnectionSummary_testSingleProfileConnectDisconnect() {
+    public void getConnectionSummary_testSingleProfileConnectDisconnect() {
         // Test without battery level
         // Set PAN profile to be connected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mPanProfile, BluetoothProfile.STATE_CONNECTED);
         assertThat(mCachedDevice.getConnectionSummary()).isNull();
 
         // Set PAN profile to be disconnected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getConnectionSummary()).isNull();
 
         // Test with battery level
         mBatteryLevel = 10;
         // Set PAN profile to be connected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mPanProfile, BluetoothProfile.STATE_CONNECTED);
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("10% battery");
 
         // Set PAN profile to be disconnected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getConnectionSummary()).isNull();
 
         // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
         mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
 
         // Set PAN profile to be connected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mPanProfile, BluetoothProfile.STATE_CONNECTED);
         assertThat(mCachedDevice.getConnectionSummary()).isNull();
 
         // Set PAN profile to be disconnected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getConnectionSummary()).isNull();
     }
 
     @Test
-    public void testGetConnectionSummary_testMultipleProfileConnectDisconnect() {
+    public void getConnectionSummary_testMultipleProfileConnectDisconnect() {
         mBatteryLevel = 10;
 
         // Set HFP, A2DP and PAN profile to be connected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
-        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
-        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mPanProfile, BluetoothProfile.STATE_CONNECTED);
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("10% battery");
 
         // Disconnect HFP only and test connection state summary
-        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
                 "10% battery");
 
         // Disconnect A2DP only and test connection state summary
-        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
-        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
                 "10% battery");
 
         // Disconnect both HFP and A2DP and test connection state summary
-        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
                 "10% battery");
 
         // Disconnect all profiles and test connection state summary
-        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getConnectionSummary()).isNull();
     }
 
     @Test
-    public void testGetConnectionSummary_testSingleProfileActiveDeviceA2dp() {
+    public void getConnectionSummary_testSingleProfileActiveDeviceA2dp() {
         // Test without battery level
         // Set A2DP profile to be connected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
         assertThat(mCachedDevice.getConnectionSummary()).isNull();
 
         // Set device as Active for A2DP and test connection state summary
@@ -159,26 +160,26 @@
                 "Active, 10% battery");
 
         // Set A2DP profile to be disconnected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getConnectionSummary()).isNull();
 
         // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
         mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
         // Set A2DP profile to be connected, Active and test connection state summary
-        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
 
         // Set A2DP profile to be disconnected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getConnectionSummary()).isNull();
     }
 
     @Test
-    public void testGetConnectionSummary_testSingleProfileActiveDeviceHfp() {
+    public void getConnectionSummary_testSingleProfileActiveDeviceHfp() {
         // Test without battery level
         // Set HFP profile to be connected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
         assertThat(mCachedDevice.getConnectionSummary()).isNull();
 
         // Set device as Active for HFP and test connection state summary
@@ -193,26 +194,26 @@
                 "Active, 10% battery");
 
         // Set HFP profile to be disconnected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getConnectionSummary()).isNull();
 
         // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
         mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
         // Set HFP profile to be connected, Active and test connection state summary
-        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
 
         // Set HFP profile to be disconnected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getConnectionSummary()).isNull();
     }
 
     @Test
-    public void testGetConnectionSummary_testSingleProfileActiveDeviceHearingAid() {
+    public void getConnectionSummary_testSingleProfileActiveDeviceHearingAid() {
         // Test without battery level
         // Set Hearing Aid profile to be connected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
         assertThat(mCachedDevice.getConnectionSummary()).isNull();
 
         // Set device as Active for Hearing Aid and test connection state summary
@@ -227,11 +228,11 @@
     }
 
     @Test
-    public void testGetConnectionSummary_testMultipleProfilesActiveDevice() {
+    public void getConnectionSummary_testMultipleProfilesActiveDevice() {
         // Test without battery level
         // Set A2DP and HFP profiles to be connected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
-        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
         assertThat(mCachedDevice.getConnectionSummary()).isNull();
 
         // Set device as Active for A2DP and HFP and test connection state summary
@@ -246,14 +247,14 @@
 
         // Disconnect A2DP only and test connection state summary
         mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.A2DP);
-        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
                 "10% battery");
 
         // Disconnect HFP only and test connection state summary
         mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.HEADSET);
-        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
-        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
                 "Active, 10% battery");
@@ -261,15 +262,15 @@
         // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
         mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
         // Set A2DP and HFP profiles to be connected, Active and test connection state summary
-        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
-        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
 
         // Set A2DP and HFP profiles to be disconnected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
-        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getConnectionSummary()).isNull();
     }
 
@@ -277,32 +278,32 @@
     public void getCarConnectionSummary_singleProfileConnectDisconnect() {
         // Test without battery level
         // Set PAN profile to be connected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mPanProfile, BluetoothProfile.STATE_CONNECTED);
         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected");
 
         // Set PAN profile to be disconnected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
 
         // Test with battery level
         mBatteryLevel = 10;
         // Set PAN profile to be connected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mPanProfile, BluetoothProfile.STATE_CONNECTED);
         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected, battery 10%");
 
         // Set PAN profile to be disconnected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
 
         // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
         mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
 
         // Set PAN profile to be connected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mPanProfile, BluetoothProfile.STATE_CONNECTED);
         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected");
 
         // Set PAN profile to be disconnected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
     }
 
@@ -311,29 +312,29 @@
         mBatteryLevel = 10;
 
         // Set HFP, A2DP and PAN profile to be connected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
-        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
-        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mPanProfile, BluetoothProfile.STATE_CONNECTED);
         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected, battery 10%");
 
         // Disconnect HFP only and test connection state summary
-        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo(
                 "Connected (no phone), battery 10%");
 
         // Disconnect A2DP only and test connection state summary
-        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
-        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo(
                 "Connected (no media), battery 10%");
 
         // Disconnect both HFP and A2DP and test connection state summary
-        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo(
                 "Connected (no phone or media), battery 10%");
 
         // Disconnect all profiles and test connection state summary
-        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
     }
 
@@ -341,7 +342,7 @@
     public void getCarConnectionSummary_singleProfileActiveDeviceA2dp() {
         // Test without battery level
         // Set A2DP profile to be connected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected");
 
         // Set device as Active for A2DP and test connection state summary
@@ -354,18 +355,18 @@
                 "Connected, battery 10%, active (media)");
 
         // Set A2DP profile to be disconnected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
 
         // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
         mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
         // Set A2DP profile to be connected, Active and test connection state summary
-        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected, active (media)");
 
         // Set A2DP profile to be disconnected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
     }
 
@@ -373,7 +374,7 @@
     public void getCarConnectionSummary_singleProfileActiveDeviceHfp() {
         // Test without battery level
         // Set HFP profile to be connected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected");
 
         // Set device as Active for HFP and test connection state summary
@@ -386,18 +387,18 @@
                 "Connected, battery 10%, active (phone)");
 
         // Set HFP profile to be disconnected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
 
         // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
         mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
         // Set HFP profile to be connected, Active and test connection state summary
-        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected, active (phone)");
 
         // Set HFP profile to be disconnected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
     }
 
@@ -405,7 +406,7 @@
     public void getCarConnectionSummary_singleProfileActiveDeviceHearingAid() {
         // Test without battery level
         // Set Hearing Aid profile to be connected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected");
 
         // Set device as Active for Hearing Aid and test connection state summary
@@ -414,8 +415,7 @@
 
         // Set Hearing Aid profile to be disconnected and test connection state summary
         mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.HEARING_AID);
-        mCachedDevice.onProfileStateChanged(mHearingAidProfile,
-                BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
     }
 
@@ -423,8 +423,8 @@
     public void getCarConnectionSummary_multipleProfilesActiveDevice() {
         // Test without battery level
         // Set A2DP and HFP profiles to be connected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
-        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected");
 
         // Set device as Active for A2DP and HFP and test connection state summary
@@ -439,14 +439,14 @@
 
         // Disconnect A2DP only and test connection state summary
         mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.A2DP);
-        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo(
                 "Connected (no media), battery 10%, active (phone)");
 
         // Disconnect HFP only and test connection state summary
         mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.HEADSET);
-        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
-        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo(
                 "Connected (no phone), battery 10%, active (media)");
@@ -454,21 +454,21 @@
         // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
         mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
         // Set A2DP and HFP profiles to be connected, Active and test connection state summary
-        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
-        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected, active");
 
         // Set A2DP and HFP profiles to be disconnected and test connection state summary
-        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
-        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
     }
 
 
     @Test
-    public void testDeviceName_testAliasNameAvailable() {
+    public void deviceName_testAliasNameAvailable() {
         when(mDevice.getAliasName()).thenReturn(DEVICE_ALIAS);
         when(mDevice.getName()).thenReturn(DEVICE_NAME);
         CachedBluetoothDevice cachedBluetoothDevice =
@@ -480,7 +480,7 @@
     }
 
     @Test
-    public void testDeviceName_testNameNotAvailable() {
+    public void deviceName_testNameNotAvailable() {
         CachedBluetoothDevice cachedBluetoothDevice =
                 new CachedBluetoothDevice(mContext, mProfileManager, mDevice);
         // Verify device address is returned on getName
@@ -490,7 +490,7 @@
     }
 
     @Test
-    public void testDeviceName_testRenameDevice() {
+    public void deviceName_testRenameDevice() {
         final String[] alias = {DEVICE_ALIAS};
         doAnswer(invocation -> alias[0]).when(mDevice).getAliasName();
         doAnswer(invocation -> {
@@ -513,7 +513,7 @@
     }
 
     @Test
-    public void testSetActive() {
+    public void setActive() {
         when(mProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile);
         when(mProfileManager.getHeadsetProfile()).thenReturn(mHfpProfile);
         when(mA2dpProfile.setActiveDevice(any(BluetoothDevice.class))).thenReturn(true);
@@ -521,19 +521,19 @@
 
         assertThat(mCachedDevice.setActive()).isFalse();
 
-        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
         assertThat(mCachedDevice.setActive()).isTrue();
 
-        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
-        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+        updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
         assertThat(mCachedDevice.setActive()).isTrue();
 
-        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.setActive()).isFalse();
     }
 
     @Test
-    public void testIsA2dpDevice_isA2dpDevice() {
+    public void isA2dpDevice_isA2dpDevice() {
         when(mProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile);
         when(mA2dpProfile.getConnectionStatus(mDevice)).
                 thenReturn(BluetoothProfile.STATE_CONNECTED);
@@ -542,7 +542,7 @@
     }
 
     @Test
-    public void testIsA2dpDevice_isNotA2dpDevice() {
+    public void isA2dpDevice_isNotA2dpDevice() {
         when(mProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile);
         when(mA2dpProfile.getConnectionStatus(mDevice)).
                 thenReturn(BluetoothProfile.STATE_DISCONNECTING);
@@ -551,7 +551,7 @@
     }
 
     @Test
-    public void testIsHfpDevice_isHfpDevice() {
+    public void isHfpDevice_isHfpDevice() {
         when(mProfileManager.getHeadsetProfile()).thenReturn(mHfpProfile);
         when(mHfpProfile.getConnectionStatus(mDevice)).
                 thenReturn(BluetoothProfile.STATE_CONNECTED);
@@ -637,4 +637,24 @@
 
         verify(mDevice, never()).setAlias(any());
     }
+
+    @Test
+    public void getProfileConnectionState_nullProfile_returnDisconnected() {
+        assertThat(mCachedDevice.getProfileConnectionState(null)).isEqualTo(
+                BluetoothProfile.STATE_DISCONNECTED);
+    }
+
+    @Test
+    public void getProfileConnectionState_profileConnected_returnConnected() {
+        doReturn(BluetoothProfile.STATE_CONNECTED).when(mA2dpProfile).getConnectionStatus(
+                any(BluetoothDevice.class));
+
+        assertThat(mCachedDevice.getProfileConnectionState(mA2dpProfile)).isEqualTo(
+                BluetoothProfile.STATE_CONNECTED);
+    }
+
+    private void updateProfileStatus(LocalBluetoothProfile profile, int status) {
+        doReturn(status).when(profile).getConnectionStatus(mDevice);
+        mCachedDevice.onProfileStateChanged(profile, status);
+    }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/SapProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/SapProfileTest.java
new file mode 100644
index 0000000..9bb53ee
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/SapProfileTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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.settingslib.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothSap;
+import android.bluetooth.BluetoothProfile;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
+
+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.RuntimeEnvironment;
+import org.robolectric.shadow.api.Shadow;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+@Config(shadows = {ShadowBluetoothAdapter.class})
+public class SapProfileTest {
+
+    @Mock
+    private CachedBluetoothDeviceManager mDeviceManager;
+    @Mock
+    private LocalBluetoothProfileManager mProfileManager;
+    @Mock
+    private BluetoothSap mService;
+    @Mock
+    private CachedBluetoothDevice mCachedBluetoothDevice;
+    @Mock
+    private BluetoothDevice mBluetoothDevice;
+    private BluetoothProfile.ServiceListener mServiceListener;
+    private SapProfile mProfile;
+    private ShadowBluetoothAdapter mShadowBluetoothAdapter;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
+        mProfile = new SapProfile(RuntimeEnvironment.application, mDeviceManager, mProfileManager);
+        mServiceListener = mShadowBluetoothAdapter.getServiceListener();
+        mServiceListener.onServiceConnected(BluetoothProfile.SAP, mService);
+    }
+
+    @Test
+    public void connect_shouldConnectBluetoothSap() {
+        mProfile.connect(mBluetoothDevice);
+        verify(mService).connect(mBluetoothDevice);
+    }
+
+    @Test
+    public void disconnect_shouldDisconnectBluetoothSap() {
+        mProfile.disconnect(mBluetoothDevice);
+        verify(mService).disconnect(mBluetoothDevice);
+    }
+
+    @Test
+    public void getConnectionStatus_shouldReturnConnectionState() {
+        when(mService.getConnectionState(mBluetoothDevice)).
+                thenReturn(BluetoothProfile.STATE_CONNECTED);
+        assertThat(mProfile.getConnectionStatus(mBluetoothDevice)).
+                isEqualTo(BluetoothProfile.STATE_CONNECTED);
+    }
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java
index c23ad79..887c1d5 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java
@@ -38,13 +38,13 @@
 import com.android.settingslib.core.lifecycle.events.OnResume;
 import com.android.settingslib.core.lifecycle.events.OnStart;
 import com.android.settingslib.core.lifecycle.events.OnStop;
-import com.android.settingslib.testutils.FragmentTestUtils;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.Robolectric;
 import org.robolectric.android.controller.ActivityController;
+import org.robolectric.shadows.androidx.fragment.FragmentController;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
 public class LifecycleTest {
@@ -184,7 +184,7 @@
     @Test
     public void runThroughDialogFragmentLifecycles_shouldObserveEverything() {
         final TestDialogFragment fragment = new TestDialogFragment();
-        FragmentTestUtils.startFragment(fragment);
+        FragmentController.setupFragment(fragment);
 
         fragment.onCreateOptionsMenu(null, null);
         fragment.onPrepareOptionsMenu(null);
@@ -208,7 +208,7 @@
     @Test
     public void runThroughFragmentLifecycles_shouldObserveEverything() {
         final TestFragment fragment = new TestFragment();
-        FragmentTestUtils.startFragment(fragment);
+        FragmentController.setupFragment(fragment);
 
         fragment.onCreateOptionsMenu(null, null);
         fragment.onPrepareOptionsMenu(null);
@@ -248,7 +248,7 @@
     @Test
     public void onOptionItemSelectedShortCircuitsIfAnObserverHandlesTheMenuItem() {
         final TestFragment fragment = new TestFragment();
-        FragmentTestUtils.startFragment(fragment);
+        FragmentController.setupFragment(fragment);
 
         final OptionItemAccepter accepter = new OptionItemAccepter();
         fragment.getLifecycle().addObserver(accepter);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java
index 96b2a14..b00476b2 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java
@@ -50,7 +50,7 @@
             + "<file-content contentId=\"0\"><![CDATA[license content #0]]></file-content>\n"
             + "</licenses2>";
 
-    private static final String EXPECTED_HTML_STRING =
+    private static final String HTML_HEAD_STRING =
             "<html><head>\n"
             + "<style type=\"text/css\">\n"
             + "body { padding: 0; font-family: sans-serif; }\n"
@@ -63,8 +63,12 @@
             + "</head>"
             + "<body topmargin=\"0\" leftmargin=\"0\" rightmargin=\"0\" bottommargin=\"0\">\n"
             + "<div class=\"toc\">\n"
-            + "<ul>\n"
-            + "<li><a href=\"#id0\">/file0</a></li>\n"
+            + "<ul>\n";
+
+    private static final String HTML_CUSTOM_HEADING = "Custom heading";
+
+    private static final String HTML_BODY_STRING =
+            "<li><a href=\"#id0\">/file0</a></li>\n"
             + "<li><a href=\"#id0\">/file1</a></li>\n"
             + "</ul>\n"
             + "</div><!-- table of contents -->\n"
@@ -81,6 +85,11 @@
             + "</td></tr><!-- same-license -->\n"
             + "</table></body></html>\n";
 
+    private static final String EXPECTED_HTML_STRING = HTML_HEAD_STRING + HTML_BODY_STRING;
+
+    private static final String EXPECTED_HTML_STRING_WITH_CUSTOM_HEADING =
+            HTML_HEAD_STRING + HTML_CUSTOM_HEADING + "\n" + HTML_BODY_STRING;
+
     @Test
     public void testParseValidXmlStream() throws XmlPullParserException, IOException {
         Map<String, String> fileNameToContentIdMap = new HashMap<String, String>();
@@ -117,7 +126,23 @@
 
         StringWriter output = new StringWriter();
         LicenseHtmlGeneratorFromXml.generateHtml(
-                fileNameToContentIdMap, contentIdToFileContentMap, new PrintWriter(output));
+                fileNameToContentIdMap, contentIdToFileContentMap, new PrintWriter(output), "");
         assertThat(output.toString()).isEqualTo(EXPECTED_HTML_STRING);
     }
+
+    @Test
+    public void testGenerateHtmlWithCustomHeading() {
+        Map<String, String> fileNameToContentIdMap = new HashMap<String, String>();
+        Map<String, String> contentIdToFileContentMap = new HashMap<String, String>();
+
+        fileNameToContentIdMap.put("/file0", "0");
+        fileNameToContentIdMap.put("/file1", "0");
+        contentIdToFileContentMap.put("0", "license content #0");
+
+        StringWriter output = new StringWriter();
+        LicenseHtmlGeneratorFromXml.generateHtml(
+                fileNameToContentIdMap, contentIdToFileContentMap, new PrintWriter(output),
+                HTML_CUSTOM_HEADING);
+        assertThat(output.toString()).isEqualTo(EXPECTED_HTML_STRING_WITH_CUSTOM_HEADING);
+    }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlLoaderCompatTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlLoaderCompatTest.java
index 12a4e69..c32cc99 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlLoaderCompatTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlLoaderCompatTest.java
@@ -142,7 +142,7 @@
         }
 
         @Implementation
-        static boolean generateHtmlFile(List<File> xmlFiles, File htmlFile) {
+        static boolean generateHtmlFile(Context context, List<File> xmlFiles, File htmlFile) {
             return sGenerateHtmlFileSucceeded;
         }
     }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleChartDataLoaderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleChartDataLoaderTest.java
new file mode 100644
index 0000000..3dc110d
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleChartDataLoaderTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.settingslib.net;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.usage.NetworkStatsManager;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.os.RemoteException;
+import android.text.format.DateUtils;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+public class NetworkCycleChartDataLoaderTest {
+
+    @Mock
+    private NetworkStatsManager mNetworkStatsManager;
+    @Mock
+    private Context mContext;
+
+    private NetworkCycleChartDataLoader mLoader;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        when(mContext.getSystemService(Context.NETWORK_STATS_SERVICE))
+            .thenReturn(mNetworkStatsManager);
+    }
+
+    @Test
+    public void recordUsage_shouldQueryNetworkSummary() throws RemoteException {
+        final long end = System.currentTimeMillis();
+        final long start = end - (DateUtils.WEEK_IN_MILLIS * 4);
+        final int networkType = ConnectivityManager.TYPE_MOBILE;
+        final String subId = "TestSubscriber";
+        mLoader = NetworkCycleChartDataLoader.builder(mContext)
+            .setNetworkType(networkType).setSubscriberId(subId).build();
+
+        mLoader.recordUsage(start, end);
+
+        verify(mNetworkStatsManager).querySummary(networkType, subId, start, end);
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java
new file mode 100644
index 0000000..53fe451
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.settingslib.net;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.usage.NetworkStatsManager;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.text.format.DateUtils;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+public class NetworkCycleDataForUidLoaderTest {
+
+    @Mock
+    private NetworkStatsManager mNetworkStatsManager;
+    @Mock
+    private Context mContext;
+
+    private NetworkCycleDataForUidLoader mLoader;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        when(mContext.getSystemService(Context.NETWORK_STATS_SERVICE))
+            .thenReturn(mNetworkStatsManager);
+    }
+
+    @Test
+    public void recordUsage_shouldQueryNetworkDetailsForUid() {
+        final long end = System.currentTimeMillis();
+        final long start = end - (DateUtils.WEEK_IN_MILLIS * 4);
+        final int networkType = ConnectivityManager.TYPE_MOBILE;
+        final String subId = "TestSubscriber";
+        final int uid = 1;
+        mLoader = NetworkCycleDataForUidLoader.builder(mContext)
+            .setUid(uid).setNetworkType(networkType).setSubscriberId(subId).build();
+
+        mLoader.recordUsage(start, end);
+
+        verify(mNetworkStatsManager).queryDetailsForUid(networkType, subId, start, end, uid);
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java
new file mode 100644
index 0000000..be7f1bb
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java
@@ -0,0 +1,155 @@
+/*
+ * 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.settingslib.net;
+
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.nullable;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.usage.NetworkStatsManager;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.INetworkStatsService;
+import android.net.INetworkStatsSession;
+import android.net.NetworkPolicy;
+import android.net.NetworkStatsHistory;
+import android.net.NetworkTemplate;
+import android.os.RemoteException;
+import android.text.format.DateUtils;
+import android.util.Range;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.util.ReflectionHelpers;
+
+import java.time.ZonedDateTime;
+import java.util.Iterator;
+import java.util.List;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+public class NetworkCycleDataLoaderTest {
+
+    @Mock
+    private NetworkStatsManager mNetworkStatsManager;
+    @Mock
+    private Context mContext;
+    @Mock
+    private NetworkPolicy mPolicy;
+    @Mock
+    private Iterator<Range<ZonedDateTime>> mIterator;
+    @Mock
+    private INetworkStatsService mNetworkStatsService;
+    @Mock
+    private NetworkCycleDataLoader.Builder mBuilder;
+
+
+    private NetworkCycleDataTestLoader mLoader;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        when(mContext.getSystemService(Context.NETWORK_STATS_SERVICE))
+            .thenReturn(mNetworkStatsManager);
+        when(mPolicy.cycleIterator()).thenReturn(mIterator);
+    }
+
+    @Test
+    public void loadInBackground_noNetworkPolicy_shouldLoad4WeeksData() {
+        mLoader = spy(new NetworkCycleDataTestLoader(mContext));
+        doNothing().when(mLoader).loadFourWeeksData();
+
+        mLoader.loadInBackground();
+
+        verify(mLoader).loadFourWeeksData();
+    }
+
+    @Test
+    public void loadInBackground_hasNetworkPolicy_shouldLoadPolicyData() {
+        mLoader = spy(new NetworkCycleDataTestLoader(mContext));
+        ReflectionHelpers.setField(mLoader, "mPolicy", mPolicy);
+
+        mLoader.loadInBackground();
+
+        verify(mLoader).loadPolicyData();
+    }
+
+    @Test
+    public void loadPolicyData_shouldRecordUsageFromPolicyCycle() {
+        final int networkType = ConnectivityManager.TYPE_MOBILE;
+        final String subId = "TestSubscriber";
+        final ZonedDateTime now = ZonedDateTime.now();
+        final Range<ZonedDateTime> cycle = new Range<>(now, now);
+        final long nowInMs = now.toInstant().toEpochMilli();
+        // mock 1 cycle data.
+        // hasNext() will be called internally in next(), hence setting it to return true twice.
+        when(mIterator.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false);
+        when(mIterator.next()).thenReturn(cycle);
+        mLoader = spy(new NetworkCycleDataTestLoader(mContext));
+        ReflectionHelpers.setField(mLoader, "mPolicy", mPolicy);
+        ReflectionHelpers.setField(mLoader, "mNetworkType", networkType);
+        ReflectionHelpers.setField(mLoader, "mSubId", subId);
+
+        mLoader.loadPolicyData();
+
+        verify(mLoader).recordUsage(nowInMs, nowInMs);
+    }
+
+    @Test
+    public void loadFourWeeksData_shouldRecordUsageForLast4Weeks() throws RemoteException {
+        mLoader = spy(new NetworkCycleDataTestLoader(mContext));
+        ReflectionHelpers.setField(mLoader, "mNetworkStatsService", mNetworkStatsService);
+        final INetworkStatsSession networkSession = mock(INetworkStatsSession.class);
+        when(mNetworkStatsService.openSession()).thenReturn(networkSession);
+        final NetworkStatsHistory networkHistory = mock(NetworkStatsHistory.class);
+        when(networkSession.getHistoryForNetwork(nullable(NetworkTemplate.class), anyInt()))
+            .thenReturn(networkHistory);
+        final long now = System.currentTimeMillis();
+        final long fourWeeksAgo = now - (DateUtils.WEEK_IN_MILLIS * 4);
+        when(networkHistory.getStart()).thenReturn(fourWeeksAgo);
+        when(networkHistory.getEnd()).thenReturn(now);
+
+        mLoader.loadFourWeeksData();
+
+        verify(mLoader).recordUsage(fourWeeksAgo, now);
+    }
+
+    public class NetworkCycleDataTestLoader extends NetworkCycleDataLoader<List<NetworkCycleData>> {
+
+        private NetworkCycleDataTestLoader(Context context) {
+            super(NetworkCycleDataLoader.builder(mContext));
+            mContext = context;
+        }
+
+        @Override
+        void recordUsage(long start, long end) {
+        }
+
+        @Override
+        List<NetworkCycleData> getCycleUsage() {
+            return null;
+        }
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/FragmentTestUtils.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/FragmentTestUtils.java
deleted file mode 100644
index d8e73b7..0000000
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/FragmentTestUtils.java
+++ /dev/null
@@ -1,74 +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.settingslib.testutils;
-
-import android.os.Bundle;
-import android.widget.LinearLayout;
-
-import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentActivity;
-import androidx.fragment.app.FragmentManager;
-
-import org.robolectric.Robolectric;
-
-/**
- * Utilities for creating Fragments for testing.
- * <p>
- * TODO(b/111195449) - Duplicated from org.robolectric.shadows.support.v4.SupportFragmentTestUtil
- */
-@Deprecated
-public class FragmentTestUtils {
-
-    public static void startFragment(Fragment fragment) {
-        buildFragmentManager(FragmentUtilActivity.class)
-                .beginTransaction().add(fragment, null).commit();
-    }
-
-    public static void startFragment(Fragment fragment,
-            Class<? extends FragmentActivity> activityClass) {
-        buildFragmentManager(activityClass)
-                .beginTransaction().add(fragment, null).commit();
-    }
-
-    public static void startVisibleFragment(Fragment fragment) {
-        buildFragmentManager(FragmentUtilActivity.class)
-                .beginTransaction().add(1, fragment, null).commit();
-    }
-
-    public static void startVisibleFragment(Fragment fragment,
-            Class<? extends FragmentActivity> activityClass, int containerViewId) {
-        buildFragmentManager(activityClass)
-                .beginTransaction().add(containerViewId, fragment, null).commit();
-    }
-
-    private static FragmentManager buildFragmentManager(
-            Class<? extends FragmentActivity> activityClass) {
-        FragmentActivity activity = Robolectric.setupActivity(activityClass);
-        return activity.getSupportFragmentManager();
-    }
-
-    private static class FragmentUtilActivity extends FragmentActivity {
-        @Override
-        protected void onCreate(Bundle savedInstanceState) {
-            super.onCreate(savedInstanceState);
-            LinearLayout view = new LinearLayout(this);
-            view.setId(1);
-
-            setContentView(view);
-        }
-    }
-}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/apppreference/AppPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/apppreference/AppPreferenceTest.java
new file mode 100644
index 0000000..10c9dfb
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/apppreference/AppPreferenceTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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.settingslib.widget.apppreference;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.view.View;
+
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+public class AppPreferenceTest {
+
+    private Context mContext;
+    private View mRootView;
+    private AppPreference mPref;
+    private PreferenceViewHolder mHolder;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mRootView = View.inflate(mContext, R.layout.preference_app, null /* parent */);
+        mHolder = PreferenceViewHolder.createInstanceForTests(mRootView);
+        mPref = new AppPreference(mContext);
+    }
+
+    @Test
+    public void setProgress_showProgress() {
+        mPref.setProgress(1);
+        mPref.onBindViewHolder(mHolder);
+
+        assertThat(mHolder.findViewById(android.R.id.progress).getVisibility())
+                .isEqualTo(View.VISIBLE);
+    }
+
+    @Test
+    public void setSummary_showSummaryContainer() {
+        mPref.setSummary("test");
+        mPref.onBindViewHolder(mHolder);
+
+        assertThat(mHolder.findViewById(R.id.summary_container).getVisibility())
+                .isEqualTo(View.VISIBLE);
+    }
+
+    @Test
+    public void noSummary_hideSummaryContainer() {
+        mPref.setSummary(null);
+        mPref.onBindViewHolder(mHolder);
+
+        assertThat(mHolder.findViewById(R.id.summary_container).getVisibility())
+                .isEqualTo(View.GONE);
+    }
+
+    @Test
+    public void foobar_testName() {
+        float iconSize = mContext.getResources().getDimension(R.dimen.secondary_app_icon_size);
+        assertThat(Float.floatToIntBits(iconSize)).isEqualTo(Float.floatToIntBits(32));
+    }
+}
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index c53417b..de86789 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -55,7 +55,7 @@
     <bool name="def_networks_available_notification_on">true</bool>
 
     <bool name="def_backup_enabled">false</bool>
-    <string name="def_backup_transport" translatable="false">android/com.android.internal.backup.LocalTransport</string>
+    <string name="def_backup_transport" translatable="false">com.android.localtransport/.LocalTransport</string>
 
     <!-- Default value for whether or not to pulse the notification LED when there is a
          pending notification -->
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index bd21b83..c09b763 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -659,6 +659,9 @@
         dumpSetting(s, p,
                 Settings.Global.GPU_DEBUG_LAYERS,
                 GlobalSettingsProto.Gpu.DEBUG_LAYERS);
+        dumpSetting(s, p,
+                Settings.Global.ANGLE_ENABLED_APP,
+                GlobalSettingsProto.Gpu.ANGLE_ENABLED_APP);
         p.end(gpuToken);
 
         final long hdmiToken = p.start(GlobalSettingsProto.HDMI);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 63978ba..18ec9c3 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -870,7 +870,11 @@
                 }
             }
             if (newRestrictions.getBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES)
-                    != prevRestrictions.getBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES)) {
+                    != prevRestrictions.getBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES) ||
+                    newRestrictions.getBoolean(
+                            UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY)
+                    != prevRestrictions.getBoolean(
+                            UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY)) {
                 final long identity = Binder.clearCallingIdentity();
                 try {
                     synchronized (mLock) {
@@ -3285,8 +3289,8 @@
                 if (currentVersion == 133) {
                     // Version 133: Add default end button behavior
                     final SettingsState systemSettings = getSystemSettingsLocked(userId);
-                    if (systemSettings.getSettingLocked(Settings.System.END_BUTTON_BEHAVIOR) ==
-                            null) {
+                    if (systemSettings.getSettingLocked(Settings.System.END_BUTTON_BEHAVIOR)
+                            .isNull()) {
                         String defaultEndButtonBehavior = Integer.toString(getContext()
                                 .getResources().getInteger(R.integer.def_end_button_behavior));
                         systemSettings.insertSettingLocked(Settings.System.END_BUTTON_BEHAVIOR,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index da870bd..5c654b4 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -151,6 +151,7 @@
 
     <uses-permission android:name="android.permission.CONTROL_KEYGUARD" />
     <uses-permission android:name="android.permission.SUSPEND_APPS" />
+    <uses-permission android:name="android.permission.READ_CLIPBOARD_IN_BACKGROUND" />
 
     <application android:label="@string/app_label"
                  android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index ec35b3d..2530abc 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -44,6 +44,7 @@
 
 import libcore.io.Streams;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.ChooserActivity;
 import com.android.internal.logging.MetricsLogger;
@@ -234,6 +235,7 @@
      */
     private boolean mTakingScreenshot;
 
+    @GuardedBy("sNotificationBundle")
     private static final Bundle sNotificationBundle = new Bundle();
 
     private boolean mIsWatch;
@@ -1059,10 +1061,12 @@
     }
 
     private static Notification.Builder newBaseNotification(Context context) {
-        if (sNotificationBundle.isEmpty()) {
-            // Rename notifcations from "Shell" to "Android System"
-            sNotificationBundle.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
-                    context.getString(com.android.internal.R.string.android_system_label));
+        synchronized (sNotificationBundle) {
+            if (sNotificationBundle.isEmpty()) {
+                // Rename notifcations from "Shell" to "Android System"
+                sNotificationBundle.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
+                        context.getString(com.android.internal.R.string.android_system_label));
+            }
         }
         return new Notification.Builder(context, NOTIFICATION_CHANNEL_ID)
                 .addExtras(sNotificationBundle)
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 aa2fb32..814324e 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
@@ -20,6 +20,7 @@
 
 import com.android.systemui.plugins.Plugin;
 import com.android.systemui.plugins.annotations.ProvidesInterface;
+import java.io.PrintWriter;
 
 @ProvidesInterface(action = NavGesture.ACTION, version = NavGesture.VERSION)
 public interface NavGesture extends Plugin {
@@ -46,6 +47,8 @@
         public void onNavigationButtonLongPress(View v);
 
         public default void destroy() { }
+
+        public default void dump(PrintWriter pw) { }
     }
 
 }
diff --git a/packages/SystemUI/res-keyguard/values-am/strings.xml b/packages/SystemUI/res-keyguard/values-am/strings.xml
index c892ac3..b64e0cf 100644
--- a/packages/SystemUI/res-keyguard/values-am/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-am/strings.xml
@@ -22,8 +22,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_name" msgid="3171996292755059205">"የቁልፍ ጥበቃ"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3420548423949593123">"ፒን ኮድ ይተይቡ"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="670683628782925409">"የሲም ፒዩኬ እና አዲሱን ፒን ኮድ ይተይቡ"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3747778500166059332">"የሲም ፒዩኬ ኮድ"</string>
+    <string name="keyguard_password_enter_puk_code" msgid="670683628782925409">"የሲም PUK እና አዲሱን ፒን ኮድ ይተይቡ"</string>
+    <string name="keyguard_password_enter_puk_prompt" msgid="3747778500166059332">"የሲም PUK ኮድ"</string>
     <string name="keyguard_password_enter_pin_prompt" msgid="8188243197504453830">"አዲስ የሲም ፒን  ኮድ"</string>
     <string name="keyguard_password_entry_touch_hint" msgid="5790410752696806482"><font size="17">"የይለፍ ቃል ለመተየብ ይንኩ"</font></string>
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"ለመክፈት የይለፍ ቃል ይተይቡ"</string>
@@ -48,12 +48,12 @@
     <string name="keyguard_permanent_disabled_sim_message_short" msgid="654102080186420706">"የማይሰራ ሲም ካርድ።"</string>
     <string name="keyguard_permanent_disabled_sim_instructions" msgid="4683178224791318347">"ሲም ካርድዎ እስከመጨረሻው ተሰናክሏል።\n ሌላ ሲም ካርድ ለማግኘት ከገመድ አልባ አገልግሎት አቅራቢዎ ጋር ይገናኙ።"</string>
     <string name="keyguard_sim_locked_message" msgid="953766009432168127">"ሲም ካርድ ተዘግቷል።"</string>
-    <string name="keyguard_sim_puk_locked_message" msgid="1772789643694942073">"ሲም ካርድ በፒዩኬ ተቆልፏል።"</string>
+    <string name="keyguard_sim_puk_locked_message" msgid="1772789643694942073">"ሲም ካርድ በPUK ተቆልፏል።"</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="3586601150825821675">"ሲም ካርድን በመክፈት ላይ..."</string>
     <string name="keyguard_accessibility_pin_area" msgid="703175752097279029">"የፒን አካባቢ"</string>
     <string name="keyguard_accessibility_password" msgid="7695303207740941101">"የመሣሪያ ይለፍ ቃል"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="912702510825058921">"የሲም ፒን አካባቢ"</string>
-    <string name="keyguard_accessibility_sim_puk_area" msgid="136979425761438705">"የሲም ፒዩኬ አካባቢ"</string>
+    <string name="keyguard_accessibility_sim_puk_area" msgid="136979425761438705">"የሲም PUK አካባቢ"</string>
     <string name="keyguard_accessibility_next_alarm" msgid="5835196989158584991">"ቀጣዩ ማንቂያ ለ<xliff:g id="ALARM">%1$s</xliff:g> ተዘጋጅቷል"</string>
     <string name="keyboardview_keycode_delete" msgid="6883116827512721630">"ሰርዝ"</string>
     <string name="disable_carrier_button_text" msgid="6914341927421916114">"eSIMን አሰናክል"</string>
@@ -74,14 +74,14 @@
     <string name="kg_sim_lock_esim_instructions" msgid="4416732549172148542">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> መሣሪያን ያለሞባይል አገልግሎት ለመጠቀም eSIMን ያሰናክሉ።"</string>
     <string name="kg_pin_instructions" msgid="4069609316644030034">"ፒን ያስገቡ"</string>
     <string name="kg_password_instructions" msgid="136952397352976538">"የይለፍ ቃል ያስገቡ"</string>
-    <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"ሲም አሁን ተሰናክሏል። ለመቀጠል የፒዩኬ ኮድ ያስገቡ። ለዝርዝር አገልግሎት አቅራቢን ያግኙ።"</string>
-    <string name="kg_puk_enter_puk_hint_multi" msgid="1373131883510840794">"ሲም «<xliff:g id="CARRIER">%1$s</xliff:g>» አሁን ተሰናክሏል። ለመቀጠል የፒዩኬ ኮድ ያስገቡ። ዝርዝር መረጃን ለማግኘት የተንቀሳቃሽ ስልክ አገልግሎት አቅራቢውን ያነጋግሩ።"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"ሲም አሁን ተሰናክሏል። ለመቀጠል የPUK ኮድ ያስገቡ። ለዝርዝር አገልግሎት አቅራቢን ያግኙ።"</string>
+    <string name="kg_puk_enter_puk_hint_multi" msgid="1373131883510840794">"ሲም «<xliff:g id="CARRIER">%1$s</xliff:g>» አሁን ተሰናክሏል። ለመቀጠል የPUK ኮድ ያስገቡ። ዝርዝር መረጃን ለማግኘት የተንቀሳቃሽ ስልክ አገልግሎት አቅራቢውን ያነጋግሩ።"</string>
     <string name="kg_puk_enter_pin_hint" msgid="3137789674920391087">"የተፈለገውን የፒን ኮድ ያስገቡ"</string>
     <string name="kg_enter_confirm_pin_hint" msgid="3089485999116759671">"የተፈለገውን ፒን ኮድ ያረጋግጡ"</string>
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4471738151810900114">"ሲም ካርድን በመክፈት ላይ..."</string>
     <string name="kg_invalid_sim_pin_hint" msgid="3057533256729513335">"ከ4 እስከ 8 ቁጥሮች የያዘ ፒን ይተይቡ።"</string>
-    <string name="kg_invalid_sim_puk_hint" msgid="6003602401368264144">"የፒዩኬ ኮድ 8 ወይም ከዚያ በላይ ቁጥሮች ሊኖረው ይገባል።"</string>
-    <string name="kg_invalid_puk" msgid="5399287873762592502">"ትክክለኛውን የፒዩኬ ኮድ እንደገና ያስገቡ። ተደጋጋሚ ሙከራዎች ሲሙን እስከመጨረሻው ያሰናክሉታል።"</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="6003602401368264144">"የPUK ኮድ 8 ወይም ከዚያ በላይ ቁጥሮች ሊኖረው ይገባል።"</string>
+    <string name="kg_invalid_puk" msgid="5399287873762592502">"ትክክለኛውን የPUK ኮድ እንደገና ያስገቡ። ተደጋጋሚ ሙከራዎች ሲሙን እስከመጨረሻው ያሰናክሉታል።"</string>
     <string name="kg_invalid_confirm_pin_hint" product="default" msgid="5672736555427444330">"ፒን ኮዶቹ አይገጣጠሙም"</string>
     <string name="kg_login_too_many_attempts" msgid="6604574268387867255">"በጣም ብዙ የስርዓተ ጥለት ሙከራዎች"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8637788033282252027">"ፒንዎን <xliff:g id="NUMBER_0">%1$d</xliff:g> ጊዜ በትክክል አልተየቡም። \n\nበ<xliff:g id="NUMBER_1">%2$d</xliff:g> ሰኮንዶች ውስጥ እንደገና ይሞክሩ።"</string>
@@ -112,7 +112,7 @@
       <item quantity="other">ልክ ያልሆነ የሲም ፒዩኬ ኮድ፣ ሲሙ እስከመጨረሻው የማይሰራ ከመሆኑ በፊት <xliff:g id="NUMBER_1">%d</xliff:g> ሙከራዎች ይቀረዎታል።</item>
     </plurals>
     <string name="kg_password_pin_failed" msgid="8769990811451236223">"የሲም ፒን ክወና አልተሳካም!"</string>
-    <string name="kg_password_puk_failed" msgid="1331621440873439974">"የሲም ፒዩኬ ክወና አልተሳካም!"</string>
+    <string name="kg_password_puk_failed" msgid="1331621440873439974">"የሲም PUK ክወና አልተሳካም!"</string>
     <string name="kg_pin_accepted" msgid="7637293533973802143">"ኮዱ ተቀባይነት አግኝቷል!"</string>
     <string name="keyguard_carrier_default" msgid="4274828292998453695">"ከአገልግሎት መስጫ ክልል ውጪ።"</string>
     <string name="accessibility_ime_switch_button" msgid="2695096475319405612">"የግቤት ስልት ቀይር"</string>
diff --git a/packages/SystemUI/res-keyguard/values-da/strings.xml b/packages/SystemUI/res-keyguard/values-da/strings.xml
index b3b9732..50dc26b 100644
--- a/packages/SystemUI/res-keyguard/values-da/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-da/strings.xml
@@ -117,13 +117,13 @@
     <string name="keyguard_carrier_default" msgid="4274828292998453695">"Ingen dækning."</string>
     <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">"Der skal angives et mønster efter genstart af enheden"</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_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">"Der skal angives et mønster, når du skifter profil"</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_device_admin" msgid="3452168247888906179">"Enheden er blevet låst af administratoren"</string>
diff --git a/packages/SystemUI/res-keyguard/values-fr/strings.xml b/packages/SystemUI/res-keyguard/values-fr/strings.xml
index d5e36ce..f0c7e92 100644
--- a/packages/SystemUI/res-keyguard/values-fr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fr/strings.xml
@@ -34,9 +34,9 @@
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Le code est incorrect."</string>
     <string name="keyguard_sim_error_message_short" msgid="592109500618448312">"Carte non valide."</string>
     <string name="keyguard_charged" msgid="3316115607283493413">"Complètement chargée"</string>
-    <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Rechargement…"</string>
-    <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Rechargement rapide…"</string>
-    <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Rechargement lent…"</string>
+    <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge…"</string>
+    <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge rapide…"</string>
+    <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge lente…"</string>
     <string name="keyguard_low_battery" msgid="9218432555787624490">"Branchez votre chargeur."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8566679946700751371">"Appuyez sur \"Menu\" pour déverrouiller le clavier."</string>
     <string name="keyguard_network_locked_message" msgid="6743537524631420759">"Réseau verrouillé"</string>
diff --git a/packages/SystemUI/res/layout/qs_detail_buttons.xml b/packages/SystemUI/res/layout/qs_detail_buttons.xml
index 03ed62b..75f43f9 100644
--- a/packages/SystemUI/res/layout/qs_detail_buttons.xml
+++ b/packages/SystemUI/res/layout/qs_detail_buttons.xml
@@ -26,6 +26,7 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginEnd="8dp"
+        android:minHeight="48dp"
         android:minWidth="132dp"
         android:textAppearance="@style/TextAppearance.QS.DetailButton"
         android:focusable="true" />
@@ -35,6 +36,7 @@
         style="@style/QSBorderlessButton"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:minHeight="48dp"
         android:minWidth="88dp"
         android:textAppearance="@style/TextAppearance.QS.DetailButton"
         android:focusable="true"/>
diff --git a/packages/SystemUI/res/layout/qs_paged_tile_layout.xml b/packages/SystemUI/res/layout/qs_paged_tile_layout.xml
index 11a0187..7083269 100644
--- a/packages/SystemUI/res/layout/qs_paged_tile_layout.xml
+++ b/packages/SystemUI/res/layout/qs_paged_tile_layout.xml
@@ -20,10 +20,13 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:layout_weight="1"
-    android:clipChildren="false"
-    android:clipToPadding="false"
+    android:clipChildren="true"
+    android:clipToPadding="true"
+    android:paddingStart="@dimen/notification_side_paddings"
+    android:paddingEnd="@dimen/notification_side_paddings"
     android:paddingBottom="@dimen/qs_paged_tile_layout_padding_bottom">
 
+
     <FrameLayout
         android:id="@+id/page_decor"
         android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 44691c2..157934f 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"maak kamera oop"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Kies nuwe taakuitleg"</string>
     <string name="cancel" msgid="6442560571259935130">"Kanselleer"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Hulpboodskapgebied"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Bevestig"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Raak die vingerafdruksensor"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Vingerafdrukikoon"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Programikoon"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Hulpboodskapgebied"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Soek tans vir jou …"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Gesig-ikoon"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Versoenbaarheid-zoem se knoppie."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoem kleiner na groter skerm."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth gekoppel."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Berging"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Wenke"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Kitsprogramme"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Kitsprogramme hoef nie geïnstalleer te word nie."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> loop tans"</string>
+    <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="2650669128861626071">"Gaan na blaaier"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Gaan na web"</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>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 966e4d7..492fa8c 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"ካሜራ ክፈት"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"የአዲስ ተግባር አቀማመጥን ይምረጡ"</string>
     <string name="cancel" msgid="6442560571259935130">"ይቅር"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"የእገዛ መልዕክት አካባቢ"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"አረጋግጥ"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"የጣት አሻራ ዳሳሹን ይንኩ"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"የጣት አሻራ አዶ"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"የመተግበሪያ አዶ"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"የእገዛ መልዕክት አካባቢ"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"እርስዎን በመፈለግ ላይ…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"የፊት አዶ"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"የተኳኋኝአጉላ አዝራር።"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"አነስተኛውን ማያ ወደ ትልቅ አጉላ።"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ብሉቱዝ ተያይዟል።"</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"ማከማቻ"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"ፍንጮች"</string>
     <string name="instant_apps" msgid="6647570248119804907">"የቅጽበት መተግበሪያዎች"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"ቅጽበታዊ መተግበሪያዎች መጫን አያስፈልጋቸውም።"</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> አሂድ"</string>
+    <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="2650669128861626071">"ወደ አሳሽ ሂድ"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"ወደ ድር ሂድ"</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>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 278b00a..fe27bb7 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -107,10 +107,12 @@
     <string name="camera_label" msgid="7261107956054836961">"فتح الكاميرا"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"تحديد تنسيق جديد للمهمة"</string>
     <string name="cancel" msgid="6442560571259935130">"إلغاء"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"منطقة رسالة المساعدة"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"تأكيد"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"المس جهاز استشعار بصمات الإصبع"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"رمز بصمة الإصبع"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"رمز التطبيق"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"منطقة رسالة المساعدة"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"جارٍ البحث عن وجهك…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"رمز الوجه"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"زر تكبير/تصغير للتوافق."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"استخدام التكبير/التصغير لتحويل شاشة صغيرة إلى شاشة أكبر"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"تم توصيل البلوتوث."</string>
@@ -847,9 +849,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"سعة التخزين"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"تلميحات"</string>
     <string name="instant_apps" msgid="6647570248119804907">"التطبيقات الفورية"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"لا تتطلب التطبيقات الفورية إجراء التثبيت."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"التطبيق <xliff:g id="APP">%1$s</xliff:g> قيد التشغيل"</string>
+    <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="2650669128861626071">"الانتقال إلى المتصفح"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"الانتقال إلى الويب"</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>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 8912f15..8cde524 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"কেমেৰা খোলক"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"নতুন কাৰ্যৰ চানেকি বাছনি কৰক"</string>
     <string name="cancel" msgid="6442560571259935130">"বাতিল কৰক"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"সহায় বাৰ্তাৰ ক্ষেত্ৰ"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"নিশ্চিত কৰক"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"ফিংগাৰপ্ৰিণ্ট ছেন্সৰটো স্পৰ্শ কৰক"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ফিংগাৰপ্ৰিণ্ট আইকন"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"এপ্লিকেশ্বন আইকন"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"সহায় বাৰ্তাৰ ক্ষেত্ৰ"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"আপোনাৰ মুখমণ্ডল বিচাৰি আছে…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"মুখমণ্ডলৰ আইকন"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"উপযোগিতা অনুসৰি জুম কৰা বুটাম।"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"স্ক্ৰীণৰ আকাৰ ডাঙৰ কৰিবলৈ জুম কৰক।"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ব্লুটুথ সংযোগ হ\'ল।"</string>
@@ -344,7 +346,7 @@
     <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> সীমা"</string>
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> সকীয়নি"</string>
     <string name="quick_settings_work_mode_label" msgid="7608026833638817218">"কৰ্মস্থানৰ প্ৰ\'ফাইল"</string>
-    <string name="quick_settings_night_display_label" msgid="3577098011487644395">"ৰাতিৰ লাইট"</string>
+    <string name="quick_settings_night_display_label" msgid="3577098011487644395">"ৰাতিৰ পোহৰ"</string>
     <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"সূৰ্যাস্তত অন কৰক"</string>
     <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>
@@ -823,9 +825,14 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"সঞ্চয়াগাৰ"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"ইংগিতবোৰ"</string>
     <string name="instant_apps" msgid="6647570248119804907">"তাৎক্ষণিক এপসমূহ"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"তাৎক্ষণিক এপসমূহক ইনষ্টল কৰাৰ প্ৰয়োজন নাই।"</string>
+    <!-- no translation found for instant_apps_title (8738419517367449783) -->
+    <skip />
+    <!-- no translation found for instant_apps_message (1183313016396018086) -->
+    <skip />
+    <!-- no translation found for instant_apps_message_with_help (6179830437630729747) -->
+    <skip />
     <string name="app_info" msgid="6856026610594615344">"এপ্ সম্পৰ্কীয় তথ্য"</string>
-    <string name="go_to_web" msgid="2650669128861626071">"ব্ৰাউজাৰলৈ যাওক"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"ৱেবলৈ যাওক"</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>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index f0779fb..2342a89 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"kemaranı açın"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Yeni tapşırıq sxemi seçin"</string>
     <string name="cancel" msgid="6442560571259935130">"Ləğv et"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Yardım mesajı bölməsi"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Təsdiq"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Barmaq izi sensoruna klikləyin"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Barmaq izi ikonası"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Tətbiq ikonası"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Yardım mesajı bölməsi"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Siz axtarılırsınız…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Üz işarəsi"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Uyğunluq zoom düyməsi."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Daha böyük ekranda uzaqlaşdır."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth qoşulub."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Yaddaş"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Məsləhətlər"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Ani Tətbiqlər"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Ani tətbiqlər quraşdırma tələb etmir."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> işləyir"</string>
+    <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="2650669128861626071">"Brauzerə daxil edin"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Vebə keçin"</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>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 9dc6460..47422b2 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -104,10 +104,12 @@
     <string name="camera_label" msgid="7261107956054836961">"otvori kameru"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Izaberi novi raspored zadataka"</string>
     <string name="cancel" msgid="6442560571259935130">"Otkaži"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Oblast poruke za pomoć"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Potvrdi"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Dodirnite senzor za otisak prsta"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikona otiska prsta"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Ikona aplikacije"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Oblast poruke za pomoć"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Tražimo vas…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Ikona lica"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Dugme Zum kompatibilnosti."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zumiranje sa manjeg na veći ekran."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth je priključen."</string>
@@ -829,9 +831,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Memorijski prostor"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Saveti"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Instant aplikacije"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Instant aplikacije ne zahtevaju instalaciju."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"Aplikacija <xliff:g id="APP">%1$s</xliff:g> je pokrenuta"</string>
+    <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="2650669128861626071">"Idi na pregledač"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Idi na veb"</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>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 9898dbd..de01516 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -105,10 +105,12 @@
     <string name="camera_label" msgid="7261107956054836961">"адкрыць камеру"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Выберыце новы макет заданняў"</string>
     <string name="cancel" msgid="6442560571259935130">"Скасаваць"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Поле даведачнага паведамлення"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Пацвердзіць"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Дакраніцеся да сканера адбіткаў пальцаў"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Значок адбіткаў пальцаў"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Значок праграмы"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Вобласць даведачнага паведамлення"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Ідзе пошук вашага твару…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Значок твару"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Кнопка сумяшчальнасці маштаба."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Маштабаванне малых элементаў для большага экрана."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth-сувязь."</string>
@@ -837,9 +839,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Захоўванне"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Падказкі"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Імгненныя праграмы"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Імгненныя праграмы не патрабуюць усталёўкі."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"Праграма \"<xliff:g id="APP">%1$s</xliff:g>\" запушчана"</string>
+    <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="2650669128861626071">"Перайсці ў браўзер"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Перайсці ў інтэрнэт"</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>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index a5506a3..29d89ec 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"отваряне на камерата"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Избиране на ново оформление за задачите"</string>
     <string name="cancel" msgid="6442560571259935130">"Отказ"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Област за помощно съобщение"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Потвърждаване"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Докоснете сензора за отпечатъци"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Икона за отпечатък"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Икона на приложението"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Област за помощно съобщение"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Търсим ви…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Икона на лице"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Бутон за промяна на мащаба с цел съвместимост."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Промяна на мащаба на екрана от по-малък до по-голям."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth е включен."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Хранилище"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Съвети"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Мигновени приложения"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"За мигновените приложения не се изисква инсталиране."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> работи"</string>
+    <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="2650669128861626071">"Към браузъра"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Към мрежата"</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>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 5d52103..d2f6401 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -31,7 +31,7 @@
     </plurals>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"কোনো বিজ্ঞপ্তি নেই"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"চলতে-থাকা"</string>
-    <string name="status_bar_latest_events_title" msgid="6594767438577593172">"বিজ্ঞপ্তিগুলি"</string>
+    <string name="status_bar_latest_events_title" msgid="6594767438577593172">"বিজ্ঞপ্তি"</string>
     <string name="battery_low_title" msgid="9187898087363540349">"চার্জ শীঘ্রই শেষ হয়ে যেতে পারে"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> অবশিষ্ট আছে"</string>
     <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> বাকি আছে, বর্তমান ব্যবহারের ভিত্তিতে আর <xliff:g id="TIME">%2$s</xliff:g> চলবে"</string>
@@ -49,7 +49,7 @@
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"অটো-রোটেট স্ক্রিন"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"মিউট করুন"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"স্বতঃ"</string>
-    <string name="status_bar_settings_notifications" msgid="397146176280905137">"বিজ্ঞপ্তিগুলি"</string>
+    <string name="status_bar_settings_notifications" msgid="397146176280905137">"বিজ্ঞপ্তি"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"ব্লুটুথ টিথার করা হয়েছে"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ইনপুট পদ্ধতিগুলি সেট আপ করুন"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"ফিজিক্যাল কীবোর্ড"</string>
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"ক্যামেরা খুলুন"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"নতুন কার্য লেআউট বেছে নিন"</string>
     <string name="cancel" msgid="6442560571259935130">"বাতিল করুন"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"সহায়তার মেসেজ দেখানোর জায়গা"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"কনফার্ম করুন"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"আঙ্গুলের ছাপের সেন্সর স্পর্শ করুন"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"আঙ্গুলের ছাপের আইকন"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"অ্যাপ্লিকেশনের আইকন"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"সহায়তার মেসেজ দেখানোর জায়গা"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"আপনার জন্য খোঁজা হচ্ছে…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"ফেস আইকন"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"সামঞ্জস্যের জুম বোতাম৷"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ছোট থেকে বৃহৎ স্ক্রীণে জুম করুন৷"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ব্লুটুথ সংযুক্ত হয়েছে৷"</string>
@@ -174,7 +176,7 @@
     <string name="accessibility_battery_level" msgid="7451474187113371965">"<xliff:g id="NUMBER">%d</xliff:g> শতাংশ ব্যাটারি রয়েছে৷"</string>
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"ব্যাটারি চার্জ হচ্ছে, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> শতাংশ৷"</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"সিস্টেম সেটিংস৷"</string>
-    <string name="accessibility_notifications_button" msgid="4498000369779421892">"বিজ্ঞপ্তিগুলি৷"</string>
+    <string name="accessibility_notifications_button" msgid="4498000369779421892">"বিজ্ঞপ্তি৷"</string>
     <string name="accessibility_overflow_action" msgid="5681882033274783311">"সমস্ত বিজ্ঞপ্তি দেখুন"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"বিজ্ঞপ্তি সাফ করুন৷"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS সক্ষম করা হয়েছে৷"</string>
@@ -334,7 +336,7 @@
       <item quantity="one">%dটি ডিভাইস</item>
       <item quantity="other">%dটি ডিভাইস</item>
     </plurals>
-    <string name="quick_settings_notifications_label" msgid="4818156442169154523">"বিজ্ঞপ্তিগুলি"</string>
+    <string name="quick_settings_notifications_label" msgid="4818156442169154523">"বিজ্ঞপ্তি"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ফ্ল্যাশলাইট"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"মোবাইল ডেটা"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"ডেটার ব্যবহার"</string>
@@ -576,7 +578,7 @@
     <string name="broadcast_tile" msgid="3894036511763289383">"সম্প্রচার টাইল"</string>
     <string name="zen_alarm_warning_indef" msgid="3482966345578319605">"তার আগে আপনি এটিকে বন্ধ না করা পর্যন্ত আপনি পরবর্তী <xliff:g id="WHEN">%1$s</xliff:g> অ্যালার্ম শুনতে পাবেন না"</string>
     <string name="zen_alarm_warning" msgid="444533119582244293">"আপনি আপনার পরবর্তী <xliff:g id="WHEN">%1$s</xliff:g> অ্যালার্ম শুনতে পাবেন না"</string>
-    <string name="alarm_template" msgid="3980063409350522735">"<xliff:g id="WHEN">%1$s</xliff:g> -টায়"</string>
+    <string name="alarm_template" msgid="3980063409350522735">"<xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="alarm_template_far" msgid="4242179982586714810">"<xliff:g id="WHEN">%1$s</xliff:g> -তে"</string>
     <string name="accessibility_quick_settings_detail" msgid="2579369091672902101">"দ্রুত সেটিংস, <xliff:g id="TITLE">%s</xliff:g>৷"</string>
     <string name="accessibility_status_bar_hotspot" msgid="4099381329956402865">"হটস্পট"</string>
@@ -679,7 +681,7 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"হোম"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"সাম্প্রতিকগুলি"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"পিছনে"</string>
-    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"বিজ্ঞপ্তিগুলি"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"বিজ্ঞপ্তি"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"কীবোর্ড শর্টকাট"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="8413348767825486492">"কীবোর্ড লে-আউট পাল্টান"</string>
     <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"অ্যাপ্লিকেশানগুলি"</string>
@@ -823,9 +825,14 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"স্টোরেজ"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"হিন্ট"</string>
     <string name="instant_apps" msgid="6647570248119804907">"ঝটপট অ্যাপ"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"ঝটপট অ্যাপ ইনস্টল করার প্রয়োজন হয় না।"</string>
+    <!-- no translation found for instant_apps_title (8738419517367449783) -->
+    <skip />
+    <!-- no translation found for instant_apps_message (1183313016396018086) -->
+    <skip />
+    <!-- no translation found for instant_apps_message_with_help (6179830437630729747) -->
+    <skip />
     <string name="app_info" msgid="6856026610594615344">"অ্যাপের তথ্য"</string>
-    <string name="go_to_web" msgid="2650669128861626071">"ব্রাউজারে যান"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"ওয়েবে যান"</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>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 4527e9a..ac0c05e 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -104,10 +104,12 @@
     <string name="camera_label" msgid="7261107956054836961">"otvori kameru"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Odaberite novi raspored zadataka"</string>
     <string name="cancel" msgid="6442560571259935130">"Otkaži"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Prostor za poruku za pomoć"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Potvrdite"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Dodirnite senzor za otisak prsta"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikona za otisak prsta"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Ikona aplikacije"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Prostor za poruku za pomoć"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Tražimo vas…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Ikona lica"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Dugme za uvećavanje u slučaju nekompatibilnosti."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Uvećani prikaz manjeg ekrana na većem ekranu."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth je povezan."</string>
@@ -831,9 +833,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Pohrana"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Savjeti"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Instant-aplikacije"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Za instant aplikacije nije potrebna instalacija"</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"Pokrenuta je aplikacija <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <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="2650669128861626071">"Idi na preglednik"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Idite na internet"</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>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 23754ea..b4a2f3b 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"obre la càmera"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Selecciona el disseny de la tasca nova"</string>
     <string name="cancel" msgid="6442560571259935130">"Cancel·la"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Àrea de missatge d\'ajuda"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Confirma"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Toca el sensor d\'empremtes digitals"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Icona d\'empremta digital"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Icona d\'aplicació"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Àrea de missatge d\'ajuda"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"S\'està cercant la teva cara…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Icona facial"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botó de zoom de compatibilitat."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Amplia menys com més gran sigui la pantalla."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth connectat."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Emmagatzematge"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Suggeriments"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Aplicacions instantànies"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"No cal instal·lar les aplicacions instantànies."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"S\'està executant <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <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="2650669128861626071">"Ves al navegador"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Ves al web"</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>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index e7583b5..6d4af4a 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -105,10 +105,12 @@
     <string name="camera_label" msgid="7261107956054836961">"spustit fotoaparát"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Vybrat nové rozvržení úkolů"</string>
     <string name="cancel" msgid="6442560571259935130">"Zrušit"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Oblast pro zprávu nápovědy"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Potvrdit"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Dotkněte se snímače otisků prstů"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikona otisku prstu"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Ikona aplikace"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Oblast pro zprávu nápovědy"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Hledáme vás…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Ikona obličeje"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Tlačítko úpravy velikosti z důvodu kompatibility"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zvětšit menší obrázek na větší obrazovku."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Rozhraní Bluetooth je připojeno."</string>
@@ -837,9 +839,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Úložiště"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Tipy"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Okamžité aplikace"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Okamžité aplikace není třeba instalovat."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"Aplikace <xliff:g id="APP">%1$s</xliff:g> je spuštěna"</string>
+    <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="2650669128861626071">"Přejít do prohlížeče"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Přejít na web"</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>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 31634a9..ade7db1 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"åbn kamera"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Vælg nyt opgavelayout"</string>
     <string name="cancel" msgid="6442560571259935130">"Annuller"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Område med hjælpemeddelelse"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Bekræft"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Sæt fingeren på fingeraftrykslæseren"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikon for fingeraftryk"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Appens ikon"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Område med hjælpemeddelelse"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Forsøger at finde dig…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Ansigt"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Knap for kompatibilitetszoom."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom mindre til større skærm."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth tilsluttet."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Lagerplads"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Tips"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Instant apps kræver ingen installation."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> kører"</string>
+    <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="2650669128861626071">"Gå til en browser"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Gå til website"</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>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index aa6e449..06aac5c 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"Kamera öffnen"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Neues Aufgabenlayout auswählen"</string>
     <string name="cancel" msgid="6442560571259935130">"Abbrechen"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Bereich für die Hilfemeldung"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Bestätigen"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Berühre den Fingerabdrucksensor"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Fingerabdruck-Symbol"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"App-Symbol"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Bereich für die Hilfemeldung"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Wir suchen nach dir…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Gesichtssymbol"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Schaltfläche für Kompatibilitätszoom"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom auf einen größeren Bildschirm"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Mit Bluetooth verbunden"</string>
@@ -448,9 +450,9 @@
     <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Benachrichtigungen durch \"Bitte nicht stören\" pausiert"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"Jetzt starten"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"Keine Benachrichtigungen"</string>
-    <string name="profile_owned_footer" msgid="8021888108553696069">"Profil wird möglicherweise überwacht."</string>
-    <string name="vpn_footer" msgid="2388611096129106812">"Das Netzwerk wird möglicherweise überwacht."</string>
-    <string name="branded_vpn_footer" msgid="2168111859226496230">"Das Netzwerk wird möglicherweise überwacht"</string>
+    <string name="profile_owned_footer" msgid="8021888108553696069">"Profil wird eventuell überwacht."</string>
+    <string name="vpn_footer" msgid="2388611096129106812">"Das Netzwerk wird eventuell überwacht."</string>
+    <string name="branded_vpn_footer" msgid="2168111859226496230">"Das Netzwerk wird eventuell überwacht"</string>
     <string name="quick_settings_disclosure_management_monitoring" msgid="6645176135063957394">"Deine Organisation verwaltet dieses Gerät und kann den Netzwerkverkehr überwachen"</string>
     <string name="quick_settings_disclosure_named_management_monitoring" msgid="370622174777570853">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> verwaltet dieses Gerät und kann den Netzwerkverkehr überwachen"</string>
     <string name="quick_settings_disclosure_management_named_vpn" msgid="1085137869053332307">"Das Gerät wird von deiner Organisation verwaltet und ist mit <xliff:g id="VPN_APP">%1$s</xliff:g> verbunden"</string>
@@ -461,7 +463,7 @@
     <string name="quick_settings_disclosure_named_management_vpns" msgid="7777821385318891527">"Das Gerät wird von <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> verwaltet und ist mit VPNs verbunden"</string>
     <string name="quick_settings_disclosure_managed_profile_monitoring" msgid="5125463987558278215">"Deine Organisation kann den Netzwerkverkehr in deinem Arbeitsprofil überwachen"</string>
     <string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8973606847896650284">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> kann den Netzwerkverkehr in deinem Arbeitsprofil überwachen"</string>
-    <string name="quick_settings_disclosure_monitoring" msgid="679658227269205728">"Das Netzwerk wird möglicherweise überwacht"</string>
+    <string name="quick_settings_disclosure_monitoring" msgid="679658227269205728">"Das Netzwerk wird eventuell überwacht"</string>
     <string name="quick_settings_disclosure_vpns" msgid="8170318392053156330">"Das Gerät ist mit VPNs verbunden"</string>
     <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="3494535754792751741">"Arbeitsprofil verbunden mit <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="4467456202486569906">"Das persönliche Profil ist mit <xliff:g id="VPN_APP">%1$s</xliff:g> verbunden"</string>
@@ -827,9 +829,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Speicher"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Hinweise"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Instant-Apps"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Bei Instant-Apps ist keine vorherige Installation erforderlich."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> wird ausgeführt"</string>
+    <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="2650669128861626071">"Browser öffnen"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Web aufrufen"</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>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 1a1c762..1892da6 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"άνοιγμα φωτογραφικής μηχανής"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Επιλέξτε τη νέα διάταξη εργασίας"</string>
     <string name="cancel" msgid="6442560571259935130">"Ακύρωση"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Περιοχή μηνυμάτων βοήθειας"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Επιβεβαίωση"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Αγγίξτε τον αισθητήρα δακτυλικών αποτυπωμάτων"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Εικονίδιο δακτυλικών αποτυπωμάτων"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Εικονίδιο εφαρμογής"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Περιοχή μηνυμάτων βοήθειας"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Αναζήτηση για εσάς…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Εικονίδιο προσώπου"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Κουμπί εστίασης συμβατότητας."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Ζουμ από μικρότερη σε μεγαλύτερη οθόνη."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Το Bluetooth είναι συνδεδεμένο."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Αποθηκευτικός χώρος"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Συμβουλές"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Instant Εφαρμογές"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Οι Instant Εφαρμογές δεν απαιτούν εγκατάσταση."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"Η εφαρμογή <xliff:g id="APP">%1$s</xliff:g> εκτελείται"</string>
+    <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="2650669128861626071">"Μετάβ. σε πρόγ. περ."</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Μετάβαση στον ιστό"</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>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index c0afae6..6503470 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"open camera"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Select new task layout"</string>
     <string name="cancel" msgid="6442560571259935130">"Cancel"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Help message area"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Confirm"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Touch the fingerprint sensor"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Fingerprint icon"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Application icon"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Help message area"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Looking for you…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Face icon"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Compatibility zoom button."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom smaller to larger screen."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth connected."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Storage"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Hints"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Instant apps don\'t require installation."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> running"</string>
+    <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="2650669128861626071">"Go to browser"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Go to web"</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>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 488c748..9e4081c 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"open camera"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Select new task layout"</string>
     <string name="cancel" msgid="6442560571259935130">"Cancel"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Help message area"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Confirm"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Touch the fingerprint sensor"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Fingerprint icon"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Application icon"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Help message area"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Looking for you…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Face icon"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Compatibility zoom button."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom smaller to larger screen."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth connected."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Storage"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Hints"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Instant apps don\'t require installation."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> running"</string>
+    <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="2650669128861626071">"Go to browser"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Go to web"</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>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index c0afae6..6503470 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"open camera"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Select new task layout"</string>
     <string name="cancel" msgid="6442560571259935130">"Cancel"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Help message area"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Confirm"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Touch the fingerprint sensor"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Fingerprint icon"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Application icon"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Help message area"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Looking for you…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Face icon"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Compatibility zoom button."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom smaller to larger screen."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth connected."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Storage"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Hints"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Instant apps don\'t require installation."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> running"</string>
+    <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="2650669128861626071">"Go to browser"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Go to web"</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>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index c0afae6..6503470 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"open camera"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Select new task layout"</string>
     <string name="cancel" msgid="6442560571259935130">"Cancel"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Help message area"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Confirm"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Touch the fingerprint sensor"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Fingerprint icon"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Application icon"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Help message area"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Looking for you…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Face icon"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Compatibility zoom button."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom smaller to larger screen."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth connected."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Storage"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Hints"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Instant apps don\'t require installation."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> running"</string>
+    <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="2650669128861626071">"Go to browser"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Go to web"</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>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index f775bb1..40205b9 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎‎‎‏‎‎‏‎‏‎‎‎‏‏‎‎‏‏‎‏‏‏‎‎‎‎‏‏‎‎‎‏‏‎‏‎‎‏‎‏‎‎‎‏‏‎‏‏‏‎‎‎‎‏‎open camera‎‏‎‎‏‎"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‏‏‏‏‎‎‎‏‏‎‎‎‎‎‏‏‏‎‏‎‎‎‎‏‎‏‏‏‎‎‏‎‎‎‏‎‏‎‎‏‎‎‏‎‎‏‏‏‏‎‎‎‎Select new task layout‎‏‎‎‏‎"</string>
     <string name="cancel" msgid="6442560571259935130">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‏‏‎‏‎‎‎‏‎‎‏‎‎‏‎‏‎‏‏‎‏‎‎‏‎‎‏‎‏‎‏‏‏‏‎‎‎‏‎‏‏‎‏‏‎‎‏‏‎‎‏‏‎‏‎‎Cancel‎‏‎‎‏‎"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‎‏‎‎‎‏‏‏‏‎‏‏‏‏‎‏‎‎‎‎‏‎‎‎‎‏‏‏‎‎‎‎‎‎‎‏‏‎‎‎‏‎‎‏‏‎‏‏‏‏‏‎Help message area‎‏‎‎‏‎"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‎‎‎‏‎‎‏‎‎‏‎‎‏‏‏‎‏‏‎‎‎‎‎‏‎‎‎‎‏‎‎‎‎‎‎‎‎‎‎‎‏‏‏‎‎‎‎‎‏‎‎‎‏‎‎Confirm‎‏‎‎‏‎"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‎‏‎‎‏‏‏‏‏‏‎‎‏‏‏‎‏‎‎‏‏‏‎‎‏‎‎‎‏‏‏‎‏‏‏‎‎‎‎‎‏‎Touch the fingerprint sensor‎‏‎‎‏‎"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‎‏‏‏‏‎‏‎‏‎‏‎‏‎‎‏‎‏‏‎‏‎‎‎‎‏‏‎‏‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‎‏‎‏‎‎Fingerprint icon‎‏‎‎‏‎"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‏‏‎‎‏‏‎‎‎‏‎‏‏‎‎‎‏‎‏‎‏‏‏‏‎‏‎‏‎‎‎‏‏‎‎‏‎‏‏‏‎‎‎‎‎‎‎‎‎‏‎‏‎‎‎‏‎Application icon‎‏‎‎‏‎"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‎‎‎‏‏‎‏‎‏‏‏‎‎‏‏‎‎‎‏‏‏‏‎‏‏‏‏‏‎‏‏‏‏‎‎‏‏‎‎‎‎‎‏‏‎‎‎‏‎‎‎‏‏‏‎Help message area‎‏‎‎‏‎"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‏‎‏‎‎‎‎‎‎‏‏‏‏‎‏‏‎‏‎‏‎‎‏‎‏‎‎‏‎‏‏‏‏‎‏‏‎‎‏‎‏‎‏‏‎‏‏‏‎‎‎‎‏‎Looking for you…‎‏‎‎‏‎"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‏‏‏‎‎‎‏‏‏‎‎‎‏‎‎‏‎‎‏‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‎‏‏‎‎‎‏‎‎‏‏‎‎‎‎‎‏‎‎Face icon‎‏‎‎‏‎"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‎‏‏‏‏‏‎‏‎‏‏‏‎‎‎‏‏‎‏‏‎‏‏‎‎‎‏‎‏‎‎‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‏‎Compatibility zoom button.‎‏‎‎‏‎"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‎‏‎‎‏‎‏‏‏‎‎‏‎‎‏‎‏‏‏‎‏‏‎‏‏‏‎‏‎‎‏‎‎‎‏‏‎‎‎‏‎‎‏‏‏‏‎‏‏‏‎‏‎‎‎Zoom smaller to larger screen.‎‏‎‎‏‎"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‎‏‎‎‎‏‎‏‎‎‏‎‏‏‎‏‎‎‏‎‏‎‎‎‏‏‏‏‎‎‏‎‎‏‏‏‎‏‎‏‎‎‏‎‏‏‏‏‎‎‏‎‏‎‎Bluetooth connected.‎‏‎‎‏‎"</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‏‎‏‏‎‏‎‎‎‏‏‎‏‏‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‎‏‎‏‎‎‎‎‏‏‎‎‎‎‎‏‏‏‎‎‎‏‎‎‎‏‎Storage‎‏‎‎‏‎"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‏‎‎‎‏‏‏‎‎‏‏‏‎‏‎‎‏‎‎‏‏‏‏‎‎‏‏‏‎‎‎‏‏‏‏‎‏‏‎‎‎‎‏‎‎‎‏‎‏‏‎‎‎‏‎Hints‎‏‎‎‏‎"</string>
     <string name="instant_apps" msgid="6647570248119804907">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‎‎‎‎‎‎‏‏‏‎‏‎‎‏‏‏‏‎‏‎‏‏‏‎‎‏‏‎‏‎‏‎‏‎‎‎‏‎‏‏‏‎‎‎‏‏‏‏‏‎‏‎‏‏‎Instant Apps‎‏‎‎‏‎"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‎‎‏‎‎‏‎‏‏‏‎‏‏‎‏‏‎‎‎‏‏‎‏‏‎‎‎‏‎‎‎‏‎‎‎Instant apps don\'t require installation.‎‏‎‎‏‎"</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‏‎‏‎‎‎‏‏‎‏‎‎‏‎‎‎‎‎‎‏‎‏‏‏‏‏‏‎‎‎‎‎‏‏‎‏‏‏‏‏‎‎‎‏‎‏‏‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="APP">%1$s</xliff:g>‎‏‎‎‏‏‏‎ running‎‏‎‎‏‎"</string>
+    <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="2650669128861626071">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‏‏‎‎‏‎‎‏‎‎‎‏‎‎‎‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‎‎‏‎‎‎‎‏‎‏‏‏‎‏‏‎‏‎‏‏‏‎Go to browser‎‏‎‎‏‎"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‎‏‎‏‏‎‎‏‎‏‏‎‎‎‎‏‏‏‎‎‏‏‏‎‏‎‎‏‏‎‎‏‎‏‎‏‎‏‏‏‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎Go to web‎‏‎‎‏‎"</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>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 31509dc..d4adfdc 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"abrir cámara"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Selecciona el nuevo diseño de la tarea."</string>
     <string name="cancel" msgid="6442560571259935130">"Cancelar"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Área de mensajes de ayuda"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Confirmar"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Toca el sensor de huellas digitales"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ícono de huella digital"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Ícono de la aplicación"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Área de mensajes de ayuda"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Autenticando tu rostro…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Ícono de rostro"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botón de zoom de compatibilidad"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom de pantalla más pequeña a más grande"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth conectado"</string>
@@ -825,9 +827,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Almacenamiento"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Sugerencias"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Apps instantáneas"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Las Apps instantáneas no requieren instalación."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> en ejecución"</string>
+    <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="2650669128861626071">"Ir al navegador"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Ir a la Web"</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>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 2cc3abd..00c179c 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="7164937344850004466">"IU del sistema"</string>
+    <string name="app_label" msgid="7164937344850004466">"UI del sistema"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Borrar"</string>
     <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"Quitar de la lista"</string>
     <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Información de la aplicación"</string>
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"abrir cámara"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Seleccionar diseño de tarea nueva"</string>
     <string name="cancel" msgid="6442560571259935130">"Cancelar"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Área de mensaje de ayuda"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Confirmar"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Toca el sensor de huellas digitales"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Icono de huella digital"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Icono de aplicación"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Área de mensaje de ayuda"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Buscando tu cara…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Icono de cara"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botón de zoom de compatibilidad"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom de pantalla más pequeña a más grande"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth conectado"</string>
@@ -561,13 +563,13 @@
     <string name="output_service_bt" msgid="6224213415445509542">"Bluetooth"</string>
     <string name="output_service_wifi" msgid="3749735218931825054">"Wi‑Fi"</string>
     <string name="output_service_bt_wifi" msgid="4486837869988770896">"Bluetooth y Wi‑Fi"</string>
-    <string name="system_ui_tuner" msgid="708224127392452018">"Configurador de IU del sistema"</string>
+    <string name="system_ui_tuner" msgid="708224127392452018">"Configurador de UI del sistema"</string>
     <string name="show_battery_percentage" msgid="5444136600512968798">"Mostrar porcentaje de batería insertado"</string>
     <string name="show_battery_percentage_summary" msgid="3215025775576786037">"Mostrar el porcentaje del nivel de batería en el icono de la barra de estado cuando no se esté cargando"</string>
     <string name="quick_settings" msgid="10042998191725428">"Ajustes rápidos"</string>
     <string name="status_bar" msgid="4877645476959324760">"Barra de estado"</string>
     <string name="overview" msgid="4018602013895926956">"Aplicaciones recientes"</string>
-    <string name="demo_mode" msgid="2532177350215638026">"Modo de demostración de IU del sistema"</string>
+    <string name="demo_mode" msgid="2532177350215638026">"Modo de demostración de UI del sistema"</string>
     <string name="enable_demo_mode" msgid="4844205668718636518">"Habilitar modo de demostración"</string>
     <string name="show_demo_mode" msgid="2018336697782464029">"Mostrar modo de demostración"</string>
     <string name="status_bar_ethernet" msgid="5044290963549500128">"Ethernet"</string>
@@ -584,12 +586,12 @@
     <string name="accessibility_status_bar_hotspot" msgid="4099381329956402865">"Zona Wi-Fi"</string>
     <string name="accessibility_managed_profile" msgid="6613641363112584120">"Perfil de trabajo"</string>
     <string name="tuner_warning_title" msgid="7094689930793031682">"Diversión solo para algunos"</string>
-    <string name="tuner_warning" msgid="8730648121973575701">"El configurador de IU del sistema te ofrece otras formas de modificar y personalizar la interfaz de usuario de Android. Estas funciones experimentales pueden cambiar, fallar o desaparecer en futuras versiones. Te recomendamos que tengas cuidado."</string>
+    <string name="tuner_warning" msgid="8730648121973575701">"El configurador de UI del sistema te ofrece otras formas de modificar y personalizar la interfaz de usuario de Android. Estas funciones experimentales pueden cambiar, fallar o desaparecer en futuras versiones. Te recomendamos que tengas cuidado."</string>
     <string name="tuner_persistent_warning" msgid="8597333795565621795">"Estas funciones experimentales pueden cambiar, fallar o desaparecer en futuras versiones. Te recomendamos que tengas cuidado."</string>
     <string name="got_it" msgid="2239653834387972602">"Entendido"</string>
-    <string name="tuner_toast" msgid="603429811084428439">"¡Enhorabuena! El configurador de IU del sistema se ha añadido a Ajustes"</string>
+    <string name="tuner_toast" msgid="603429811084428439">"¡Enhorabuena! El configurador de UI del sistema se ha añadido a Ajustes"</string>
     <string name="remove_from_settings" msgid="8389591916603406378">"Quitar de Ajustes"</string>
-    <string name="remove_from_settings_prompt" msgid="6069085993355887748">"¿Quitar el configurador de IU del sistema de Ajustes y dejar de utilizar sus funciones?"</string>
+    <string name="remove_from_settings_prompt" msgid="6069085993355887748">"¿Quitar el configurador de UI del sistema de Ajustes y dejar de utilizar sus funciones?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"La aplicación no está instalada en tu dispositivo"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Mostrar los segundos del reloj"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Muestra los segundos del reloj en la barra de estado. Puede afectar a la duración de la batería."</string>
@@ -825,9 +827,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Almacenamiento"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Sugerencias"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Aplicaciones Instantáneas"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"No es necesario instalar las Aplicaciones Instantáneas."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> se está ejecutando"</string>
+    <string name="instant_apps_message" msgid="1183313016396018086">"La aplicación se abre sin necesidad de instalarla."</string>
+    <string name="instant_apps_message_with_help" msgid="6179830437630729747">"La aplicación se abre sin necesidad de instalarla. 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="2650669128861626071">"Ir al navegador"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Ir a la Web"</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>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index f22dc1a..246f1f8 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"ava kaamera"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Uue toimingu paigutuse valimine"</string>
     <string name="cancel" msgid="6442560571259935130">"Tühista"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Abisõnumi ala"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Kinnita"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Puudutage sõrmejäljeandurit"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Sõrmejälje ikoon"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Rakenduse ikoon"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Abisõnumi ala"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Otsitakse teid …"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Näoikoon"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Sobivussuumi nupp."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Suumi suuremale ekraanile vähem."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth on ühendatud."</string>
@@ -825,9 +827,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Salvestusruum"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Vihjed"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Installimata avatavad rakendused"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Installimata avatavaid rakendusi pole vaja installida."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"Rakendus <xliff:g id="APP">%1$s</xliff:g> töötab"</string>
+    <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="2650669128861626071">"Ava brauser"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Avage veebis"</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>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 87dba92..b73946e 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"ireki kamera"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Hautatu zereginen diseinua"</string>
     <string name="cancel" msgid="6442560571259935130">"Utzi"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Laguntza-mezuaren eremua"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Berretsi"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Sakatu hatz-marken sentsorea"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Hatz-markaren ikonoa"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Aplikazioaren ikonoa"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Laguntza-mezuaren eremua"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Zure bila…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Aurpegiaren ikonoa"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Zoom-bateragarritasunaren botoia."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Handiagotu pantaila txikia."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetootha konektatuta."</string>
@@ -825,9 +827,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Memoria"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Aholkuak"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Zuzeneko aplikazioak"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Zuzeneko aplikazioak ez dira instalatu behar."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> exekutatzen ari da"</string>
+    <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="2650669128861626071">"Joan arakatzailera"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Joan sarera"</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>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 5411d3d..3997f1a 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -47,7 +47,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"تنظیمات"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"چرخش خودکار صفحه"</string>
-    <string name="status_bar_settings_mute_label" msgid="554682549917429396">"بی‌صدا"</string>
+    <string name="status_bar_settings_mute_label" msgid="554682549917429396">"صامت"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"خودکار"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"اعلان‌ها"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"اتصال اینترنتی با بلوتوث تلفن همراه"</string>
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"باز کردن دوربین"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"انتخاب طرح‌بندی جدید کار"</string>
     <string name="cancel" msgid="6442560571259935130">"لغو"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"بخش پیام راهنما"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"تأیید"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"حسگر اثر انگشت را لمس کنید"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"نماد اثر انگشت"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"نماد برنامه"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"بخش پیام راهنما"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"درحال جستجوی شما…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"نماد چهره"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"دکمه بزرگ‌نمایی سازگار."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"بزرگ‌نمایی از صفحه‌های کوچک تا بزرگ."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"بلوتوث متصل است."</string>
@@ -539,14 +541,14 @@
     <string name="ring_toggle_title" msgid="3281244519428819576">"تماس‌ها"</string>
     <string name="volume_ringer_status_normal" msgid="4273142424125855384">"زنگ زدن"</string>
     <string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"لرزش"</string>
-    <string name="volume_ringer_status_silent" msgid="6896394161022916369">"بی‌صدا"</string>
+    <string name="volume_ringer_status_silent" msgid="6896394161022916369">"صامت"</string>
     <string name="qs_status_phone_vibrate" msgid="204362991135761679">"تلفن در حالت لرزش است"</string>
     <string name="qs_status_phone_muted" msgid="5437668875879171548">"تلفن بی‌صدا است"</string>
     <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"‏%1$s. برای باصدا کردن ضربه بزنید."</string>
     <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"‏%1$s. برای تنظیم روی لرزش ضربه بزنید. ممکن است سرویس‌های دسترس‌پذیری بی‌صدا شوند."</string>
-    <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"‏%1$s. برای بی‌صدا کردن ضربه بزنید. ممکن است سرویس‌های دسترس‌پذیری بی‌صدا شوند."</string>
+    <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"‏%1$s. برای صامت کردن ضربه بزنید. ممکن است سرویس‌های دسترس‌پذیری صامت شود."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="6427727603978431301">"‏%1$s. برای تنظیم روی لرزش، ضربه بزنید."</string>
-    <string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"‏%1$s. برای بی‌صدا کردن ضربه بزنید."</string>
+    <string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"‏%1$s. برای صامت کردن ضربه بزنید."</string>
     <string name="volume_ringer_hint_mute" msgid="9199811307292269601">"صامت کردن"</string>
     <string name="volume_ringer_hint_unmute" msgid="6602880133293060368">"باصدا کردن"</string>
     <string name="volume_ringer_hint_vibrate" msgid="4036802135666515202">"لرزش"</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"فضای ذخیره‌سازی"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"نکات"</string>
     <string name="instant_apps" msgid="6647570248119804907">"برنامه‌های فوری"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"برنامه‌های فوری نیاز به نصب ندارند."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> درحال اجرا"</string>
+    <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="2650669128861626071">"رفتن به مرورگر"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"رفتن به وب"</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>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 83345b8..6e8cb4c 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"avaa kamera"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Valitse uusi tehtävien asettelu"</string>
     <string name="cancel" msgid="6442560571259935130">"Peruuta"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Ohjeviestialue"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Vahvista"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Kosketa sormenjälkitunnistinta"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Sormenjälkikuvake"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Sovelluskuvake"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Ohjeviestialue"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Etsitään kasvoja…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Kasvokuvake"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Yhteensopivuuszoomaus-painike."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoomaa pienemmältä suuremmalle ruudulle."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth yhdistetty."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Tallennustila"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Vihjeet"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Pikasovelluksia ei tarvitse asentaa."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> on käynnissä"</string>
+    <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="2650669128861626071">"Siirry selaimeen"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Avaa verkossa"</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>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index c9c252f..f6d66b7 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"Ouvrir l\'appareil photo"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Sélectionner un nouveau format de tâche"</string>
     <string name="cancel" msgid="6442560571259935130">"Annuler"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Zone de message d\'aide"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Confirmer"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Touchez le capteur d\'empreintes digitales"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Icône d\'empreinte digitale"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Icône de l\'application"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Zone de message d\'aide"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Recherche de votre visage…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Icône de visage"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Bouton \"Zoom de compatibilité\""</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom de compatibilité avec la taille de l\'écran"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth connecté"</string>
@@ -825,9 +827,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Stockage"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Conseils"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Applications instantanées"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Les applications instantanées ne nécessitent pas d\'installation."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> en cours d\'exécution"</string>
+    <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="2650669128861626071">"Ouvrir le navigateur"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Accéder au Web"</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>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 4559854..326b7c7 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"ouvrir l\'appareil photo"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Sélectionner un nouveau plan de tâche"</string>
     <string name="cancel" msgid="6442560571259935130">"Annuler"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Zone de message d\'aide"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Confirmer"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Appuyez sur le lecteur d\'empreinte digitale"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Icône d\'empreinte digitale"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Icône d\'application"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Zone de message d\'aide"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Recherche de votre visage…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Icône représentant un visage"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Bouton \"Zoom de compatibilité\""</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom de compatibilité avec la taille de l\'écran"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth connecté"</string>
@@ -401,9 +403,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Aucune\ninterruption"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Priorité\nuniquement"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Alarmes\nuniquement"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rechargement… (rechargé à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rechargement rapide… (à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rechargement lent… (à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Recharge... (à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Recharge rapide… (à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Recharge lente… (à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Changer d\'utilisateur"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Changer d\'utilisateur (utilisateur actuel : <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Utilisateur actuel : <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -825,9 +827,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Espace de stockage"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Astuces"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Applis instantanées"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Les applis instantanées ne nécessitent pas d\'installation."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> en cours d\'exécution"</string>
+    <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="2650669128861626071">"Accéder au navigateur"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Accéder au site Web"</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>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 9cb251e..192c132 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"abrir cámara"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Seleccionar novo deseño de tarefas"</string>
     <string name="cancel" msgid="6442560571259935130">"Cancelar"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Área de mensaxes de axuda"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Confirmar"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Toca o sensor de impresión dixital"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Icona de impresión dixital"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Icona de aplicación"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Área de mensaxes de axuda"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Buscándote…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Icona de cara"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botón de zoom de compatibilidade"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom de compatibilidade co tamaño da pantalla."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth conectado"</string>
@@ -825,9 +827,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Almacenamento"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Consellos"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Aplicacións instantáneas"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"As aplicacións instantáneas non precisan instalación."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"Estase executando <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <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="2650669128861626071">"Ir ao navegador"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Acceder á web"</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>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index df06cbe..f392268 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"કૅમેરો ખોલો"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"નવું કાર્ય લેઆઉટ પસંદ કરો"</string>
     <string name="cancel" msgid="6442560571259935130">"રદ કરો"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"સહાય સંદેશનું ક્ષેત્ર"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"કન્ફર્મ કરો"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"ફિંગરપ્રિન્ટના સેન્સરને સ્પર્શ કરો"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ફિંગરપ્રિન્ટનું આઇકન"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"ઍપ્લિકેશનનું આઇકન"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"સહાય સંદેશનું ક્ષેત્ર"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"તમારા માટે શોધી રહ્યાં છે..."</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"ચહેરા આઇકન"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"સુસંગતતા ઝૂમ બટન."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"નાનીથી મોટી સ્ક્રીન પર ઝૂમ કરો."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"બ્લૂટૂથ કનેક્ટ થયું."</string>
@@ -823,9 +825,14 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"સ્ટોરેજ"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"હિન્ટ"</string>
     <string name="instant_apps" msgid="6647570248119804907">"ઝટપટ ઍપ્લિકેશનો"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"ઝટપટ ઍપ્લિકેશનો માટે ઇન્સ્ટૉલેશનની જરૂર નથી."</string>
+    <!-- no translation found for instant_apps_title (8738419517367449783) -->
+    <skip />
+    <!-- no translation found for instant_apps_message (1183313016396018086) -->
+    <skip />
+    <!-- no translation found for instant_apps_message_with_help (6179830437630729747) -->
+    <skip />
     <string name="app_info" msgid="6856026610594615344">"ઍપ્લિકેશન માહિતી"</string>
-    <string name="go_to_web" msgid="2650669128861626071">"બ્રાઉઝર પર જાઓ"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"વેબ પર જાઓ"</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>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 46555a4..8795264 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"कैमरा खोलें"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"नया कार्य लेआउट चुनें"</string>
     <string name="cancel" msgid="6442560571259935130">"रद्द करें"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"सहायता का मैसेज दिखाने की जगह"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"पुष्टि करें"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"फ़िंगरप्रिंट सेंसर को छुएं"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"फ़िंगरप्रिंट आइकॉन"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"ऐप्लिकेशन आइकॉन"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"सहायता का मैसेज दिखाने की जगह"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"आपको पहचान रहा है…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"चेहरे का आइकॉन"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"संगतता ज़ूम बटन."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"छोटी से बड़ी स्‍क्रीन पर ज़ूम करें."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ब्लूटूथ कनेक्ट किया गया."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"जगह"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"संकेत"</string>
     <string name="instant_apps" msgid="6647570248119804907">"इंस्टेंट ऐप"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"झटपट ऐप्स के लिए इंस्टॉलेशन ज़रूरी नहीं है."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> चल रहा है"</string>
+    <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="2650669128861626071">"ब्राउज़र पर जाएं"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"वेब पर जाएं"</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>
diff --git a/packages/SystemUI/res/values-hi/strings_car.xml b/packages/SystemUI/res/values-hi/strings_car.xml
index 8820046..3beada5 100644
--- a/packages/SystemUI/res/values-hi/strings_car.xml
+++ b/packages/SystemUI/res/values-hi/strings_car.xml
@@ -20,8 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_guest" msgid="3738772168718508650">"मेहमान"</string>
-    <!-- no translation found for start_guest_session (7055742120180595689) -->
-    <skip />
+    <string name="start_guest_session" msgid="7055742120180595689">"मेहमान मोड"</string>
     <string name="car_add_user" msgid="5245196248349230898">"उपयोगकर्ता जोड़ें"</string>
     <string name="car_new_user" msgid="8142927244990323906">"नया उपयोगकर्ता"</string>
     <string name="user_add_user_message_setup" msgid="1791011504259527329">"जब आप कोई नया उपयोगकर्ता जोड़ते हैं तो, उस व्यक्ति को अपनी जगह सेट करनी होती है."</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 7ad2fe2..b6fa4f5 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -104,10 +104,12 @@
     <string name="camera_label" msgid="7261107956054836961">"otvaranje fotoaparata"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Odaberite novi izgled zadataka"</string>
     <string name="cancel" msgid="6442560571259935130">"Odustani"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Područje poruke za pomoć"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Potvrdi"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Dodirnite senzor otiska prsta"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikona otiska prsta"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Ikona aplikacije"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Područje poruke za pomoć"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Tražimo vas…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Ikona lica"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Gumb za kompatibilnost zumiranja."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zumiranje manjeg zaslona na veći."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth povezan."</string>
@@ -829,9 +831,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Pohrana"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Savjeti"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Instant aplikacije"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Instant aplikacije nije potrebno instalirati."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"Izvodi se aplikacija <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <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="2650669128861626071">"Otvori preglednik"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Prijeđi na web"</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>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index f5fad27..9076379 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"kamera megnyitása"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Új feladatelrendezés kiválasztása"</string>
     <string name="cancel" msgid="6442560571259935130">"Mégse"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Súgószöveg területe"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Megerősítés"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Érintse meg az ujjlenyomat-érzékelőt"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ujjlenyomat ikonja"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Alkalmazás ikonja"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Súgószöveg területe"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Keresem az Ön arcát…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Arcikon"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Kompatibilitási zoom gomb."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Kicsinyítsen a nagyobb képernyőhöz."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth csatlakoztatva."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Tárhely"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Tippek"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Azonnali alkalmazások"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Az azonnali alkalmazásokat nem kell telepíteni."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"A(z) <xliff:g id="APP">%1$s</xliff:g> alkalmazás jelenleg fut"</string>
+    <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="2650669128861626071">"Ugrás a böngészőbe"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Tovább az internetre"</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>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 5eeca4c..54401f5 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"բացել ֆոտոխցիկը"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Ընտրել առաջադրանքի նոր դասավորություն"</string>
     <string name="cancel" msgid="6442560571259935130">"Չեղարկել"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Օգնության հաղորդագրության դաշտ"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Հաստատել"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Հպեք մատնահետքերի սկաներին"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Մատնահետքի պատկերակ"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Հավելվածի պատկերակ"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Օգնության հաղորդագրության դաշտ"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Դեմքի ճանաչում…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Դեմքի պատկերակ"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Համատեղելիության խոշորացման կոճակը:"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Դիտափոխել փոքրից ավելի մեծ էկրան:"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth-ը միացված է:"</string>
@@ -582,12 +584,12 @@
     <string name="accessibility_status_bar_hotspot" msgid="4099381329956402865">"Թեժ կետ"</string>
     <string name="accessibility_managed_profile" msgid="6613641363112584120">"Աշխատանքային պրոֆիլ"</string>
     <string name="tuner_warning_title" msgid="7094689930793031682">"Զվարճանք մեկ՝ որոշակի մարդու համար"</string>
-    <string name="tuner_warning" msgid="8730648121973575701">"Համակարգի ՕՄ-ի ընդունիչը հնարավորություն է տալիս հարմարեցնել Android-ի օգտատիրոջ միջերեսը: Այս փորձնական գործառույթները կարող են հետագա թողարկումների մեջ փոփոխվել, խափանվել կամ ընդհանրապես չհայտնվել: Եթե շարունակում եք, զգուշացեք:"</string>
+    <string name="tuner_warning" msgid="8730648121973575701">"Համակարգի ՕՄ-ի կարգավորիչը հնարավորություն է տալիս հարմարեցնել Android-ի օգտատիրոջ միջերեսը: Այս փորձնական գործառույթները կարող են հետագա թողարկումների մեջ փոփոխվել, խափանվել կամ ընդհանրապես չհայտնվել: Եթե շարունակում եք, զգուշացեք:"</string>
     <string name="tuner_persistent_warning" msgid="8597333795565621795">"Այս փորձնական գործառույթները կարող են հետագա թողարկումների մեջ փոփոխվել, խափանվել կամ ընդհանրապես չհայտնվել: Եթե շարունակում եք, զգուշացեք:"</string>
     <string name="got_it" msgid="2239653834387972602">"Եղավ"</string>
-    <string name="tuner_toast" msgid="603429811084428439">"Համակարգի ՕՄ-ի ընդունիչը ավելացվել է կարգավորումներին"</string>
+    <string name="tuner_toast" msgid="603429811084428439">"Համակարգի ՕՄ-ի կարգավորիչը ավելացվել է կարգավորումներին"</string>
     <string name="remove_from_settings" msgid="8389591916603406378">"Հեռացնել կարգավորումներից"</string>
-    <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Հեռացնե՞լ Համակարգի ՕՄ-ի ընդունիչը կարգավորումներից և չօգտվել այլևս նրա գործառույթներից:"</string>
+    <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Հեռացնե՞լ Համակարգի ՕՄ-ի կարգավորիչը կարգավորումներից և չօգտվել այլևս նրա գործառույթներից:"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Հավելվածը տեղադրված չէ սարքի վրա"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Ցույց տալ ժամացույցի վայրկյանները"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Ցույց տալ ժամացույցի վայրկյանները կարգավիճակի տողում: Կարող է ազդել մարտկոցի աշխատանքի ժամանակի վրա:"</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Տարածք"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Հուշումներ"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Ակնթարթային հավելվածներ"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Ակնթարթային հավելվածները տեղադրում չեն պահանջում։"</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> հավելվածն աշխատում է"</string>
+    <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="2650669128861626071">"Անցնել դիտարկիչ"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Բացեք համացանցում"</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>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 5a61a64..2474158 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"buka kamera"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Pilih tata letak tugas baru"</string>
     <string name="cancel" msgid="6442560571259935130">"Batal"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Area pesan bantuan"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Konfirmasi"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Sentuh sensor sidik jari"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikon sidik jari"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Ikon aplikasi"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Area pesan bantuan"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Mencari wajah Anda…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Ikon wajah"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Tombol perbesar/perkecil kompatibilitas."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Perbesar dari layar kecil ke besar."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth tersambung."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Penyimpanan"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Petunjuk"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Aplikasi Instan"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Aplikasi instan tidak perlu diinstal."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> berjalan"</string>
+    <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="2650669128861626071">"Buka browser"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Buka di web"</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>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index fb83ff07..c2a020b 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"opna myndavél"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Velja nýtt útlit verkefna"</string>
     <string name="cancel" msgid="6442560571259935130">"Hætta við"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Svæði hjálparskilaboða"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Staðfesta"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Snertu fingrafaralesarann"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Fingrafaratákn"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Forritstákn"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Svæði hjálparskilaboða"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Leitar að þér ..."</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Andlitstákn"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Hnappur fyrir samhæfisaðdrátt."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Aðlaga forrit fyrir lítinn skjá að stærri skjá."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth tengt."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Geymslurými"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Vísbendingar"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Skyndiforrit"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Skyndiforrit þurfa ekki uppsetningu."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> er í gangi"</string>
+    <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="2650669128861626071">"Opna vafra"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Fara á vefinn"</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>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index c081eaa..aefaa6d 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"apri fotocamera"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Seleziona un nuovo layout per le attività"</string>
     <string name="cancel" msgid="6442560571259935130">"Annulla"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Area dei messaggi di assistenza"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Confermo"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Tocca il sensore di impronte digitali"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Icona dell\'impronta digitale"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Icona dell\'applicazione"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Area dei messaggi di assistenza"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"In attesa del volto…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Icona volto"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Pulsante zoom compatibilità."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom inferiore per schermo più grande."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth collegato."</string>
@@ -825,9 +827,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Spazio di archiviazione"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Suggerimenti"</string>
     <string name="instant_apps" msgid="6647570248119804907">"App istantanee"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Le app istantanee non richiedono l\'installazione."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"App <xliff:g id="APP">%1$s</xliff:g> in esecuzione"</string>
+    <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="2650669128861626071">"Vai al browser"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Vai sul Web"</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>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index d3d18ae..b83f5df 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -105,10 +105,12 @@
     <string name="camera_label" msgid="7261107956054836961">"פתח את המצלמה"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"בחר פריסה חדשה להצגת משימות"</string>
     <string name="cancel" msgid="6442560571259935130">"ביטול"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"אזור הודעת עזרה"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"אישור"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"יש לגעת בחיישן טביעות האצבע"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"סמל טביעת אצבע"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"סמל אפליקציה"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"אזור הודעת עזרה"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"מחפש אותך…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"סמל הפנים"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"לחצן מרחק מתצוגה של תאימות."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"שנה מרחק מתצוגה של מסך קטן לגדול יותר."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"‏Bluetooth מחובר."</string>
@@ -194,7 +196,7 @@
     <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"פתח מידע על האפליקציה <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"מפעיל את <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"הודעה נדחתה."</string>
-    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"לוח הודעות."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"לוח התראות."</string>
     <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"הגדרות מהירות."</string>
     <string name="accessibility_desc_lock_screen" msgid="5625143713611759164">"מסך נעילה."</string>
     <string name="accessibility_desc_settings" msgid="3417884241751434521">"הגדרות"</string>
@@ -266,7 +268,7 @@
       <item quantity="other">יש בפנים עוד <xliff:g id="NUMBER_1">%s</xliff:g> הודעות.</item>
       <item quantity="one">יש בפנים עוד הודעה <xliff:g id="NUMBER_0">%s</xliff:g>.</item>
     </plurals>
-    <string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"הגדרות עבור הודעות"</string>
+    <string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"הגדרת התראות"</string>
     <string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"הגדרות <xliff:g id="APP_NAME">%s</xliff:g>"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"המסך יסתובב באופן אוטומטי."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"המסך נעול כעת לרוחב."</string>
@@ -835,9 +837,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"אחסון"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"טיפים"</string>
     <string name="instant_apps" msgid="6647570248119804907">"אפליקציות אינסטנט"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"אפליקציות אינסטנט לא דורשות התקנה."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> פועלת"</string>
+    <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="2650669128861626071">"מעבר אל הדפדפן"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"התחבר לאינטרנט"</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>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 8377f07..e5b0a2b 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"カメラを起動"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"新しいタスクレイアウトの選択"</string>
     <string name="cancel" msgid="6442560571259935130">"キャンセル"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"ヘルプ メッセージ領域"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"確認"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"指紋認証センサーをタップしてください"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"指紋アイコン"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"アプリのアイコン"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"ヘルプ メッセージ領域"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"顔を認証しています…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"顔アイコン"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"互換ズームボタン。"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"小さい画面から大きい画面に拡大。"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetoothに接続済み。"</string>
@@ -346,7 +348,7 @@
     <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"上限: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"警告: 上限は<xliff:g id="DATA_LIMIT">%s</xliff:g>です"</string>
     <string name="quick_settings_work_mode_label" msgid="7608026833638817218">"仕事用プロファイル"</string>
-    <string name="quick_settings_night_display_label" msgid="3577098011487644395">"読書灯"</string>
+    <string name="quick_settings_night_display_label" msgid="3577098011487644395">"夜間モード"</string>
     <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"日の入りに ON"</string>
     <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> に ON"</string>
@@ -825,9 +827,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"ストレージ"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"ヒント"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Instant Apps はインストールせずに利用できます。"</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> を実行中"</string>
+    <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="2650669128861626071">"ブラウザに移動"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"ウェブページを開く"</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>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index fb880c7..19e9f47 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"კამერის გახსნა"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"ახალი ამოცანის განლაგების არჩევა"</string>
     <string name="cancel" msgid="6442560571259935130">"გაუქმება"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"დამხმარე შეტყობინების არე"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"დადასტურება"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"შეეხეთ თითის ანაბეჭდის სენსორს"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"თითის ანაბეჭდის ხატულა"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"აპლიკაციის ხატულა"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"დახმარების შეტყობინების არეალი"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"მიმდინარეობს თქვენი ძიება…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"სახის ხატულა"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"თავსებადი მასშტაბირების ღილაკი."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"შეცვალეთ პატარა ეკრანი უფრო დიდით."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth დაკავშირებულია."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"მეხსიერება"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"მინიშნებები"</string>
     <string name="instant_apps" msgid="6647570248119804907">"მყისიერი აპები"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"მყისიერი აპები ინსტალაციას არ საჭიროებს."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> გაშვებულია"</string>
+    <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="2650669128861626071">"ბრაუზერზე გადასვლა"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"ვებზე გადასვლა"</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>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 6e372d7..15f8cd5 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"камераны ашу"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Жаңа тапсырма пішімін таңдау"</string>
     <string name="cancel" msgid="6442560571259935130">"Бас тарту"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Анықтама хабары аумағы"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Растау"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Саусақ ізін оқу сканерін түртіңіз"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Саусақ ізі белгішесі"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Қолданба белгішесі"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Анықтама хабары аумағы"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Бет ізделуде…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Бет белгішесі"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Үйлесімділік ұлғайту түймесі."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Үлкендеу экранда кішірейту."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth қосылған."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Жад"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Кеңестер"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Лездік қолданбаларды орнатудың қажеті жоқ."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> іске қосулы"</string>
+    <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="2650669128861626071">"Браузерге өту"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Вебке өту"</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>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index eb9ed61..af8d4ce 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"បើក​ម៉ាស៊ីន​ថត"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"ជ្រើសប្លង់ភារកិច្ចថ្មី"</string>
     <string name="cancel" msgid="6442560571259935130">"បោះ​បង់​"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"តំបន់សារ​ជំនួយ"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"បញ្ជាក់"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"ប៉ះ​ឧបករណ៍​ចាប់ស្នាម​ម្រាមដៃ"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"រូបតំណាង​ស្នាម​ម្រាមដៃ"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"រូបតំណាង​កម្មវិធី"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"តំបន់សារ​ជំនួយ"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"កំពុងស្វែងរកអ្នក…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"រូប​ផ្ទៃមុខ"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ប៊ូតុង​ពង្រីក​ត្រូវ​គ្នា។"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ពង្រីក/បង្រួម​​អេក្រង់​ពី​​ទៅធំ"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"បាន​តភ្ជាប់​ប៊្លូធូស។"</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"ទំហំផ្ទុក"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"ការ​សម្រួល"</string>
     <string name="instant_apps" msgid="6647570248119804907">"កម្មវិធី​ប្រើ​ភ្លាមៗ"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"កម្មវិធី​ប្រើ​ភ្លាមៗ​មិន​តម្រូវ​ឲ្យ​មានការ​ដំឡើង​ទេ។"</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> កំពុង​ដំណើរការ"</string>
+    <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="2650669128861626071">"ចូល​ទៅ​កម្មវិធី​រុករក​តាម​អ៊ីនធឺណិត"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"ចូលទៅកាន់បណ្តាញ"</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>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index c63dbe9..ac36e73 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"ಕ್ಯಾಮರಾ ತೆರೆಯಿರಿ"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"ಹೊಸ ಕಾರ್ಯ ವಿನ್ಯಾಸವನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
     <string name="cancel" msgid="6442560571259935130">"ರದ್ದುಮಾಡಿ"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"ಸಹಾಯ ಸಂದೇಶ ಪ್ರದೇಶ"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"ದೃಢೀಕರಿಸಿ"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್‌‌ ಅನ್ನು ಸ್ಪರ್ಶಿಸಿ"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಐಕಾನ್"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"ಅಪ್ಲಿಕೇಶನ್‌ ಐಕಾನ್‌"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"ಸಹಾಯ ಸಂದೇಶ ಪ್ರದೇಶ"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"ನಿಮಗಾಗಿ ಹುಡುಕಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"ಮುಖದ ಐಕಾನ್‌"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ಹೊಂದಾಣಿಕೆಯ ಝೂಮ್ ಬಟನ್."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ಚಿಕ್ಕ ಪರದೆಯಿಂದ ದೊಡ್ಡ ಪರದೆಗೆ ಝೂಮ್ ಮಾಡು."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ಬ್ಲೂಟೂತ್‌‌ ಸಂಪರ್ಕಗೊಂಡಿದೆ."</string>
@@ -823,9 +825,14 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"ಸಂಗ್ರಹಣೆ"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"ಸುಳಿವುಗಳು"</string>
     <string name="instant_apps" msgid="6647570248119804907">"ತತ್‌ಕ್ಷಣ ಆಪ್‌ಗಳು"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"ತತ್‌ಕ್ಷಣ ಆಪ್‌ಗಳಿಗೆ ಸ್ಥಾಪನೆಯ ಅಗತ್ಯವಿಲ್ಲ."</string>
+    <!-- no translation found for instant_apps_title (8738419517367449783) -->
+    <skip />
+    <!-- no translation found for instant_apps_message (1183313016396018086) -->
+    <skip />
+    <!-- no translation found for instant_apps_message_with_help (6179830437630729747) -->
+    <skip />
     <string name="app_info" msgid="6856026610594615344">"ಅಪ್ಲಿಕೇಶನ್ ಮಾಹಿತಿ"</string>
-    <string name="go_to_web" msgid="2650669128861626071">"ಬ್ರೌಸರ್‌ಗೆ ಹೋಗಿ"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"ವೆಬ್‌ಗೆ ಹೋಗಿ"</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>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 77c983e..1e2ab42 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"카메라 열기"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"새 작업 레이아웃 선택"</string>
     <string name="cancel" msgid="6442560571259935130">"취소"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"도움말 메시지 영역"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"확인"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"지문 센서를 터치하세요."</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"지문 아이콘"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"애플리케이션 아이콘"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"도움말 메시지 영역"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"찾는 중..."</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"얼굴 아이콘"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"호환성 확대/축소 버튼입니다."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"작은 화면을 큰 화면으로 확대합니다."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"블루투스가 연결되었습니다."</string>
@@ -410,13 +412,13 @@
     <string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"프로필 표시"</string>
     <string name="user_add_user" msgid="5110251524486079492">"사용자 추가"</string>
     <string name="user_new_user_name" msgid="426540612051178753">"새 사용자"</string>
-    <string name="guest_nickname" msgid="8059989128963789678">"손님"</string>
+    <string name="guest_nickname" msgid="8059989128963789678">"게스트"</string>
     <string name="guest_new_guest" msgid="600537543078847803">"게스트 추가"</string>
-    <string name="guest_exit_guest" msgid="7187359342030096885">"손님 삭제"</string>
-    <string name="guest_exit_guest_dialog_title" msgid="8480693520521766688">"손님을 삭제하시겠습니까?"</string>
+    <string name="guest_exit_guest" msgid="7187359342030096885">"게스트 삭제"</string>
+    <string name="guest_exit_guest_dialog_title" msgid="8480693520521766688">"게스트를 삭제하시겠습니까?"</string>
     <string name="guest_exit_guest_dialog_message" msgid="4155503224769676625">"이 세션에 있는 모든 앱과 데이터가 삭제됩니다."</string>
     <string name="guest_exit_guest_dialog_remove" msgid="7402231963862520531">"삭제"</string>
-    <string name="guest_wipe_session_title" msgid="6419439912885956132">"손님 세션 다시 시작"</string>
+    <string name="guest_wipe_session_title" msgid="6419439912885956132">"게스트 세션 다시 시작"</string>
     <string name="guest_wipe_session_message" msgid="8476238178270112811">"세션을 계속 진행하시겠습니까?"</string>
     <string name="guest_wipe_session_wipe" msgid="5065558566939858884">"다시 시작"</string>
     <string name="guest_wipe_session_dontwipe" msgid="1401113462524894716">"예, 계속합니다."</string>
@@ -825,9 +827,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"저장공간"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"힌트"</string>
     <string name="instant_apps" msgid="6647570248119804907">"인스턴트 앱"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"인스턴트 앱은 설치가 필요하지 않습니다."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> 실행 중"</string>
+    <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="2650669128861626071">"브라우저로 이동"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"웹으로 이동"</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>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index e334da4..585e290 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"камераны ачуу"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Жаңы тапшырманын планын тандаңыз"</string>
     <string name="cancel" msgid="6442560571259935130">"Жокко чыгаруу"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Жардам билдирүүсү"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Ырастоо"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Манжа изинин сенсорун басыңыз"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Манжа изинин сүрөтчөсү"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Колдонмонун сүрөтчөсү"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Жардам билдирүүсү"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Жүзүңүз изделүүдө…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Жүздүн сүрөтчөсү"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Масштабды сыйыштыруу баскычы."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Кичинекейди чоң экранга масштабдоо."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth байланышта"</string>
@@ -209,7 +211,7 @@
     <string name="accessibility_quick_settings_airplane_changed_off" msgid="66846307818850664">"Учак режими өчүрүлдү."</string>
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Учак режими күйгүзүлдү."</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_alarms_on" msgid="3357131899365865386">"ойготкуч гана"</string>
     <string name="accessibility_quick_settings_dnd" msgid="6607873236717185815">"Тынчымды алба."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Тынчымды алба деген өчүрүлдү."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Тынчымды алба деген күйгүзүлдү."</string>
@@ -276,7 +278,7 @@
     <string name="quick_settings_header_onboarding_text" msgid="8030309023792936283">"Кошумча параметрлерди ачуу үчүн сүрөтчөлөрдү басып, кармап туруңуз"</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_alarms_label" msgid="2559229444312445858">"Ойготкуч гана"</string>
     <string name="quick_settings_dnd_none_label" msgid="5025477807123029478">"Тымтырс"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> түзмөк)"</string>
@@ -395,7 +397,7 @@
     <string name="interruption_level_none_with_warning" msgid="5114872171614161084">"Толук жымжырттык талап кылынат. Бул экрандагыны окугучтарды да тынчтандырат."</string>
     <string name="interruption_level_none" msgid="6000083681244492992">"Тымтырс"</string>
     <string name="interruption_level_priority" msgid="6426766465363855505">"Шашылыш эскертмелер гана"</string>
-    <string name="interruption_level_alarms" msgid="5226306993448328896">"Ойготкучтар гана"</string>
+    <string name="interruption_level_alarms" msgid="5226306993448328896">"Ойготкуч гана"</string>
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Тым-\nтырс"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Артыкчылыктуу\nгана"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Ойготкучтар\nгана"</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Сактагыч"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Кеңештер"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Ыкчам ачылуучу колдонмолор"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Ыкчам ачылуучу колдонмолорду орнотуу талап кылынбайт."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> иштеп жатат"</string>
+    <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="2650669128861626071">"Серепчиге өтүү"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Интернетке өтүү"</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>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 56f9e1d..0952df4 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"ເປີດ​ກ້ອງ"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"ເລືອກ​ແຜນ​ຜັງ​ໜ້າ​ວຽກ​ໃໝ່"</string>
     <string name="cancel" msgid="6442560571259935130">"ຍົກເລີກ"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"ຊ່ວຍພື້ນທີ່ຂໍ້ຄວາມ"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"ຢືນຢັນ"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Touch the fingerprint sensor"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ໄອຄອນລາຍນິ້ວມື"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"ໄອຄອນແອັບພລິເຄຊັນ"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"ຊ່ວຍພື້ນທີ່ຂໍ້ຄວາມ"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"ກຳລັງຊອກຫາທ່ານ…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"ໄອຄອນໃບໜ້າ"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ປຸ່ມຊູມທີ່ໃຊ້ຮ່ວມກັນໄດ້."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ຊູມຈໍນ້ອຍໄປເປັນຈໍຂະຫນາດໃຫຍ່."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ເຊື່ອມຕໍ່ Bluetooth ແລ້ວ."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"ບ່ອນເກັບຂໍ້ມູນ"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"ຄຳໃບ້"</string>
     <string name="instant_apps" msgid="6647570248119804907">"ອິນສະແຕນແອັບ"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"ອິນສະແຕນແອັບບໍ່ຈຳເປັນຕ້ອງມີການຕິດຕັ້ງ."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> ກຳລັງເຮັດວຽກຢູ່"</string>
+    <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="2650669128861626071">"ໄປທີ່ໂປຣແກຣມທ່ອງເວັບ"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"ໄປທີ່ເວັບ"</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>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index b8ae38b..ac6cfc7 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -105,10 +105,12 @@
     <string name="camera_label" msgid="7261107956054836961">"atidaryti fotoaparatą"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Pasirinkti naują užduoties išdėstymą"</string>
     <string name="cancel" msgid="6442560571259935130">"Atšaukti"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Pagalbos pranešimo sritis"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Patvirtinkite"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Palieskite kontrolinio kodo jutiklį"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Kontrolinio kodo piktograma"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Programos piktograma"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Pagalbos pranešimo sritis"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Ieškoma jūsų…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Veido piktograma"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Suderinamumo priartinimo mygtukas."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Padidinti ekraną."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"„Bluetooth“ prijungtas."</string>
@@ -835,9 +837,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Saugykla"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Užuominos"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Akimirksniu įkeliamos programos"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Akimirksniu įkeliamų programų nereikia įdiegti."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"Programa „<xliff:g id="APP">%1$s</xliff:g>“ paleista"</string>
+    <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="2650669128861626071">"Eiti į naršyklę"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Eiti į žiniatinklį"</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>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 4a0ee10..01e2e39 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -104,10 +104,12 @@
     <string name="camera_label" msgid="7261107956054836961">"atvērt kameru"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Atlasiet jaunu uzdevumu izkārtojumu"</string>
     <string name="cancel" msgid="6442560571259935130">"Atcelt"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Palīdzības ziņojuma apgabals"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Apstiprināt"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Pieskarieties pirksta nospieduma sensoram"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Pirksta nospieduma ikona"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Lietojumprogrammas ikona"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Palīdzības ziņojuma apgabals"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Notiek jūsu sejas meklēšana…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Sejas ikona"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Saderības tālummaiņas poga."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Veikt tālummaiņu no mazāka ekrāna uz lielāku."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth savienojums ir izveidots."</string>
@@ -829,9 +831,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Krātuve"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Padomi"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Tūlītējās lietotnes"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Tūlītējām lietotnēm nav nepieciešama instalēšana."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"Lietotne <xliff:g id="APP">%1$s</xliff:g> darbojas"</string>
+    <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="2650669128861626071">"Atvērt pārlūku"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Pāriet uz tīmekli"</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>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index bf9cc35..8b4b458 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"отвори камера"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Изберете нов распоред на задача"</string>
     <string name="cancel" msgid="6442560571259935130">"Откажи"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Област за пораки за помош"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Потврди"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Допрете го сензорот за отпечатоци"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Икона за отпечатоци"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Икона за апликацијата"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Поле за пораки за помош"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Ве бараме вас…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Икона за лице"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Копче за компатибилност на зум."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Зумот е помал на поголем екран."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth е поврзан."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Капацитет"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Совети"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Инстант апликации"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Инстант апликациите нема потреба да се инсталираат."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"Се извршува <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <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="2650669128861626071">"Одете на прелистувач"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Одете на интернет"</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>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index fefd073..fc32b88 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"ക്യാമറ തുറക്കുക"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"പുതിയ ടാസ്‌ക് ലേഔട്ട് തിരഞ്ഞെടുക്കുക"</string>
     <string name="cancel" msgid="6442560571259935130">"റദ്ദാക്കുക"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"സഹായ സന്ദേശ ഏരിയ"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"സ്ഥിരീകരിക്കുക"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"വിരലടയാള സെൻസർ സ്‌പർശിക്കുക"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"വിരലടയാള ഐക്കൺ"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"ആപ്പ് ഐക്കൺ"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"സഹായ സന്ദേശ ഏരിയ"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"നിങ്ങൾക്കായി തിരയുന്നു…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"മുഖത്തിന്റെ ഐക്കൺ"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"അനുയോജ്യതാ സൂം ബട്ടൺ."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ചെറുതിൽ നിന്ന് വലിയ സ്‌ക്രീനിലേക്ക് സൂം ചെയ്യുക."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ബ്ലൂടൂത്ത് കണക്‌റ്റുചെയ്തു."</string>
@@ -823,9 +825,14 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"സ്റ്റോറേജ്"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"സൂചനകൾ"</string>
     <string name="instant_apps" msgid="6647570248119804907">"ഇൻസ്റ്റന്റ് ആപ്പ്"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"ഇൻസ്‌റ്റ‌ന്റ് ആപ്പിന് ഇൻസ്‌റ്റലേഷൻ ആവശ്യമില്ല."</string>
+    <!-- no translation found for instant_apps_title (8738419517367449783) -->
+    <skip />
+    <!-- no translation found for instant_apps_message (1183313016396018086) -->
+    <skip />
+    <!-- no translation found for instant_apps_message_with_help (6179830437630729747) -->
+    <skip />
     <string name="app_info" msgid="6856026610594615344">"ആപ്പ് വിവരം"</string>
-    <string name="go_to_web" msgid="2650669128861626071">"ബ്രൗസറിലേക്ക് പോവുക"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"വെബിൽ പോവുക"</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>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index e86dc64..331e9b7 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -101,10 +101,12 @@
     <string name="camera_label" msgid="7261107956054836961">"камер нээх"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Шинэ ажиллах талбарыг сонгоно уу"</string>
     <string name="cancel" msgid="6442560571259935130">"Цуцлах"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Тусламжийн зурвасын хэсэг"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Баталгаажуулах"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Хурууны хээ мэдрэгчид хүрэх"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Хурууны хээний дүрс тэмдэг"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Аппын дүрс тэмдэг"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Туслах зурвасын хэсэг"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Таныг хайж байна…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Царайны дүрс тэмдэг"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Тохиромжтой өсгөх товч."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Жижгээс том дэлгэцрүү өсгөх."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth холбогдсон."</string>
@@ -821,9 +823,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Хадгалах сан"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Заавар"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Шуурхай апп"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Шуурхай аппыг суулгах шаардлагагүй."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g>-г ажиллуулж байна"</string>
+    <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="2650669128861626071">"Хөтчид очих"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Вэбэд очих"</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>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index a9f9af4..33761ca 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"कॅमेरा उघडा"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"नवीन कार्य लेआउट निवडा"</string>
     <string name="cancel" msgid="6442560571259935130">"रद्द करा"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"मदत मेसेज परिसर"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"खात्री करा"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"फिंगरप्रिंट सेन्सरला स्पर्श करा"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"फिंगरप्रिंट आयकन"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"अॅप्लिकेशन आयकन"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"मदत मेसेज क्षेत्र"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"तुमच्यासाठी शोधत आहे…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"चेहरा आयकन"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"सुसंगतता झूम बटण."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"लहानपासून मोठ्‍या स्‍क्रीनवर झूम करा."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ब्लूटूथ कनेक्‍ट केले."</string>
@@ -823,9 +825,14 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"स्टोरेज"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"सूचना"</string>
     <string name="instant_apps" msgid="6647570248119804907">"इन्सटंट अ‍ॅप्स"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"इन्सटंट अॅप्सना स्थापनेची आवश्यकता नसते."</string>
+    <!-- no translation found for instant_apps_title (8738419517367449783) -->
+    <skip />
+    <!-- no translation found for instant_apps_message (1183313016396018086) -->
+    <skip />
+    <!-- no translation found for instant_apps_message_with_help (6179830437630729747) -->
+    <skip />
     <string name="app_info" msgid="6856026610594615344">"अॅप माहिती"</string>
-    <string name="go_to_web" msgid="2650669128861626071">"ब्राउझरवर जा"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"वेबवर जा"</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>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 6ec7889..d6a71ef 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"buka kamera"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Pilih reka letak tugas baharu"</string>
     <string name="cancel" msgid="6442560571259935130">"Batal"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Bahagian mesej bantuan"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Sahkan"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Sentuh penderia cap jari"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikon cap jari"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Ikon aplikasi"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Bahagian mesej bantuan"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Mencari anda…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Ikon wajah"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Butang zum keserasian."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Skrin zum lebih kecil kepada lebih besar."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth disambungkan."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Storan"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Pembayang"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Apl Segera"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Apl segera tidak memerlukan pemasangan."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> sedang berjalan"</string>
+    <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="2650669128861626071">"Pergi ke penyemak imbas"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Pergi ke web"</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>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 7afb3b9..2a6e3c2 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"ကင်မရာ ဖွင့်ရန်"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"အလုပ်သစ်စီစဥ်မှုကို ရွေးပါ။"</string>
     <string name="cancel" msgid="6442560571259935130">"မလုပ်တော့"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"အကူအညီမက်ဆေ့ဂျ် နေရာ"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"အတည်ပြုပါ"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"လက်ဗွေအာရုံခံကိရိယာကို တို့ပါ"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"လက်ဗွေ သင်္ကေတ"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"အပလီကေးရှင်း သင်္ကေတ"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"အကူအညီမက်ဆေ့ဂျ် နေရာ"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"သင့်ကို ရှာဖွေနေသည်…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"မျက်နှာသင်္ကေတ"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"အံဝင်ခွင်ကျ ဇူးမ်ခလုတ်"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ဖန်သားပြင်ပေါ်တွင် အသေးမှအကြီးသို့ ဇူးမ်ဆွဲခြင်း"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ဘလူးတုသ်ချိတ်ဆက်ထားမှု"</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"သိုလှောင်မှုများ"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"အရိပ်အမြွက်များ"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"ချက်ခြင်းသုံးအက်ပ်များကို ထည့်သွင်းစရာမလိုပါ။"</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> လုပ်ဆောင်နေသည်"</string>
+    <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="2650669128861626071">"ဘရောင်ဇာသို့ သွားပါ"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"ဝဘ်သို့ သွားရန်"</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>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index b817877..d90eba3 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"åpne kamera"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Velg en ny utforming for oppgaver"</string>
     <string name="cancel" msgid="6442560571259935130">"Avbryt"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Område for hjelpemelding"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Bekreft"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Trykk på fingeravtrykkssensoren"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikon for fingeravtrykk"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Appikon"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Område for hjelpemelding"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Ser etter deg …"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Ansiktikon"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Zoomknapp for kompatibilitet."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom fra mindre til større skjerm."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth er tilkoblet."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Lagring"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Hint"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Du trenger ikke å installere instant-apper."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> kjører"</string>
+    <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="2650669128861626071">"Gå til nettleser"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Gå til nettstedet"</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>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 6cc405f..4e3cddd 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"क्यामेरा खोल्नुहोस्"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"नयाँ कार्य लेआउट चयन गर्नुहोस्"</string>
     <string name="cancel" msgid="6442560571259935130">"रद्द गर्नुहोस्"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"मद्दतसम्बन्धी सन्देशको क्षेत्र"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"पुष्टि गर्नुहोस्"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"फिंगरप्रिन्ट सेन्सरमा छुनुहोस्‌"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"फिंगरप्रिन्ट जनाउने आइकन"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"अनुप्रयोग जनाउने आइकन"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"मद्दतसम्बन्धी सन्देशको क्षेत्र"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"तपाईंलाई खोज्दै…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"अनुहारको आइकन"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"मिलाउने जुम बटन।"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"स्क्रिनलाई सानोबाट ठूलो पार्नुहोस्।"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ब्लुटुथ जडान भयो।"</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"भण्डारण"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"सङ्केतहरू"</string>
     <string name="instant_apps" msgid="6647570248119804907">"तात्कालिक अनुप्रयोगहरू"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"तात्कालिक अनुप्रयोगहरूलाई स्थापना गर्नु पर्दैन|"</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> चलिरहेको छ"</string>
+    <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="2650669128861626071">"ब्राउजरमा जानुहोस्"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"वेबमा जानुहोस्"</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>
diff --git a/packages/SystemUI/res/values-night/styles.xml b/packages/SystemUI/res/values-night/styles.xml
new file mode 100644
index 0000000..3ab6b56
--- /dev/null
+++ b/packages/SystemUI/res/values-night/styles.xml
@@ -0,0 +1,27 @@
+<?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">
+
+    <style name="Theme.SystemUI.Dialog" parent="@android:style/Theme.DeviceDefault.Dialog" />
+
+    <style name="Theme.SystemUI.Dialog.Alert" parent="@*android:style/Theme.DeviceDefault.Dialog.Alert" />
+
+    <style name="Theme.SystemUI.Dialog.GlobalActions" parent="@android:style/Theme.DeviceDefault.NoActionBar.Fullscreen">
+        <item name="android:windowIsFloating">true</item>
+    </style>
+
+</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index e8c6f8d..9dda44e 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"camera openen"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Nieuwe taakindeling selecteren"</string>
     <string name="cancel" msgid="6442560571259935130">"Annuleren"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Gebied voor Help-berichten"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Bevestigen"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Raak de vingerafdruksensor aan"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Vingerafdrukpictogram"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"App-pictogram"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Gebied voor Help-berichten"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Jouw gezicht zoeken…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Gezichtspictogram"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Knop voor compatibiliteitszoom."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Kleiner scherm uitzoomen naar groter scherm."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth-verbinding ingesteld."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Opslag"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Hints"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Instant-apps"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Instant-apps hoeven niet te worden geïnstalleerd."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> actief"</string>
+    <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="2650669128861626071">"Ga naar browser"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Ga naar internet"</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>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 277181f..91c62bb 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"କ୍ୟାମେରା ଖୋଲନ୍ତୁ"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"ନୂଆ ଟାସ୍କ ଲେଆଉଟ୍‍ ଚୟନ କରନ୍ତୁ"</string>
     <string name="cancel" msgid="6442560571259935130">"କ୍ୟାନ୍ସଲ୍‍ କରନ୍ତୁ"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"ସାହାଯ୍ୟ ମେସେଜ୍ କ୍ଷେତ୍ର"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"ନିଶ୍ଚିତ କରନ୍ତୁ"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ସେନସର୍‌କୁ ଛୁଅଁନ୍ତୁ"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ଆଇକନ୍"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"ଆପ୍ଲିକେଶନ୍‌ ଆଇକନ୍‌"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"ହେଲ୍ପ ମେସେଜ୍ କ୍ଷେତ୍ର"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"ଆପଣଙ୍କୁ ଚିହ୍ନଟ କରୁଛି…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"ମୁହଁ ଆଇକନ୍"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"କମ୍ପାଟିବିଲିଟୀ ଜୁମ୍ ବଟନ୍।"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ଜୁମ୍ କରି ସ୍କ୍ରୀନ୍‌କୁ ଛୋଟରୁ ବଡ଼ କରନ୍ତୁ।"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ବ୍ଲୁ-ଟୂଥ୍‍‌ ସଂଯୋଗ କରାଯାଇଛି।"</string>
@@ -823,9 +825,14 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"ଷ୍ଟୋରେଜ୍‌"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"ହିଣ୍ଟ"</string>
     <string name="instant_apps" msgid="6647570248119804907">"ଇନଷ୍ଟାଣ୍ଟ ଆପ୍‌"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"ଇନଷ୍ଟାଣ୍ଟ ଆପ୍‌ ଇନଷ୍ଟଲ୍‍ କରିବାର ଆବଶ୍ୟକତା ନାହିଁ"</string>
+    <!-- no translation found for instant_apps_title (8738419517367449783) -->
+    <skip />
+    <!-- no translation found for instant_apps_message (1183313016396018086) -->
+    <skip />
+    <!-- no translation found for instant_apps_message_with_help (6179830437630729747) -->
+    <skip />
     <string name="app_info" msgid="6856026610594615344">"ଆପ୍‍ ସୂଚନା"</string>
-    <string name="go_to_web" msgid="2650669128861626071">"ବ୍ରାଉଜର୍‌କୁ ଯାଆନ୍ତୁ"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"ୱେବକୁ ଯାଆନ୍ତୁ"</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>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 6509871..96fb641 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"ਕੈਮਰਾ ਖੋਲ੍ਹੋ"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"ਨਵਾਂ ਕੰਮ ਲੇਆਉਟ ਚੁਣੋ"</string>
     <string name="cancel" msgid="6442560571259935130">"ਰੱਦ ਕਰੋ"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"ਮਦਦ ਸੁਨੇਹਾ ਖੇਤਰ"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"ਪੁਸ਼ਟੀ ਕਰੋ"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਨੂੰ ਸਪੱਰਸ਼ ਕਰੋ"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਦਾ ਪ੍ਰਤੀਕ"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"ਐਪਲੀਕੇਸ਼ਨ ਦਾ ਪ੍ਰਤੀਕ"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"ਮਦਦ ਸੁਨੇਹਾ ਖੇਤਰ"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"ਤੁਹਾਡੀ ਪਛਾਣ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"ਚਿਹਰਾ ਪ੍ਰਤੀਕ"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ਅਨੁਰੂਪਤਾ ਜ਼ੂਮ ਬਟਨ।"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ਵੱਡੀ ਸਕ੍ਰੀਨ ਤੇ ਛੋਟਾ ਜ਼ੂਮ ਕਰੋ।"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth ਕਨੈਕਟ ਕੀਤੀ।"</string>
@@ -344,7 +346,7 @@
     <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ਸੀਮਾ"</string>
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ਚਿਤਾਵਨੀ"</string>
     <string name="quick_settings_work_mode_label" msgid="7608026833638817218">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ"</string>
-    <string name="quick_settings_night_display_label" msgid="3577098011487644395">"ਰਾਤਰੀ ਲਾਈਟ"</string>
+    <string name="quick_settings_night_display_label" msgid="3577098011487644395">"ਰਾਤ ਦੀ ਰੋਸ਼ਨੀ"</string>
     <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"ਸੂਰਜ ਛਿਪਣ \'ਤੇ ਚਾਲੂ"</string>
     <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>
@@ -823,9 +825,14 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"ਸਟੋਰੇਜ"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"ਸੰਕੇਤ"</string>
     <string name="instant_apps" msgid="6647570248119804907">"ਤਤਕਾਲ ਐਪਾਂ"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"ਤਤਕਾਲ ਐਪਾਂ ਨੂੰ ਸਥਾਪਨਾ ਦੀ ਲੋੜ ਨਹੀਂ ਹੈ।"</string>
+    <!-- no translation found for instant_apps_title (8738419517367449783) -->
+    <skip />
+    <!-- no translation found for instant_apps_message (1183313016396018086) -->
+    <skip />
+    <!-- no translation found for instant_apps_message_with_help (6179830437630729747) -->
+    <skip />
     <string name="app_info" msgid="6856026610594615344">"ਐਪ ਜਾਣਕਾਰੀ"</string>
-    <string name="go_to_web" msgid="2650669128861626071">"ਬ੍ਰਾਊਜ਼ਰ \'ਤੇ ਜਾਓ"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"ਵੈੱਬ \'ਤੇ ਜਾਓ"</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>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 2959a8d..28d24bf 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -105,10 +105,12 @@
     <string name="camera_label" msgid="7261107956054836961">"otwórz aparat"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Wybierz nowy układ zadań"</string>
     <string name="cancel" msgid="6442560571259935130">"Anuluj"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Obszar komunikatu pomocy"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Potwierdź"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Dotknij czytnika linii papilarnych"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikona odcisku palca"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Ikona aplikacji"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Obszar komunikatu pomocy"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Szukam Cię…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Ikona twarzy"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Przycisk powiększenia na potrzeby zgodności."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Powiększa mniejszy ekran do większego."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth połączony."</string>
@@ -835,9 +837,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Pamięć wewnętrzna"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Wskazówki"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Aplikacje błyskawiczne"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Aplikacji błyskawicznych nie trzeba instalować."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"Aplikacja <xliff:g id="APP">%1$s</xliff:g> działa"</string>
+    <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="2650669128861626071">"Otwórz przeglądarkę"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Wejdź na stronę internetową"</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>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index ba50c13..ab0f5f2 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"abrir câmera"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Selecionar novo layout da tarefa"</string>
     <string name="cancel" msgid="6442560571259935130">"Cancelar"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Área da mensagem de ajuda"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Confirmar"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Toque no sensor de impressão digital"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ícone de impressão digital"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Ícone do app"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Área da mensagem de ajuda"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Procurando você…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Ícone facial"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botão de zoom da compatibilidade."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Aumentar a tela com zoom."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth conectado."</string>
@@ -825,9 +827,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Armazenamento"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Dicas"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Os Instant Apps não requerem instalação."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> em execução"</string>
+    <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="2650669128861626071">"Abrir o navegador"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Acessar a Web"</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>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index a03dba2..fb0675a 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"abrir câmara"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Selecionar novo esquema de tarefa"</string>
     <string name="cancel" msgid="6442560571259935130">"Cancelar"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Área da mensagem de ajuda"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Confirmar"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Toque no sensor de impressões digitais."</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ícone de impressão digital"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Ícone de aplicação"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Área da mensagem de ajuda"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"À sua procura…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Ícone de rosto"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botão zoom de compatibilidade."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom menor para ecrã maior."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth ligado."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Armazenamento"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Sugestões"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Aplicações instantâneas"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"As Aplicações instantâneas não requerem instalação."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> em execução"</string>
+    <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="2650669128861626071">"Ir para o navegador"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Aceder à Web"</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>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index ba50c13..ab0f5f2 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"abrir câmera"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Selecionar novo layout da tarefa"</string>
     <string name="cancel" msgid="6442560571259935130">"Cancelar"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Área da mensagem de ajuda"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Confirmar"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Toque no sensor de impressão digital"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ícone de impressão digital"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Ícone do app"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Área da mensagem de ajuda"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Procurando você…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Ícone facial"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botão de zoom da compatibilidade."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Aumentar a tela com zoom."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth conectado."</string>
@@ -825,9 +827,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Armazenamento"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Dicas"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Os Instant Apps não requerem instalação."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> em execução"</string>
+    <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="2650669128861626071">"Abrir o navegador"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Acessar a Web"</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>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 149803b..9b5f5e1 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -104,10 +104,12 @@
     <string name="camera_label" msgid="7261107956054836961">"deschideți camera foto"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Selectați noul aspect pentru activitate"</string>
     <string name="cancel" msgid="6442560571259935130">"Anulați"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Zona mesajelor de ajutor"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Confirmați"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Atingeți senzorul de amprente"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Pictograma amprentă"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Pictograma aplicației"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Zona mesajelor de ajutor"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Vă căutăm…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Pictograma chip"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Buton zoom pentru compatibilitate."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Faceți zoom de la o imagine mai mică la una mai mare."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Conectat prin Bluetooth."</string>
@@ -831,9 +833,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Stocare"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Indicii"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Aplicații instantanee"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Aplicațiile instantanee nu necesită instalare."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> rulează"</string>
+    <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="2650669128861626071">"Accesați browserul"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Accesați pe web"</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>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 7a756cd..8069317 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -105,10 +105,12 @@
     <string name="camera_label" msgid="7261107956054836961">"Открыть камеру."</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Выберите другой макет"</string>
     <string name="cancel" msgid="6442560571259935130">"Отмена"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Справочное сообщение"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Подтвердить"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Прикоснитесь к сканеру отпечатков пальцев."</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Значок отпечатка пальца"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Значок приложения"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Справочное сообщение"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Поиск лица…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Значок лица"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Кнопка масштабирования (режим совместимости)"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Уменьшение изображения для увеличения свободного места на экране."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth-соединение установлено."</string>
@@ -837,9 +839,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Хранилище"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Подсказки"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Приложения с мгновенным запуском"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Приложения с мгновенным запуском не требуется устанавливать."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> уже здесь!"</string>
+    <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="2650669128861626071">"Перейти в браузер"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Перейти в браузер"</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>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index e29aeda..8802833 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"කැමරාව විවෘත කරන්න"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"නව කාර්යය සැකැස්ම තෝරන්න"</string>
     <string name="cancel" msgid="6442560571259935130">"අවලංගු කරන්න"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"උදවු පණිවිඩ ප්‍රදේශය"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"තහවුරු කරන්න"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"ඇඟිලි සලකුණු සංවේදකය ස්පර්ශ කරන්න"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ඇඟිලි සලකුණු නිරූපකය"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"යෙදුම් නිරූපකය"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"උදවු පණිවිඩ ප්‍රදේශය"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"ඔබව සොයමින්…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"මුහුණ නිරූපකය"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ගැළපෙන විශාලන බොත්තම."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"විශාල තිරය වෙත කුඩාව විශාලනය කරන්න."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"බ්ලූටූත් සම්බන්ධිතයි."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"ගබඩාව"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"ඉඟි"</string>
     <string name="instant_apps" msgid="6647570248119804907">"ක්ෂණික යෙදුම්"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"ක්ෂණික යෙදුම් ස්ථාපනය කිරීම අවශ්‍ය නොවේ."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> ධාවනය වෙමින්"</string>
+    <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="2650669128861626071">"බ්‍රවුසරය වෙත යන්න"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"වෙබය වෙත යන්න"</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>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 8193e3f..233a81b 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -105,10 +105,12 @@
     <string name="camera_label" msgid="7261107956054836961">"spustiť fotoaparát"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Vyberte nové rozloženie úlohy"</string>
     <string name="cancel" msgid="6442560571259935130">"Zrušiť"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Oblasť správy pomocníka"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Potvrdiť"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Klepnite na senzor odtlačkov prstov"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikona odtlačku prsta"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Ikona aplikácie"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Oblasť chybového hlásenia"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Hľadáme vás…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Ikona tváre"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Tlačidlo úpravy veľkosti z dôvodu kompatibility."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zväčšiť menší obrázok na väčšiu obrazovku."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth pripojené."</string>
@@ -837,9 +839,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Úložisko"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Tipy"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Okamžité aplikácie"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Okamžité aplikácie nevyžadujú inštaláciu."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"Aplikácia <xliff:g id="APP">%1$s</xliff:g> je spustená"</string>
+    <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="2650669128861626071">"Otvoriť prehliadač"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Prejsť na internet"</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>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 7169441..c7e661a 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -105,10 +105,12 @@
     <string name="camera_label" msgid="7261107956054836961">"odpri fotoaparat"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Izberite novo postavitev opravil"</string>
     <string name="cancel" msgid="6442560571259935130">"Prekliči"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Območje sporočila pomoči"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Potrdite"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Dotaknite se tipala prstnih odtisov"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikona prstnih odtisov"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Ikona aplikacije"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Območje sporočila pomoči"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Preverjanje vašega obraza …"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Ikona obraza"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Gumb povečave za združljivost."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Povečava manjšega na večji zaslon."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Povezava Bluetooth vzpostavljena."</string>
@@ -837,9 +839,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Shramba"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Namigi"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Nenamestljive aplikacije"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Nenamestljivih aplikacij ni treba namestiti."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"Aplikacija <xliff:g id="APP">%1$s</xliff:g> se izvaja"</string>
+    <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="2650669128861626071">"Odpri brskalnik"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Pojdi v splet"</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>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index f2903ef..f4d3d2a 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"hap kamerën"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Zgjidh strukturën e re të detyrës"</string>
     <string name="cancel" msgid="6442560571259935130">"Anulo"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Zona e mesazhit të ndihmës"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Konfirmo"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Prek sensorin e gjurmës së gishtit"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikona e gjurmës së gishtit"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Ikona e aplikacionit"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Zona e mesazhit të ndihmës"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Po të kërkojmë…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Ikona e fytyrës"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Butoni i zmadhimit të pajtueshmërisë."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zmadho nga një ekran i vogël në të madh."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Pajisja është lidhur me \"bluetooth\"."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Hapësira ruajtëse"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Sugjerimet"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Aplikacionet e çastit"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Aplikacionet e çastit nuk kërkojnë instalim."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"Po ekzekutohet <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <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="2650669128861626071">"Shko te shfletuesi"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Shko në ueb"</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>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index e77b080..5825231 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -104,10 +104,12 @@
     <string name="camera_label" msgid="7261107956054836961">"отвори камеру"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Изабери нови распоред задатака"</string>
     <string name="cancel" msgid="6442560571259935130">"Откажи"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Област поруке за помоћ"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Потврди"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Додирните сензор за отисак прста"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Икона отиска прста"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Икона апликације"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Област поруке за помоћ"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Тражимо вас…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Икона лица"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Дугме Зум компатибилности."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Зумирање са мањег на већи екран."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth је прикључен."</string>
@@ -829,9 +831,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Меморијски простор"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Савети"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Инстант апликације"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Инстант апликације не захтевају инсталацију."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"Апликација <xliff:g id="APP">%1$s</xliff:g> је покренута"</string>
+    <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="2650669128861626071">"Иди на прегледач"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Иди на веб"</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>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index ccc498e..7040ec2 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"öppna kameran"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Välj en ny layout för uppgiften"</string>
     <string name="cancel" msgid="6442560571259935130">"Avbryt"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Område för hjälpmeddelande"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Bekräfta"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Tryck på fingeravtryckssensorn"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikon för fingeravtryck"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Appikon"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Område för hjälpmeddelande"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Håller utkik efter dig …"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Ansiktsikon"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Knapp för kompatibilitetszoom."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zooma mindre skärm till större."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth ansluten."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Lagring"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Tips"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Snabbappar"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Snabbappar behöver inte installeras."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> körs"</string>
+    <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="2650669128861626071">"Öppna webbläsaren"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Öppna webbplatsen"</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>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 83e9997..0633e8a 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"fungua kamera"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Chagua muundo mpya wa kazi"</string>
     <string name="cancel" msgid="6442560571259935130">"Ghairi"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Sehemu ya ujumbe wa usaidizi"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Thibitisha"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Gusa kitambua alama ya kidole"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Aikoni ya alama ya kidole"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Aikoni ya programu"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Sehemu ya ujumbe wa usaidizi"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Inakutafuta…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Aikoni ya uso"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Kichupo cha kukuza kwa utangamanifu"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Kuza kidogo kwa skrini kubwa."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth imeunganishwa."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Hifadhi"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Vidokezo"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Programu Zinazofunguka Papo Hapo"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Huhitaji kusakinisha programu zinazofunguka papo hapo."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> inaendelea kutumika"</string>
+    <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="2650669128861626071">"Tumia kivinjari"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Nenda kwenye wavuti"</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>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 6f06ab5..469e797 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"கேமராவைத் திற"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"புதிய பணி தளவமைப்பைத் தேர்ந்தெடுக்கவும்"</string>
     <string name="cancel" msgid="6442560571259935130">"ரத்துசெய்"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"உதவிச் செய்திக்கான பகுதி"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"உறுதிப்படுத்துக"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"கைரேகை உணர்வியைத் தொடவும்"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"கைரேகை ஐகான்"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"பயன்பாட்டு ஐகான்"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"உதவிச் செய்திக்கான பகுதி"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"உங்கள் முகத்தைத் தேடுகிறது…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"முக ஐகான்"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"பொருந்துமாறு அளவை மாற்றும் பொத்தான்."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"சிறியதிலிருந்து பெரிய திரைக்கு அளவை மாற்றும்."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"புளூடூத் இணைக்கப்பட்டது."</string>
@@ -344,9 +346,9 @@
     <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> வரம்பு"</string>
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> எச்சரிக்கை"</string>
     <string name="quick_settings_work_mode_label" msgid="7608026833638817218">"பணி விவரம்"</string>
-    <string name="quick_settings_night_display_label" msgid="3577098011487644395">"இரவு ஒளி"</string>
+    <string name="quick_settings_night_display_label" msgid="3577098011487644395">"நைட் லைட்"</string>
     <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"மாலையில் ஆன் செய்"</string>
-    <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"சூரிய உதயம் வரை"</string>
+    <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>
@@ -823,9 +825,14 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"சேமிப்பிடம்"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"குறிப்புகள்"</string>
     <string name="instant_apps" msgid="6647570248119804907">"இன்ஸ்டண்ட் ஆப்ஸ்"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"இன்ஸ்டண்ட் பயன்பாடுகளுக்கு நிறுவல் தேவையில்லை."</string>
+    <!-- no translation found for instant_apps_title (8738419517367449783) -->
+    <skip />
+    <!-- no translation found for instant_apps_message (1183313016396018086) -->
+    <skip />
+    <!-- no translation found for instant_apps_message_with_help (6179830437630729747) -->
+    <skip />
     <string name="app_info" msgid="6856026610594615344">"பயன்பாட்டுத் தகவல்"</string>
-    <string name="go_to_web" msgid="2650669128861626071">"உலாவிக்குச் செல்"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"இணையத்திற்குச் செல்"</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>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 7c09699..5d869f1 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"కెమెరాను తెరువు"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"కొత్త విధి లేఅవుట్‌ను ఎంచుకోండి"</string>
     <string name="cancel" msgid="6442560571259935130">"రద్దు చేయి"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"సహాయ సందేశ ప్రాంతం"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"నిర్ధారించు"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"వేలిముద్ర సెన్సార్‌ను తాకండి"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"వేలిముద్ర చిహ్నం"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"అప్లికేషన్ చిహ్నం"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"సహాయ సందేశ ప్రాంతం"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"మీ కోసం చూస్తోంది…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"ముఖ చిహ్నం"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"అనుకూలత జూమ్ బటన్."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"చిన్న స్క్రీన్ నుండి పెద్దదానికి జూమ్ చేయండి."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"బ్లూటూత్ కనెక్ట్ చేయబడింది."</string>
@@ -823,9 +825,14 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"నిల్వ"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"సూచనలు"</string>
     <string name="instant_apps" msgid="6647570248119804907">"తక్షణ యాప్‌లు"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"తక్షణ అనువర్తనాలకు ఇన్‌స్టాలేషన్ అవసరం లేదు."</string>
+    <!-- no translation found for instant_apps_title (8738419517367449783) -->
+    <skip />
+    <!-- no translation found for instant_apps_message (1183313016396018086) -->
+    <skip />
+    <!-- no translation found for instant_apps_message_with_help (6179830437630729747) -->
+    <skip />
     <string name="app_info" msgid="6856026610594615344">"యాప్ సమాచారం"</string>
-    <string name="go_to_web" msgid="2650669128861626071">"బ్రౌజర్‌కు వెళ్లండి"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"వెబ్‌కు వెళ్లు"</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>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 1d59868..408c5a0 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"เปิดกล้อง"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"เลือกรูปแบบงานใหม่"</string>
     <string name="cancel" msgid="6442560571259935130">"ยกเลิก"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"พื้นที่ข้อความช่วยเหลือ"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"ยืนยัน"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"แตะเซ็นเซอร์ลายนิ้วมือ"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ไอคอนลายนิ้วมือ"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"ไอคอนแอปพลิเคชัน"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"พื้นที่ข้อความช่วยเหลือ"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"กำลังหาใบหน้าคุณ…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"ไอคอนใบหน้า"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ปุ่มซูมที่ใช้งานร่วมกันได้"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ซูมหน้าจอให้มีขนาดใหญ่ขึ้น"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"เชื่อมต่อบลูทูธแล้ว"</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"พื้นที่เก็บข้อมูล"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"คำแนะนำ"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Instant App"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Instant Apps ไม่ต้องใช้การติดตั้ง"</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> ทำงานอยู่"</string>
+    <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="2650669128861626071">"ไปที่เบราว์เซอร์"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"ไปที่เว็บ"</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>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 013acd4..8da4946 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"buksan ang camera"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Pumili ng bagong layout ng gawain"</string>
     <string name="cancel" msgid="6442560571259935130">"Kanselahin"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Lugar ng mensahe ng tulong"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Kumpirmahin"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Pindutin ang fingerprint sensor"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Icon ng fingerprint"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Icon ng application"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Lugar ng mensahe ng tulong"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Hinahanap ka…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Face icon"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Button ng zoom ng pagiging tugma."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Mag-zoom nang mas maliit sa mas malaking screen."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Nakakonekta ang Bluetooth."</string>
@@ -346,7 +348,7 @@
     <string name="quick_settings_work_mode_label" msgid="7608026833638817218">"Profile sa trabaho"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Night Light"</string>
     <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Mao-on sa sunset"</string>
-    <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Hanggang mag-umaga"</string>
+    <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Hanggang sunrise"</string>
     <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Mao-on sa ganap na <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Hanggang <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Storage"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Mga Hint"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Hindi kailangang i-install ang mga instant na app."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"Tumatakbo ang <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <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="2650669128861626071">"Pumunta sa browser"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Pumunta sa web"</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>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 9030113..de8ed9d 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"kamerayı aç"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Yeni görev düzenini seçin"</string>
     <string name="cancel" msgid="6442560571259935130">"İptal"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Yardım mesajı alanı"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Onaylayın"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Parmak izi sensörüne dokunun"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Parmak izi simgesi"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Uygulama simgesi"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Yardım mesajı alanı"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Yüzünüz tanınmaya çalışılıyor…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Yüz simgesi"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Uyumluluk zum düğmesi."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Daha büyük ekrana daha küçük yakınlaştır."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth bağlandı."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Depolama alanı"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"İpuçları"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Hazır Uygulamalar"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Hazır uygulamaların yüklenmesi gerekmez."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> çalışıyor"</string>
+    <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="2650669128861626071">"Tarayıcıya git"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Web\'e 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>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index cf21c0f..6c2e661 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -105,10 +105,12 @@
     <string name="camera_label" msgid="7261107956054836961">"відкрити камеру"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Виберіть новий макет завдання"</string>
     <string name="cancel" msgid="6442560571259935130">"Скасувати"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Область довідкового повідомлення"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Підтвердити"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Торкніться сканера відбитків пальців"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Значок відбитка пальця"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Значок додатка"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Область довідкового повідомлення"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Пошук обличчя…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Значок обличчя"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Кнопка масштабування сумісності."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Збільшення екрана."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth під’єднано."</string>
@@ -837,9 +839,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Пам’ять"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Поради"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Додатки з миттєвим запуском"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Додатки з миттєвим запуском не потрібно встановлювати."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> працює"</string>
+    <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="2650669128861626071">"Веб-переглядач"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Перейти на веб-сайт"</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>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index d2ee8c7..88391b0 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"کیمرا کھولیں"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"نئے کام کا لے آؤٹ منتخب کریں"</string>
     <string name="cancel" msgid="6442560571259935130">"منسوخ کریں"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"امدادی پیغام کا علاقہ"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"تصدیق کریں"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"فنگر پرنٹ سینسر پر ٹچ کریں"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"فنگر پرنٹ آئیکن"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"ایپلیکیشن کا آئیکن"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"امدادی پیغام کا علاقہ"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"آپ کے لیے تلاش کیا جا رہا ہے…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"چہرے کا آئیکن"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"مطابقت پذیری زوم بٹن۔"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"چھوٹی سے بڑی اسکرین پر زوم کریں۔"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"بلوٹوتھ مربوط ہے۔"</string>
@@ -823,9 +825,14 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"اسٹوریج"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"اشارات"</string>
     <string name="instant_apps" msgid="6647570248119804907">"فوری ایپس"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"فوری ایپس کو انسٹالیشن کی ضرورت نہیں ہے۔"</string>
+    <!-- no translation found for instant_apps_title (8738419517367449783) -->
+    <skip />
+    <!-- no translation found for instant_apps_message (1183313016396018086) -->
+    <skip />
+    <!-- no translation found for instant_apps_message_with_help (6179830437630729747) -->
+    <skip />
     <string name="app_info" msgid="6856026610594615344">"ایپ کی معلومات"</string>
-    <string name="go_to_web" msgid="2650669128861626071">"براؤزر پر جائیں"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"ویب پر جائیں"</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>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 2c45ab8..37d31c2 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"kamerani ochish"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Yangi vazifa tartibini tanlash"</string>
     <string name="cancel" msgid="6442560571259935130">"Bekor qilish"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Yordam xabari"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"OK"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Barmoq izi skaneriga tegining"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Barmoq izi belgisi"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Ilova belgisi"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Yordam xabari"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Yuzingiz tekshirilmoqda…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Yuz belgisi"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Kattalashtirish tugmasi mosligi."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Kattaroq ekran uchun kichikroqni kattalashtirish."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth ulandi."</string>
@@ -825,9 +827,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Xotira"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Maslahatlar"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Darhol ochiladigan ilovalar"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Darhol ochiladigan ilovalarni o‘rnatish shart emas."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> ishlamoqda"</string>
+    <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 oolish uchun bu yerga bosing."</string>
     <string name="app_info" msgid="6856026610594615344">"Ilova haqida"</string>
-    <string name="go_to_web" msgid="2650669128861626071">"Brauzerni ochish"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Brauzerga o‘tish"</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>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 8c5e10d..f476790 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"mở máy ảnh"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Chọn bố cục tác vụ mới"</string>
     <string name="cancel" msgid="6442560571259935130">"Hủy"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Vùng thông báo trợ giúp"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Xác nhận"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Chạm vào cảm biến vân tay"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Biểu tượng vân tay"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Biểu tượng ứng dụng"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Vùng thông báo trợ giúp"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Đang tìm kiếm bạn…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Biểu tượng khuôn mặt"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Nút thu phóng khả năng tương thích."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Thu phóng màn hình lớn hơn hoặc nhỏ hơn."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Đã kết nối bluetooth."</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Bộ nhớ"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Gợi ý"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Ứng dụng tức thì"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Ứng dụng tức thì không yêu cầu cài đặt."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> đang chạy"</string>
+    <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="2650669128861626071">"Đi tới trình duyệt"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Truy cập web"</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>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 6259bfd..aaa4c63 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"打开相机"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"选择新的任务布局"</string>
     <string name="cancel" msgid="6442560571259935130">"取消"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"帮助消息区域"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"确认"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"请触摸指纹传感器"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"指纹图标"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"应用图标"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"帮助消息区域"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"正在查找中…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"面孔图标"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"兼容性缩放按钮。"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"将小屏幕的图片放大在较大屏幕上显示。"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"蓝牙已连接。"</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"存储空间"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"提示"</string>
     <string name="instant_apps" msgid="6647570248119804907">"免安装应用"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"免安装应用无需安装就能使用。"</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"正在运行<xliff:g id="APP">%1$s</xliff:g>"</string>
+    <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="2650669128861626071">"转到浏览器"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"转到网页版"</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>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index aa19f4f..aad4b4f 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"開啟相機"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"選取新的工作版面配置"</string>
     <string name="cancel" msgid="6442560571259935130">"取消"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"說明訊息區域"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"確認"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"請輕觸指紋感應器"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"指紋圖示"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"應用程式圖示"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"說明訊息區域"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"正在搜尋您的臉孔…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"面孔圖示"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"相容性縮放按鈕。"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"將較小螢幕的畫面放大在較大螢幕上顯示。"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"藍牙連線已建立。"</string>
@@ -825,9 +827,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"儲存空間"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"提示"</string>
     <string name="instant_apps" msgid="6647570248119804907">"即時應用程式"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"即時應用程式無需安裝即可使用。"</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> 運作中"</string>
+    <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="2650669128861626071">"前往瀏覽器"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"前往網頁版"</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>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 363c610..6b88545 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"開啟攝影機"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"選取新工作版面配置"</string>
     <string name="cancel" msgid="6442560571259935130">"取消"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"說明訊息區域"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"確認"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"請輕觸指紋感應器"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"指紋圖示"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"應用程式圖示"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"說明訊息區域"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"正在尋找你的臉孔…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"臉孔圖示"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"相容性縮放按鈕。"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"將較小螢幕的畫面放大在較大螢幕上顯示。"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"藍牙連線已建立。"</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"儲存空間"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"提示"</string>
     <string name="instant_apps" msgid="6647570248119804907">"免安裝應用程式"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"免安裝應用程式不必安裝就能使用。"</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"正在執行「<xliff:g id="APP">%1$s</xliff:g>」"</string>
+    <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="2650669128861626071">"前往瀏覽器"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"前往網頁版"</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>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 0e4729b..085c3b3 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -103,10 +103,12 @@
     <string name="camera_label" msgid="7261107956054836961">"vula ikhamera"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"Khetha isakhiwo somsebenzi omusha"</string>
     <string name="cancel" msgid="6442560571259935130">"Khansela"</string>
+    <string name="accessibility_biometric_dialog_help_area" msgid="8953787076940186847">"Indawo yosizo lomlayezo"</string>
+    <string name="biometric_dialog_confirm" msgid="6468457350041712674">"Qinisekisa"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Thinta inzwa yesigxivizo somunwe"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Isithonjana sezigxivizo zeminwe"</string>
-    <string name="accessibility_fingerprint_dialog_app_icon" msgid="3228052542929174609">"Isithonjana sohlelo lokusebenza"</string>
-    <string name="accessibility_fingerprint_dialog_help_area" msgid="5730471601819225159">"Indawo yosizo lomlayezo"</string>
+    <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Kufunwa wena…"</string>
+    <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Isithonjana sobuso"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Inkinobho evumelekile yokusondeza"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Sondeza kancane esikrinini esikhudlwana"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth ixhunyiwe"</string>
@@ -823,9 +825,11 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Isitoreji"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Ukubonisa"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Izinhlelo zokusebenza ezisheshayo"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Izinhlelo zokusebenza ezisheshayo azidingi ukufakwa."</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> esebenzayo"</string>
+    <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="2650669128861626071">"Iya kusiphequluli"</string>
+    <string name="go_to_web" msgid="1106022723459948514">"Iya kuwebhu"</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>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index a3306d3..2b51aaa 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2138,14 +2138,23 @@
     <!-- App label of the instant apps notification [CHAR LIMIT=60] -->
     <string name="instant_apps">Instant Apps</string>
 
-    <!-- Message of the instant apps notification indicating they don't need install [CHAR LIMIT=NONE] -->
-    <string name="instant_apps_message">Instant apps don\'t require installation.</string>
+    <!-- Title of notification indicating that an instant app is running. [CHAR LIMIT=60] -->
+    <string name="instant_apps_title"><xliff:g id="app" example="Gmail">%1$s</xliff:g> running</string>
+
+    <!-- Message of the instant apps notification indicating they don't need install. [CHAR LIMIT=NONE] -->
+    <string name="instant_apps_message">App opened without being installed.</string>
+
+    <!-- Message of the instant apps notification indicating they don't need install, plus a link to more information. [CHAR LIMIT=NONE] -->
+    <string name="instant_apps_message_with_help">App opened without being installed. Tap to learn more.</string>
+
+    <!-- URL of the webpage that explains instant apps. -->
+    <string name="instant_apps_help_url" translatable="false"></string>
 
     <!-- Action label for launching app info on the specified app [CHAR LIMIT=20] -->
     <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 browser</string>
+    <string name="go_to_web">Go to web</string>
 
     <!-- Quick settings tile for toggling mobile data [CHAR LIMIT=20] -->
     <string name="mobile_data">Mobile data</string>
diff --git a/packages/SystemUI/shared/Android.bp b/packages/SystemUI/shared/Android.bp
index 710b5f7..defc49b 100644
--- a/packages/SystemUI/shared/Android.bp
+++ b/packages/SystemUI/shared/Android.bp
@@ -20,6 +20,10 @@
         "src/**/I*.aidl",
     ],
 
+    static_libs: [
+        "SystemUIPluginLib"
+    ],
+
     // Enforce that the library is build agains java 7 so that there are
     // no compatibility issues with launcher
     java_version: "1.7",
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInitializer.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInitializer.java
new file mode 100644
index 0000000..9857894
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInitializer.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 com.android.systemui.shared.plugins;
+
+import android.content.Context;
+import android.os.Looper;
+
+/**
+ * Provides necessary components for initializing {@link PluginManagerImpl}.
+ */
+public interface PluginInitializer {
+
+    Looper getBgLooper();
+
+    /**
+     * This Runnable is run on the bg looper during initialization of {@link PluginManagerImpl}.
+     * It can be null.
+     */
+    Runnable getBgInitCallback();
+
+    String[] getWhitelistedPlugins(Context context);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java
similarity index 95%
rename from packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java
rename to packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java
index 7bc7e5f..e80c079 100644
--- a/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java
@@ -12,7 +12,7 @@
  * permissions and limitations under the License.
  */
 
-package com.android.systemui.plugins;
+package com.android.systemui.shared.plugins;
 
 import android.app.Notification;
 import android.app.Notification.Action;
@@ -39,12 +39,14 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
-import com.android.systemui.plugins.VersionInfo.InvalidVersionException;
+import com.android.systemui.plugins.Plugin;
+import com.android.systemui.plugins.PluginFragment;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.shared.plugins.VersionInfo.InvalidVersionException;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-import com.android.systemui.R;
 
 public class PluginInstanceManager<T extends Plugin> {
 
@@ -71,8 +73,7 @@
     PluginInstanceManager(Context context, String action, PluginListener<T> listener,
             boolean allowMultiple, Looper looper, VersionInfo version, PluginManagerImpl manager) {
         this(context, context.getPackageManager(), action, listener, allowMultiple, looper, version,
-                manager, Build.IS_DEBUGGABLE,
-                context.getResources().getStringArray(R.array.config_pluginWhitelist));
+                manager, Build.IS_DEBUGGABLE, manager.getWhitelistedPlugins());
     }
 
     @VisibleForTesting
@@ -114,7 +115,7 @@
 
     public void destroy() {
         if (DEBUG) Log.d(TAG, "stopListening");
-        ArrayList<PluginInfo> plugins = new ArrayList<>(mPluginHandler.mPlugins);
+        ArrayList<PluginInfo> plugins = new ArrayList<PluginInfo>(mPluginHandler.mPlugins);
         for (PluginInfo plugin : plugins) {
             mMainHandler.obtainMessage(MainHandler.PLUGIN_DISCONNECTED,
                     plugin.mPlugin).sendToTarget();
@@ -132,7 +133,7 @@
 
     public boolean checkAndDisable(String className) {
         boolean disableAny = false;
-        ArrayList<PluginInfo> plugins = new ArrayList<>(mPluginHandler.mPlugins);
+        ArrayList<PluginInfo> plugins = new ArrayList<PluginInfo>(mPluginHandler.mPlugins);
         for (PluginInfo info : plugins) {
             if (className.startsWith(info.mPackage)) {
                 disable(info);
@@ -143,7 +144,7 @@
     }
 
     public boolean disableAll() {
-        ArrayList<PluginInfo> plugins = new ArrayList<>(mPluginHandler.mPlugins);
+        ArrayList<PluginInfo> plugins = new ArrayList<PluginInfo>(mPluginHandler.mPlugins);
         for (int i = 0; i < plugins.size(); i++) {
             disable(plugins.get(i));
         }
@@ -165,7 +166,7 @@
     }
 
     public <T> boolean dependsOn(Plugin p, Class<T> cls) {
-        ArrayList<PluginInfo> plugins = new ArrayList<>(mPluginHandler.mPlugins);
+        ArrayList<PluginInfo> plugins = new ArrayList<PluginInfo>(mPluginHandler.mPlugins);
         for (PluginInfo info : plugins) {
             if (info.mPlugin.getClass().getName().equals(p.getClass().getName())) {
                 return info.mVersion != null && info.mVersion.hasClass(cls);
diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginManager.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManager.java
similarity index 72%
rename from packages/SystemUI/src/com/android/systemui/plugins/PluginManager.java
rename to packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManager.java
index 298eaf1..208f4fe 100644
--- a/packages/SystemUI/src/com/android/systemui/plugins/PluginManager.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManager.java
@@ -12,10 +12,12 @@
  * permissions and limitations under the License.
  */
 
-package com.android.systemui.plugins;
+package com.android.systemui.shared.plugins;
 
 import android.text.TextUtils;
 
+import com.android.systemui.plugins.Plugin;
+import com.android.systemui.plugins.PluginListener;
 import com.android.systemui.plugins.annotations.ProvidesInterface;
 
 public interface PluginManager {
@@ -40,14 +42,17 @@
 
     <T> boolean dependsOn(Plugin p, Class<T> cls);
 
-    static <P> String getAction(Class<P> cls) {
-        ProvidesInterface info = cls.getDeclaredAnnotation(ProvidesInterface.class);
-        if (info == null) {
-            throw new RuntimeException(cls + " doesn't provide an interface");
+    class Helper {
+        public static <P> String getAction(Class<P> cls) {
+            ProvidesInterface info = cls.getDeclaredAnnotation(ProvidesInterface.class);
+            if (info == null) {
+                throw new RuntimeException(cls + " doesn't provide an interface");
+            }
+            if (TextUtils.isEmpty(info.action())) {
+                throw new RuntimeException(cls + " doesn't provide an action");
+            }
+            return info.action();
         }
-        if (TextUtils.isEmpty(info.action())) {
-            throw new RuntimeException(cls + " doesn't provide an action");
-        }
-        return info.action();
     }
+
 }
diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginManagerImpl.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java
similarity index 90%
rename from packages/SystemUI/src/com/android/systemui/plugins/PluginManagerImpl.java
rename to packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java
index 1cbf1fe..7f1d161 100644
--- a/packages/SystemUI/src/com/android/systemui/plugins/PluginManagerImpl.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java
@@ -12,7 +12,7 @@
  * permissions and limitations under the License.
  */
 
-package com.android.systemui.plugins;
+package com.android.systemui.shared.plugins;
 
 import android.app.Notification;
 import android.app.Notification.Action;
@@ -41,10 +41,11 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
-import com.android.systemui.Dependency;
-import com.android.systemui.R;
-import com.android.systemui.plugins.PluginInstanceManager.PluginContextWrapper;
-import com.android.systemui.plugins.PluginInstanceManager.PluginInfo;
+
+import com.android.systemui.plugins.Plugin;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.shared.plugins.PluginInstanceManager.PluginContextWrapper;
+import com.android.systemui.shared.plugins.PluginInstanceManager.PluginInfo;
 import com.android.systemui.plugins.annotations.ProvidesInterface;
 
 import dalvik.system.PathClassLoader;
@@ -79,31 +80,33 @@
     private Looper mLooper;
     private boolean mWtfsSet;
 
-    public PluginManagerImpl(Context context) {
+    public PluginManagerImpl(Context context, PluginInitializer initializer) {
         this(context, new PluginInstanceManagerFactory(), Build.IS_DEBUGGABLE,
-                context.getResources().getStringArray(R.array.config_pluginWhitelist),
-                Thread.getUncaughtExceptionPreHandler());
+                Thread.getUncaughtExceptionPreHandler(), initializer);
     }
 
     @VisibleForTesting
     PluginManagerImpl(Context context, PluginInstanceManagerFactory factory, boolean debuggable,
-            String[] whitelistedPlugins, UncaughtExceptionHandler defaultHandler) {
+            UncaughtExceptionHandler defaultHandler, PluginInitializer initializer) {
         mContext = context;
         mFactory = factory;
-        mLooper = Dependency.get(Dependency.BG_LOOPER);
+        mLooper = initializer.getBgLooper();
         isDebuggable = debuggable;
-        mWhitelistedPlugins.addAll(Arrays.asList(whitelistedPlugins));
+        mWhitelistedPlugins.addAll(Arrays.asList(initializer.getWhitelistedPlugins(mContext)));
         mPluginPrefs = new PluginPrefs(mContext);
 
         PluginExceptionHandler uncaughtExceptionHandler = new PluginExceptionHandler(
                 defaultHandler);
         Thread.setUncaughtExceptionPreHandler(uncaughtExceptionHandler);
-        new Handler(mLooper).post(() -> {
-            // Plugin dependencies that don't have another good home can go here, but
-            // dependencies that have better places to init can happen elsewhere.
-            Dependency.get(PluginDependencyProvider.class)
-                    .allowPluginDependency(ActivityStarter.class);
-        });
+
+        Runnable bgRunnable = initializer.getBgInitCallback();
+        if (bgRunnable != null) {
+            new Handler(mLooper).post(bgRunnable);
+        }
+    }
+
+    public String[] getWhitelistedPlugins() {
+        return mWhitelistedPlugins.toArray(new String[0]);
     }
 
     public <T extends Plugin> T getOneShotPlugin(Class<T> cls) {
@@ -121,7 +124,9 @@
         if (Looper.myLooper() != Looper.getMainLooper()) {
             throw new RuntimeException("Must be called from UI thread");
         }
-        PluginInstanceManager<T> p = mFactory.createPluginInstanceManager(mContext, action, null,
+        // Passing null causes compiler to complain about incompatible (generic) types.
+        PluginListener<Plugin> dummy = null;
+        PluginInstanceManager<T> p = mFactory.createPluginInstanceManager(mContext, action, dummy,
                 false, mLooper, cls, this);
         mPluginPrefs.addAction(action);
         PluginInfo<T> info = p.getPlugin();
@@ -140,7 +145,7 @@
 
     public <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<?> cls,
             boolean allowMultiple) {
-        addPluginListener(PluginManager.getAction(cls), listener, cls, allowMultiple);
+        addPluginListener(PluginManager.Helper.getAction(cls), listener, cls, allowMultiple);
     }
 
     public <T extends Plugin> void addPluginListener(String action, PluginListener<T> listener,
@@ -293,8 +298,12 @@
     public void handleWtfs() {
         if (!mWtfsSet) {
             mWtfsSet = true;
-            Log.setWtfHandler((tag, what, system) -> {
-                throw new CrashWhilePluginActiveException(what);
+            Log.setWtfHandler(new Log.TerribleFailureHandler() {
+                @Override
+                public void onTerribleFailure(String tag, Log.TerribleFailure what,
+                        boolean system) {
+                    throw new CrashWhilePluginActiveException(what);
+                }
             });
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginPrefs.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginPrefs.java
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/plugins/PluginPrefs.java
rename to packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginPrefs.java
index 3671b3c..c0c5d70 100644
--- a/packages/SystemUI/src/com/android/systemui/plugins/PluginPrefs.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginPrefs.java
@@ -12,7 +12,7 @@
  * permissions and limitations under the License.
  */
 
-package com.android.systemui.plugins;
+package com.android.systemui.shared.plugins;
 
 import android.content.Context;
 import android.content.SharedPreferences;
diff --git a/packages/SystemUI/src/com/android/systemui/plugins/VersionInfo.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/VersionInfo.java
similarity index 75%
rename from packages/SystemUI/src/com/android/systemui/plugins/VersionInfo.java
rename to packages/SystemUI/shared/src/com/android/systemui/shared/plugins/VersionInfo.java
index facfd98..bb845cd 100644
--- a/packages/SystemUI/src/com/android/systemui/plugins/VersionInfo.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/VersionInfo.java
@@ -12,7 +12,9 @@
  * permissions and limitations under the License.
  */
 
-package com.android.systemui.plugins;
+package com.android.systemui.shared.plugins;
+
+import android.util.ArrayMap;
 
 import com.android.systemui.plugins.annotations.Dependencies;
 import com.android.systemui.plugins.annotations.DependsOn;
@@ -20,7 +22,7 @@
 import com.android.systemui.plugins.annotations.Requirements;
 import com.android.systemui.plugins.annotations.Requires;
 
-import android.util.ArrayMap;
+import java.util.function.BiConsumer;
 
 public class VersionInfo {
 
@@ -73,25 +75,32 @@
     }
 
     public void checkVersion(VersionInfo plugin) throws InvalidVersionException {
-        ArrayMap<Class<?>, Version> versions = new ArrayMap<>(mVersions);
-        plugin.mVersions.forEach((aClass, version) -> {
-            Version v = versions.remove(aClass);
-            if (v == null) {
-                v = createVersion(aClass);
-            }
-            if (v == null) {
-                throw new InvalidVersionException(aClass.getSimpleName()
-                        + " does not provide an interface", false);
-            }
-            if (v.mVersion != version.mVersion) {
-                throw new InvalidVersionException(aClass, v.mVersion < version.mVersion, v.mVersion,
-                        version.mVersion);
+        final ArrayMap<Class<?>, Version> versions = new ArrayMap<>(mVersions);
+        plugin.mVersions.forEach(new BiConsumer<Class<?>, Version>() {
+            @Override
+            public void accept(Class<?> aClass, Version version) {
+                Version v = versions.remove(aClass);
+                if (v == null) {
+                    v = VersionInfo.this.createVersion(aClass);
+                }
+                if (v == null) {
+                    throw new InvalidVersionException(aClass.getSimpleName()
+                            + " does not provide an interface", false);
+                }
+                if (v.mVersion != version.mVersion) {
+                    throw new InvalidVersionException(aClass, v.mVersion < version.mVersion,
+                            v.mVersion,
+                            version.mVersion);
+                }
             }
         });
-        versions.forEach((aClass, version) -> {
-            if (version.mRequired) {
-                throw new InvalidVersionException("Missing required dependency "
-                        + aClass.getSimpleName(), false);
+        versions.forEach(new BiConsumer<Class<?>, Version>() {
+            @Override
+            public void accept(Class<?> aClass, Version version) {
+                if (version.mRequired) {
+                    throw new InvalidVersionException("Missing required dependency "
+                            + aClass.getSimpleName(), false);
+                }
             }
         });
     }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/view/RecentsTransition.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/view/RecentsTransition.java
index ab89043..e253360 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/view/RecentsTransition.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/view/RecentsTransition.java
@@ -21,13 +21,11 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.GraphicBuffer;
+import android.graphics.Picture;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IRemoteCallback;
 import android.os.RemoteException;
-import android.view.DisplayListCanvas;
-import android.view.RenderNode;
-import android.view.ThreadedRenderer;
 import android.view.View;
 
 import java.util.function.Consumer;
@@ -108,12 +106,10 @@
      *         null if we were unable to allocate a hardware bitmap.
      */
     public static Bitmap createHardwareBitmap(int width, int height, Consumer<Canvas> consumer) {
-        RenderNode node = RenderNode.create("RecentsTransition", null);
-        node.setLeftTopRightBottom(0, 0, width, height);
-        node.setClipToBounds(false);
-        DisplayListCanvas c = node.start(width, height);
-        consumer.accept(c);
-        node.end(c);
-        return ThreadedRenderer.createHardwareBitmap(node, width, height);
+        final Picture picture = new Picture();
+        final Canvas canvas = picture.beginRecording(width, height);
+        consumer.accept(canvas);
+        picture.endRecording();
+        return Bitmap.createBitmap(picture);
     }
 }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
index b04d047..c7910f9 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
@@ -342,6 +342,20 @@
     }
 
     /**
+     * Moves an already resumed task to the side of the screen to initiate split screen.
+     */
+    public boolean setTaskWindowingModeSplitScreenPrimary(int taskId, int createMode,
+            Rect initialBounds) {
+        try {
+            return ActivityTaskManager.getService().setTaskWindowingModeSplitScreenPrimary(taskId,
+                    createMode, true /* onTop */, false /* animate */, initialBounds,
+                    true /* showRecents */);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
      * Registers a task stack listener with the system.
      * This should be called on the main thread.
      */
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityOptionsCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityOptionsCompat.java
index 36fb3a7..7154f53 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityOptionsCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityOptionsCompat.java
@@ -21,6 +21,8 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 
 import android.app.ActivityOptions;
+import android.content.Context;
+import android.os.Handler;
 
 /**
  * Wrapper around internal ActivityOptions creation.
@@ -43,4 +45,17 @@
             RemoteAnimationAdapterCompat remoteAnimationAdapter) {
         return ActivityOptions.makeRemoteAnimation(remoteAnimationAdapter.getWrapped());
     }
+
+    public static ActivityOptions makeCustomAnimation(Context context, int enterResId,
+            int exitResId, final Runnable callback, final Handler callbackHandler) {
+        return ActivityOptions.makeCustomAnimation(context, enterResId, exitResId, callbackHandler,
+                new ActivityOptions.OnAnimationStartedListener() {
+                    @Override
+                    public void onAnimationStarted() {
+                        if (callback != null) {
+                            callbackHandler.post(callback);
+                        }
+                    }
+                });
+    }
 }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
index d83b36d..3191d14 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
@@ -151,6 +151,25 @@
         }
     }
 
+    public void setPipVisibility(final boolean visible) {
+        try {
+            WindowManagerGlobal.getWindowManagerService().setPipVisibility(visible);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Unable to reach window manager", e);
+        }
+    }
+
+    /**
+     * @return whether there is a soft nav bar.
+     */
+    public boolean hasSoftNavigationBar() {
+        try {
+            return WindowManagerGlobal.getWindowManagerService().hasNavigationBar();
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
     /**
      * @return The side of the screen where navigation bar is positioned.
      * @see #NAV_BAR_POS_RIGHT
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 5bbbc52..28eff46 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -14,7 +14,7 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.plugins.ClockPlugin;
 import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.shared.plugins.PluginManager;
 
 /**
  * Switch to show plugin clock when plugin is connected, otherwise it will show default clock.
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
index 5ffdc7b..2daa33b 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
@@ -377,6 +377,7 @@
 
     @Override
     public void onResume(int reason) {
+        displayDefaultSecurityMessage();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index b159b39..b8df3c06 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -342,12 +342,11 @@
                 case SimPuk:
                     // Shortcut for SIM PIN/PUK to go to directly to user's security screen or home
                     SecurityMode securityMode = mSecurityModel.getSecurityMode(targetUserId);
-                    if (securityMode != SecurityMode.None
-                            || !mLockPatternUtils.isLockScreenDisabled(
+                    if (securityMode == SecurityMode.None || mLockPatternUtils.isLockScreenDisabled(
                             KeyguardUpdateMonitor.getCurrentUser())) {
-                        showSecurityScreen(securityMode);
-                    } else {
                         finish = true;
+                    } else {
+                        showSecurityScreen(securityMode);
                     }
                     break;
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 10c8ec0..f1b53fe 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -86,9 +86,8 @@
 import com.android.internal.util.Preconditions;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.settingslib.WirelessUtils;
-import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
-
+import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.google.android.collect.Lists;
 
 import java.io.FileDescriptor;
@@ -2218,8 +2217,8 @@
         }
     }
 
-    private final SysUiTaskStackChangeListener
-            mTaskStackListener = new SysUiTaskStackChangeListener() {
+    private final TaskStackChangeListener
+            mTaskStackListener = new TaskStackChangeListener() {
         @Override
         public void onTaskStackChangedBackground() {
             try {
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index b2cf305..fe1fe1a 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -39,9 +39,10 @@
 import com.android.systemui.keyguard.ScreenLifecycle;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.PluginInitializerImpl;
 import com.android.systemui.plugins.PluginDependencyProvider;
-import com.android.systemui.plugins.PluginManager;
-import com.android.systemui.plugins.PluginManagerImpl;
+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;
@@ -236,7 +237,7 @@
                 new DeviceProvisionedControllerImpl(mContext));
 
         mProviders.put(PluginManager.class, () ->
-                new PluginManagerImpl(mContext));
+                new PluginManagerImpl(mContext, new PluginInitializerImpl()));
 
         mProviders.put(AssistManager.class, () ->
                 new AssistManager(getDependency(DeviceProvisionedController.class), mContext));
diff --git a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
index bd2b7a5..1af2156 100644
--- a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
@@ -16,6 +16,11 @@
 
 package com.android.systemui;
 
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
+import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_SWIPE_UP;
+import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON;
+import static com.android.systemui.shared.system.NavigationBarCompat.InteractionType;
+
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -33,11 +38,7 @@
 import android.provider.Settings;
 import android.util.Log;
 import android.view.MotionEvent;
-
 import com.android.systemui.OverviewProxyService.OverviewProxyListener;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.DockedFirstAnimationFrameEvent;
-import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.shared.recents.IOverviewProxy;
 import com.android.systemui.shared.recents.ISystemUiProxy;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -46,17 +47,11 @@
 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;
 import java.util.List;
 
-import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
-import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_SWIPE_UP;
-import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON;
-import static com.android.systemui.shared.system.NavigationBarCompat.InteractionType;
-
 /**
  * Class to send information from overview to launcher with a binder.
  */
@@ -133,7 +128,10 @@
             }
             long token = Binder.clearCallingIdentity();
             try {
-                EventBus.getDefault().post(new DockedFirstAnimationFrameEvent());
+                Divider divider = SysUiServiceProvider.getComponent(mContext, Divider.class);
+                if (divider != null) {
+                    divider.onDockedFirstAnimationFrame();
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -314,8 +312,7 @@
                 getDefaultInteractionFlags());
 
         // Listen for the package update changes.
-        if (SystemServicesProxy.getInstance(context)
-                .isSystemUser(mDeviceProvisionedController.getCurrentUser())) {
+        if (mDeviceProvisionedController.getCurrentUser() == UserHandle.USER_SYSTEM) {
             updateEnabledState();
             mDeviceProvisionedController.addCallback(mDeviceProvisionedCallback);
             IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
diff --git a/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java b/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java
index ddd4833..f6ad626 100644
--- a/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java
@@ -21,7 +21,7 @@
 import android.view.View;
 
 import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.plugins.ViewProvider;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
index f9dbf4a..fb343f9 100644
--- a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
@@ -22,27 +22,10 @@
 
 public interface RecentsComponent {
     void showRecentApps(boolean triggeredFromAltTab);
-    void showNextAffiliatedTask();
-    void showPrevAffiliatedTask();
 
     /**
      * Docks the top-most task and opens recents.
      */
-    boolean splitPrimaryTask(int dragMode, int stackCreateMode, Rect initialBounds,
+    boolean splitPrimaryTask(int stackCreateMode, Rect initialBounds,
             int metricsDockAction);
-
-    /**
-     * Called during a drag-from-navbar-in gesture.
-     *
-     * @param distanceFromTop the distance of the current drag in gesture from the top of the
-     *                        screen
-     */
-    void onDraggingInRecents(float distanceFromTop);
-
-    /**
-     * Called when the gesture to drag in recents ended.
-     *
-     * @param velocity the velocity of the finger when releasing it in pixels per second
-     */
-    void onDraggingInRecentsEnded(float velocity);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index 044cc5c..48181bc 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -187,9 +187,11 @@
 
         mOverlay.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
         mOverlay.setAlpha(0);
+        mOverlay.setAllowForceDark(false);
 
         mBottomOverlay.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
         mBottomOverlay.setAlpha(0);
+        mBottomOverlay.setAllowForceDark(false);
 
         updateViews();
 
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index a3b5395..0215fda 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -61,13 +61,14 @@
     public static final float SWIPED_FAR_ENOUGH_SIZE_FRACTION = 0.6f;
     static final float MAX_SCROLL_SIZE_FRACTION = 0.3f;
 
+    protected final Handler mHandler;
+
     private float mMinSwipeProgress = 0f;
     private float mMaxSwipeProgress = 1f;
 
     private final FlingAnimationUtils mFlingAnimationUtils;
     private float mPagingTouchSlop;
     private final Callback mCallback;
-    private final Handler mHandler;
     private final int mSwipeDirection;
     private final VelocityTracker mVelocityTracker;
     private final FalsingManager mFalsingManager;
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index b96a604..78053b2 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -34,7 +34,7 @@
 
 import com.android.systemui.plugins.OverlayPlugin;
 import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.StatusBarWindowController;
 import com.android.systemui.util.NotificationChannels;
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index bb82a54..8e29841 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -28,8 +28,8 @@
 import java.io.PrintWriter;
 
 import com.android.internal.os.BinderInternal;
-import com.android.systemui.plugins.PluginManager;
-import com.android.systemui.plugins.PluginManagerImpl;
+import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.shared.plugins.PluginManagerImpl;
 
 public class SystemUIService extends Service {
 
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
index e6026c1..21b21d9 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
@@ -44,7 +44,7 @@
     public static final int PULSE_REASON_SENSOR_PICKUP = 3;
     public static final int PULSE_REASON_SENSOR_DOUBLE_TAP = 4;
     public static final int PULSE_REASON_SENSOR_LONG_PRESS = 5;
-    public static final int PULSE_REASON_SENSOR_REACH = 6;
+    public static final int PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN = 6;
     public static final int REASON_SENSOR_WAKE_UP = 7;
 
     private static boolean sRegisterKeyguardCallback = true;
@@ -177,9 +177,9 @@
         log("state " + state);
     }
 
-    public static void traceReachWakeUp() {
+    public static void traceWakeLockScreenWakeUp() {
         if (!ENABLED) return;
-        log("reachWakeUp");
+        log("wakeLockScreenWakeUp");
     }
 
     public static void traceProximityResult(Context context, boolean near, long millis,
@@ -199,7 +199,7 @@
             case PULSE_REASON_SENSOR_PICKUP: return "pickup";
             case PULSE_REASON_SENSOR_DOUBLE_TAP: return "doubletap";
             case PULSE_REASON_SENSOR_LONG_PRESS: return "longpress";
-            case PULSE_REASON_SENSOR_REACH: return "reach";
+            case PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN: return "wakeLockScreen";
             case REASON_SENSOR_WAKE_UP: return "wakeup";
             default: throw new IllegalArgumentException("bad reason: " + pulseReason);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
index 36b2347..c566460 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
@@ -16,11 +16,15 @@
 
 package com.android.systemui.doze;
 
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.hardware.Sensor;
 import android.hardware.SensorEvent;
 import android.hardware.SensorEventListener;
 import android.hardware.SensorManager;
+import android.os.Build;
 import android.os.Handler;
 import android.os.Trace;
 import android.os.UserHandle;
@@ -31,7 +35,12 @@
 /**
  * Controls the screen brightness when dozing.
  */
-public class DozeScreenBrightness implements DozeMachine.Part, SensorEventListener {
+public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachine.Part,
+        SensorEventListener {
+    protected static final String ACTION_AOD_BRIGHTNESS =
+            "com.android.systemui.doze.AOD_BRIGHTNESS";
+    protected static final String BRIGHTNESS_BUCKET = "brightness_bucket";
+
     private final Context mContext;
     private final DozeMachine.Service mDozeService;
     private final DozeHost mDozeHost;
@@ -40,36 +49,52 @@
     private final Sensor mLightSensor;
     private final int[] mSensorToBrightness;
     private final int[] mSensorToScrimOpacity;
+    private final boolean mDebuggable;
 
     private boolean mRegistered;
     private int mDefaultDozeBrightness;
     private boolean mPaused = false;
     private int mLastSensorValue = -1;
 
+    /**
+     * Debug value used for emulating various display brightness buckets:
+     *
+     * {@code am broadcast -p com.android.systemui -a com.android.systemui.doze.AOD_BRIGHTNESS
+     * --ei brightness_bucket 1}
+     */
+    private int mDebugBrightnessBucket = -1;
+
+    @VisibleForTesting
     public DozeScreenBrightness(Context context, DozeMachine.Service service,
             SensorManager sensorManager, Sensor lightSensor, DozeHost host,
             Handler handler, int defaultDozeBrightness, int[] sensorToBrightness,
-            int[] sensorToScrimOpacity) {
+            int[] sensorToScrimOpacity, boolean debuggable) {
         mContext = context;
         mDozeService = service;
         mSensorManager = sensorManager;
         mLightSensor = lightSensor;
         mDozeHost = host;
         mHandler = handler;
+        mDebuggable = debuggable;
 
         mDefaultDozeBrightness = defaultDozeBrightness;
         mSensorToBrightness = sensorToBrightness;
         mSensorToScrimOpacity = sensorToScrimOpacity;
+
+        if (mDebuggable) {
+            IntentFilter filter = new IntentFilter();
+            filter.addAction(ACTION_AOD_BRIGHTNESS);
+            mContext.registerReceiverAsUser(this, UserHandle.ALL, filter, null, null);
+        }
     }
 
-    @VisibleForTesting
     public DozeScreenBrightness(Context context, DozeMachine.Service service,
             SensorManager sensorManager, Sensor lightSensor, DozeHost host,
             Handler handler, AlwaysOnDisplayPolicy policy) {
         this(context, service, sensorManager, lightSensor, host, handler,
                 context.getResources().getInteger(
                         com.android.internal.R.integer.config_screenBrightnessDoze),
-                policy.screenBrightnessArray, policy.dimmingScrimArray);
+                policy.screenBrightnessArray, policy.dimmingScrimArray, Build.IS_DEBUGGABLE);
     }
 
     @Override
@@ -87,7 +112,7 @@
                 resetBrightnessToDefault();
                 break;
             case FINISH:
-                setLightSensorEnabled(false);
+                onDestroy();
                 break;
         }
         if (newState != DozeMachine.State.FINISH) {
@@ -95,6 +120,13 @@
         }
     }
 
+    private void onDestroy() {
+        setLightSensorEnabled(false);
+        if (mDebuggable) {
+            mContext.unregisterReceiver(this);
+        }
+    }
+
     @Override
     public void onSensorChanged(SensorEvent event) {
         Trace.beginSection("DozeScreenBrightness.onSensorChanged" + event.values[0]);
@@ -110,7 +142,9 @@
 
     private void updateBrightnessAndReady() {
         if (mRegistered) {
-            int brightness = computeBrightness(mLastSensorValue);
+            int sensorValue = mDebugBrightnessBucket == -1
+                    ? mLastSensorValue : mDebugBrightnessBucket;
+            int brightness = computeBrightness(sensorValue);
             boolean brightnessReady = brightness > 0;
             if (brightnessReady) {
                 mDozeService.setDozeScreenBrightness(clampToUserSetting(brightness));
@@ -125,7 +159,7 @@
                 scrimOpacity = 255;
             } else if (brightnessReady) {
                 // Only unblank scrim once brightness is ready.
-                scrimOpacity = computeScrimOpacity(mLastSensorValue);
+                scrimOpacity = computeScrimOpacity(sensorValue);
             }
             if (scrimOpacity >= 0) {
                 mDozeHost.setAodDimmingScrim(scrimOpacity / 255f);
@@ -184,4 +218,9 @@
         }
     }
 
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        mDebugBrightnessBucket = intent.getIntExtra(BRIGHTNESS_BUCKET, -1);
+        updateBrightnessAndReady();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index f9dfb5d..7013947 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -113,10 +113,10 @@
                         true /* reports touch coordinates */,
                         true /* touchscreen */),
                 new TriggerSensor(
-                        findSensorWithType(config.reachSensorType()),
-                        Settings.Secure.DOZE_REACH_GESTURE,
+                        findSensorWithType(config.wakeLockScreenSensorType()),
+                        Settings.Secure.DOZE_WAKE_LOCK_SCREEN_GESTURE,
                         true /* configured */,
-                        DozeLog.PULSE_REASON_SENSOR_REACH,
+                        DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN,
                         false /* reports touch coordinates */,
                         false /* touchscreen */),
                 new WakeScreenSensor(),
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index 7339304..c61e10a 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -26,7 +26,7 @@
 import com.android.systemui.plugins.DozeServicePlugin;
 import com.android.systemui.plugins.DozeServicePlugin.RequestDoze;
 import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.shared.plugins.PluginManager;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 31548b9..cb91d78 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -128,7 +128,7 @@
         boolean isDoubleTap = pulseReason == DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP;
         boolean isPickup = pulseReason == DozeLog.PULSE_REASON_SENSOR_PICKUP;
         boolean isLongPress = pulseReason == DozeLog.PULSE_REASON_SENSOR_LONG_PRESS;
-        boolean isReach = pulseReason == DozeLog.PULSE_REASON_SENSOR_REACH;
+        boolean isWakeLockScreen = pulseReason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN;
 
         if (isLongPress) {
             requestPulse(pulseReason, sensorPerformedProxCheck);
@@ -141,7 +141,7 @@
                 if (isDoubleTap) {
                     mDozeHost.onDoubleTap(screenX, screenY);
                     mMachine.wakeUp();
-                } else if (isPickup || isReach) {
+                } else if (isPickup || isWakeLockScreen) {
                     mMachine.wakeUp();
                 } else {
                     mDozeHost.extendPulse();
@@ -156,8 +156,8 @@
             final boolean withinVibrationThreshold =
                     timeSinceNotification < mDozeParameters.getPickupVibrationThreshold();
             DozeLog.tracePickupWakeUp(mContext, withinVibrationThreshold);
-        } else if (isReach) {
-            DozeLog.traceReachWakeUp();
+        } else if (isWakeLockScreen) {
+            DozeLog.traceWakeLockScreenWakeUp();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java b/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java
index 745f312..d833c16 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java
@@ -19,9 +19,6 @@
 import com.android.internal.policy.IKeyguardDismissCallback;
 import com.android.systemui.Dependency;
 import com.android.systemui.UiOffloadThread;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.recents.misc.SystemServicesProxy;
-
 import java.util.ArrayList;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 757c821..4988f07 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1938,6 +1938,12 @@
             mStatusBarManager = (StatusBarManager)
                     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 {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
index 0cedf98..74f7706 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
@@ -19,7 +19,6 @@
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.app.ActivityTaskManager;
-import android.app.IActivityManager;
 import android.app.IActivityTaskManager;
 import android.app.KeyguardManager;
 import android.content.ComponentName;
@@ -29,11 +28,9 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.Log;
-
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
-import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.TaskStackChangeListener;
 
 public class WorkLockActivityController {
     private static final String TAG = WorkLockActivityController.class.getSimpleName();
@@ -111,7 +108,7 @@
         }
     }
 
-    private final SysUiTaskStackChangeListener mLockListener = new SysUiTaskStackChangeListener() {
+    private final TaskStackChangeListener mLockListener = new TaskStackChangeListener() {
         @Override
         public void onTaskProfileLocked(int taskId, int userId) {
             startWorkChallengeInTask(taskId, userId);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipUI.java b/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
index b7164cb..864a6f9 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
@@ -21,11 +21,12 @@
 
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
-
+import android.os.UserHandle;
+import android.os.UserManager;
 import com.android.systemui.SystemUI;
-import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.component.ExpandPipEvent;
 import com.android.systemui.statusbar.CommandQueue;
-
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
@@ -47,8 +48,8 @@
         }
 
         // Ensure that we are the primary user's SystemUI.
-        final int processUser = SystemServicesProxy.getInstance(mContext).getProcessUser();
-        if (!SystemServicesProxy.getInstance(mContext).isSystemUser(processUser)) {
+        final int processUser = UserManager.get(mContext).getUserHandle();
+        if (processUser != UserHandle.USER_SYSTEM) {
             throw new IllegalStateException("Non-primary Pip component not currently supported.");
         }
 
@@ -58,6 +59,7 @@
         mPipManager.initialize(mContext);
 
         getComponent(CommandQueue.class).addCallbacks(this);
+        putComponent(PipUI.class, this);
     }
 
     @Override
@@ -65,6 +67,10 @@
         mPipManager.showPictureInPictureMenu();
     }
 
+    public void expandPip() {
+        EventBus.getDefault().send(new ExpandPipEvent());
+    }
+
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/ForegroundThread.java b/packages/SystemUI/src/com/android/systemui/pip/phone/ForegroundThread.java
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/recents/misc/ForegroundThread.java
rename to packages/SystemUI/src/com/android/systemui/pip/phone/ForegroundThread.java
index 784ac4e..9bf46bb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/ForegroundThread.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/ForegroundThread.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.recents.misc;
+package com.android.systemui.pip.phone;
 
 import android.os.Handler;
 import android.os.HandlerThread;
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 5547e2d..9ce2606 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
@@ -19,21 +19,17 @@
 import android.content.Context;
 import android.graphics.PixelFormat;
 import android.graphics.Point;
-import android.graphics.PointF;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.view.View.OnLayoutChangeListener;
-import android.view.ViewGroup;
 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.recents.misc.SystemServicesProxy;
+import com.android.systemui.shared.system.WindowManagerWrapper;
 
 public class PipDismissViewController {
 
@@ -59,7 +55,7 @@
         if (mDismissView == null) {
             // Determine sizes for the view
             final Rect stableInsets = new Rect();
-            SystemServicesProxy.getInstance(mContext).getStableInsets(stableInsets);
+            WindowManagerWrapper.getInstance().getStableInsets(stableInsets);
             final Point windowSize = new Point();
             mWindowManager.getDefaultDisplay().getRealSize(windowSize);
             final int gradientHeight = mContext.getResources().getDimensionPixelSize(
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 ee15655..04746c1 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -17,7 +17,6 @@
 package com.android.systemui.pip.phone;
 
 import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.WindowManager.INPUT_CONSUMER_PIP;
 
 import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
@@ -36,15 +35,15 @@
 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;
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.component.ExpandPipEvent;
-import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
-import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 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;
 
 /**
@@ -72,7 +71,7 @@
     /**
      * Handler for system task stack changes.
      */
-    SysUiTaskStackChangeListener mTaskStackListener = new SysUiTaskStackChangeListener() {
+    TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
         @Override
         public void onActivityPinned(String packageName, int userId, int taskId, int stackId) {
             mTouchHandler.onActivityPinned();
@@ -80,7 +79,9 @@
             mMenuController.onActivityPinned();
             mAppOpsListener.onActivityPinned(packageName);
 
-            SystemServicesProxy.getInstance(mContext).setPipVisibility(true);
+            Dependency.get(UiOffloadThread.class).submit(() -> {
+                WindowManagerWrapper.getInstance().setPipVisibility(true);
+            });
         }
 
         @Override
@@ -93,7 +94,9 @@
             mTouchHandler.onActivityUnpinned(topActivity);
             mAppOpsListener.onActivityUnpinned();
 
-            SystemServicesProxy.getInstance(mContext).setPipVisibility(topActivity != null);
+            Dependency.get(UiOffloadThread.class).submit(() -> {
+                WindowManagerWrapper.getInstance().setPipVisibility(topActivity != null);
+            });
         }
 
         @Override
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 f0ab046..ce7da79 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -30,7 +30,6 @@
 import android.animation.ValueAnimator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.app.ActivityManager.StackInfo;
-import android.app.ActivityTaskManager;
 import android.app.IActivityManager;
 import android.app.IActivityTaskManager;
 import android.content.Context;
@@ -43,14 +42,11 @@
 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.recents.misc.ForegroundThread;
-import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.shared.system.WindowManagerWrapper;
 import com.android.systemui.statusbar.FlingAnimationUtils;
-
 import java.io.PrintWriter;
 
 /**
@@ -116,7 +112,7 @@
      */
     void onConfigurationChanged() {
         mSnapAlgorithm.onConfigurationChanged();
-        SystemServicesProxy.getInstance(mContext).getStableInsets(mStableInsets);
+        WindowManagerWrapper.getInstance().getStableInsets(mStableInsets);
     }
 
     /**
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 020c550..43e9db7 100755
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -16,6 +16,11 @@
 
 package com.android.systemui.pip.tv;
 
+import static android.app.ActivityTaskManager.INVALID_STACK_ID;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.view.Display.DEFAULT_DISPLAY;
+
 import android.app.ActivityManager;
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.ActivityManager.StackInfo;
@@ -44,22 +49,17 @@
 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;
 import com.android.systemui.pip.BasePipManager;
-import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
-import com.android.systemui.recents.misc.SystemServicesProxy;
 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;
 
-import static android.app.ActivityTaskManager.INVALID_STACK_ID;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.view.Display.DEFAULT_DISPLAY;
-
 /**
  * Manages the picture-in-picture (PIP) UI and states.
  */
@@ -630,7 +630,7 @@
         return false;
     }
 
-    private SysUiTaskStackChangeListener mTaskStackListener = new SysUiTaskStackChangeListener() {
+    private TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
         @Override
         public void onTaskStackChanged() {
             if (DEBUG) Log.d(TAG, "onTaskStackChanged()");
@@ -754,7 +754,9 @@
     }
 
     private void updatePipVisibility(final boolean visible) {
-        SystemServicesProxy.getInstance(mContext).setPipVisibility(visible);
+        Dependency.get(UiOffloadThread.class).submit(() -> {
+            WindowManagerWrapper.getInstance().setPipVisibility(visible);
+        });
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginDependencyProvider.java b/packages/SystemUI/src/com/android/systemui/plugins/PluginDependencyProvider.java
index c58d889..03daa95 100644
--- a/packages/SystemUI/src/com/android/systemui/plugins/PluginDependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/plugins/PluginDependencyProvider.java
@@ -18,6 +18,7 @@
 
 import com.android.systemui.Dependency;
 import com.android.systemui.plugins.PluginDependency.DependencyProvider;
+import com.android.systemui.shared.plugins.PluginManager;
 
 public class PluginDependencyProvider extends DependencyProvider {
 
diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginInitializerImpl.java b/packages/SystemUI/src/com/android/systemui/plugins/PluginInitializerImpl.java
new file mode 100644
index 0000000..108c2d0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/plugins/PluginInitializerImpl.java
@@ -0,0 +1,47 @@
+/*
+ * 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 android.content.Context;
+import android.os.Looper;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.shared.plugins.PluginInitializer;
+import com.android.systemui.R;
+
+public class PluginInitializerImpl implements PluginInitializer {
+    @Override
+    public Looper getBgLooper() {
+        return Dependency.get(Dependency.BG_LOOPER);
+    }
+
+    @Override
+    public Runnable getBgInitCallback() {
+        return new Runnable() {
+            @Override
+            public void run() {
+                // Plugin dependencies that don't have another good home can go here, but
+                // dependencies that have better places to init can happen elsewhere.
+                Dependency.get(PluginDependencyProvider.class)
+                        .allowPluginDependency(ActivityStarter.class);
+            }
+        };
+    }
+
+    @Override
+    public String[] getWhitelistedPlugins(Context context) {
+        return context.getResources().getStringArray(R.array.config_pluginWhitelist);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index fcd479c..4b5ab2a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -6,9 +6,7 @@
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
 import android.content.Context;
-
-import androidx.viewpager.widget.PagerAdapter;
-import androidx.viewpager.widget.ViewPager;
+import android.content.res.Resources;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.LayoutInflater;
@@ -18,6 +16,9 @@
 import android.view.animation.OvershootInterpolator;
 import android.widget.Scroller;
 
+import androidx.viewpager.widget.PagerAdapter;
+import androidx.viewpager.widget.ViewPager;
+
 import com.android.systemui.R;
 import com.android.systemui.qs.QSPanel.QSTileLayout;
 import com.android.systemui.qs.QSPanel.TileRecord;
@@ -224,7 +225,9 @@
     public boolean updateResources() {
         // Update bottom padding, useful for removing extra space once the panel page indicator is
         // hidden.
-        setPadding(0, 0, 0,
+        Resources res = getContext().getResources();
+        final int sidePadding = res.getDimensionPixelSize(R.dimen.notification_side_paddings);
+        setPadding(sidePadding, 0, sidePadding,
                 getContext().getResources().getDimensionPixelSize(
                         R.dimen.qs_paged_tile_layout_padding_bottom));
         boolean changed = false;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index c36cdf6..79e5086 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -256,7 +256,7 @@
     public void setExpanded(boolean expanded) {
         if (DEBUG) Log.d(TAG, "setExpanded " + expanded);
         mQsExpanded = expanded;
-        mQSPanel.setListening(mListening && mQsExpanded);
+        mQSPanel.setListening(mListening, mQsExpanded);
         updateQsState();
     }
 
@@ -287,8 +287,7 @@
         mListening = listening;
         mHeader.setListening(listening);
         mFooter.setListening(listening);
-        mQSPanel.setListening(mListening && mQsExpanded);
-        mQSPanel.getFooter().setListening(listening);
+        mQSPanel.setListening(mListening, mQsExpanded);
     }
 
     @Override
@@ -365,7 +364,11 @@
                 .setListener(new AnimatorListenerAdapter() {
                     @Override
                     public void onAnimationEnd(Animator animation) {
-                        getView().animate().setListener(null);
+                        if (getView() != null) {
+                            // The view could be destroyed before the animation completes when
+                            // switching users.
+                            getView().animate().setListener(null);
+                        }
                         mHeaderAnimating = false;
                         updateQsState();
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 7a57fdd..e98ef4c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -199,7 +199,11 @@
 
     public void openDetails(String subPanel) {
         QSTile tile = getTile(subPanel);
-        showDetailAdapter(true, tile.getDetailAdapter(), new int[]{getWidth() / 2, 0});
+        // If there's no tile with that name (as defined in QSFactoryImpl or other QSFactory),
+        // QSFactory will not be able to create a tile and getTile will return null
+        if (tile != null) {
+            showDetailAdapter(true, tile.getDetailAdapter(), new int[]{getWidth() / 2, 0});
+        }
     }
 
     private QSTile getTile(String subPanel) {
@@ -353,12 +357,21 @@
         if (mListening) {
             refreshAllTiles();
         }
-        if (mBrightnessView.getVisibility() == View.VISIBLE) {
-            if (listening) {
-                mBrightnessController.registerCallbacks();
-            } else {
-                mBrightnessController.unregisterCallbacks();
-            }
+    }
+
+    public void setListening(boolean listening, boolean expanded) {
+        setListening(listening && expanded);
+        getFooter().setListening(listening);
+        // Set the listening as soon as the QS fragment starts listening regardless of the expansion,
+        // so it will update the current brightness before the slider is visible.
+        setBrightnessListening(listening);
+    }
+
+    public void setBrightnessListening(boolean listening) {
+        if (listening) {
+            mBrightnessController.registerCallbacks();
+        } else {
+            mBrightnessController.unregisterCallbacks();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index 86e69e3..cefeeb5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -31,7 +31,7 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.plugins.PluginManager;
+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;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index 01ff72e..e884302 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -103,8 +103,7 @@
         // it will show all its tiles. In this case, the tiles have to be entered before the
         // container is measured. Any change in the tiles, should trigger a remeasure.
         final int numTiles = mRecords.size();
-        final int width = MeasureSpec.getSize(widthMeasureSpec)
-                - getPaddingStart() - getPaddingEnd();
+        final int width = MeasureSpec.getSize(widthMeasureSpec);
         final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
         if (heightMode == MeasureSpec.UNSPECIFIED) {
             mRows = (numTiles + mColumns - 1) / mColumns;
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 12daff1..9edd65e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
@@ -25,6 +25,7 @@
 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;
@@ -77,6 +78,9 @@
 
     @Override
     protected void handleClick() {
+        if (getAdapter() == null) {
+            return;
+        }
         if (!getAdapter().isEnabled()) {
             getAdapter().enable();
         } else {
@@ -96,13 +100,13 @@
 
     @Override
     protected void handleUpdateState(BooleanState state, Object arg) {
-        final Drawable mEnable = mContext.getDrawable(R.drawable.ic_qs_nfc_enabled);
-        final Drawable mDisable = mContext.getDrawable(R.drawable.ic_qs_nfc_disabled);
-
-        if (getAdapter() == null) return;
-        state.value = getAdapter().isEnabled();
+        state.value = getAdapter() != null && getAdapter().isEnabled();
+        state.state = getAdapter() == null
+                ? Tile.STATE_UNAVAILABLE
+                : state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
+        state.icon = ResourceIcon.get(
+                state.value ? R.drawable.ic_qs_nfc_enabled : R.drawable.ic_qs_nfc_disabled);
         state.label = mContext.getString(R.string.quick_settings_nfc_label);
-        state.icon = new DrawableIcon(state.value ? mEnable : mDisable);
         state.expandedAccessibilityClassName = Switch.class.getName();
         state.contentDescription = state.label;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl b/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl
index fc1831d..90c1099 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl
+++ b/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl
@@ -31,8 +31,7 @@
     void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
     void toggleRecents(int recentsGrowTarget);
     void onConfigurationChanged();
-    void splitPrimaryTask(int topTaskId, int dragMode, int stackCreateMode,
-            in Rect initialBounds);
+    void splitPrimaryTask(int topTaskId, int stackCreateMode, in Rect initialBounds);
     void onDraggingInRecents(float distanceFromTop);
     void onDraggingInRecentsEnded(float velocity);
     void showCurrentUserToast(int msgResId, int msgLength);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl b/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl
index 58d8d8f..e977144 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl
+++ b/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl
@@ -29,7 +29,7 @@
     void updateRecentsVisibility(boolean visible);
     void startScreenPinning(int taskId);
     void sendRecentsDrawnEvent();
-    void sendDockingTopTaskEvent(int dragMode, in Rect initialRect);
+    void sendDockingTopTaskEvent(in Rect initialRect);
     void sendLaunchRecentsEvent();
     void sendDockedFirstAnimationFrameEvent();
     void setWaitingForTransitionStartEvent(boolean waitingForTransitionStart);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 8bb3c02..74f6c2d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -53,6 +53,7 @@
 import com.android.systemui.R;
 import com.android.systemui.RecentsComponent;
 import com.android.systemui.SystemUIApplication;
+import com.android.systemui.recents.events.ui.RecentsGrowingEvent;
 import com.android.systemui.shared.recents.IOverviewProxy;
 import com.android.systemui.SystemUI;
 import com.android.systemui.recents.events.EventBus;
@@ -248,6 +249,10 @@
         mImpl.onBootCompleted();
     }
 
+    public void growRecents() {
+        EventBus.getDefault().send(new RecentsGrowingEvent());
+    }
+
     /**
      * Shows the Recents.
      */
@@ -463,7 +468,7 @@
     }
 
     @Override
-    public boolean splitPrimaryTask(int dragMode, int stackCreateMode, Rect initialBounds,
+    public boolean splitPrimaryTask(int stackCreateMode, Rect initialBounds,
             int metricsDockAction) {
         // Ensure the device has been provisioned before allowing the user to interact with
         // recents
@@ -495,16 +500,15 @@
                             runningTask.topActivity.flattenToShortString());
                 }
                 if (sSystemServicesProxy.isSystemUser(currentUser)) {
-                    mImpl.splitPrimaryTask(runningTask.id, dragMode, stackCreateMode,
-                            initialBounds);
+                    mImpl.splitPrimaryTask(runningTask.id, stackCreateMode, initialBounds);
                 } else {
                     if (mSystemToUserCallbacks != null) {
                         IRecentsNonSystemUserCallbacks callbacks =
                                 mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
                         if (callbacks != null) {
                             try {
-                                callbacks.splitPrimaryTask(runningTask.id, dragMode,
-                                        stackCreateMode, initialBounds);
+                                callbacks.splitPrimaryTask(runningTask.id, stackCreateMode,
+                                        initialBounds);
                             } catch (RemoteException e) {
                                 Log.e(TAG, "Callback failed", e);
                             }
@@ -552,53 +556,6 @@
         }
     }
 
-    @Override
-    public void onDraggingInRecents(float distanceFromTop) {
-        if (sSystemServicesProxy.isSystemUser(mDraggingInRecentsCurrentUser)) {
-            mImpl.onDraggingInRecents(distanceFromTop);
-        } else {
-            if (mSystemToUserCallbacks != null) {
-                IRecentsNonSystemUserCallbacks callbacks =
-                        mSystemToUserCallbacks.getNonSystemUserRecentsForUser(
-                                mDraggingInRecentsCurrentUser);
-                if (callbacks != null) {
-                    try {
-                        callbacks.onDraggingInRecents(distanceFromTop);
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Callback failed", e);
-                    }
-                } else {
-                    Log.e(TAG, "No SystemUI callbacks found for user: "
-                            + mDraggingInRecentsCurrentUser);
-                }
-            }
-        }
-    }
-
-    @Override
-    public void onDraggingInRecentsEnded(float velocity) {
-        if (sSystemServicesProxy.isSystemUser(mDraggingInRecentsCurrentUser)) {
-            mImpl.onDraggingInRecentsEnded(velocity);
-        } else {
-            if (mSystemToUserCallbacks != null) {
-                IRecentsNonSystemUserCallbacks callbacks =
-                        mSystemToUserCallbacks.getNonSystemUserRecentsForUser(
-                                mDraggingInRecentsCurrentUser);
-                if (callbacks != null) {
-                    try {
-                        callbacks.onDraggingInRecentsEnded(velocity);
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Callback failed", e);
-                    }
-                } else {
-                    Log.e(TAG, "No SystemUI callbacks found for user: "
-                            + mDraggingInRecentsCurrentUser);
-                }
-            }
-        }
-    }
-
-    @Override
     public void showNextAffiliatedTask() {
         // Ensure the device has been provisioned before allowing the user to interact with
         // recents
@@ -609,7 +566,6 @@
         mImpl.showNextAffiliatedTask();
     }
 
-    @Override
     public void showPrevAffiliatedTask() {
         // Ensure the device has been provisioned before allowing the user to interact with
         // recents
@@ -686,7 +642,12 @@
     public final void onBusEvent(DockedFirstAnimationFrameEvent event) {
         SystemServicesProxy ssp = Recents.getSystemServices();
         int processUser = ssp.getProcessUser();
-        if (!ssp.isSystemUser(processUser)) {
+        if (ssp.isSystemUser(processUser)) {
+            final Divider divider = getComponent(Divider.class);
+            if (divider != null) {
+                divider.onDockedFirstAnimationFrame();
+            }
+        } else {
             postToSystemUser(new Runnable() {
                 @Override
                 public void run() {
@@ -723,7 +684,12 @@
 
     public final void onBusEvent(final RecentsDrawnEvent event) {
         int processUser = sSystemServicesProxy.getProcessUser();
-        if (!sSystemServicesProxy.isSystemUser(processUser)) {
+        if (sSystemServicesProxy.isSystemUser(processUser)) {
+            final Divider divider = getComponent(Divider.class);
+            if (divider != null) {
+                divider.onRecentsDrawn();
+            }
+        } else {
             postToSystemUser(new Runnable() {
                 @Override
                 public void run() {
@@ -739,13 +705,17 @@
 
     public final void onBusEvent(final DockedTopTaskEvent event) {
         int processUser = sSystemServicesProxy.getProcessUser();
-        if (!sSystemServicesProxy.isSystemUser(processUser)) {
+        if (sSystemServicesProxy.isSystemUser(processUser)) {
+            final Divider divider = getComponent(Divider.class);
+            if (divider != null) {
+                divider.onDockedTopTask();
+            }
+        } else {
             postToSystemUser(new Runnable() {
                 @Override
                 public void run() {
                     try {
-                        mUserToSystemCallbacks.sendDockingTopTaskEvent(event.dragMode,
-                                event.initialRect);
+                        mUserToSystemCallbacks.sendDockingTopTaskEvent(event.initialRect);
                     } catch (RemoteException e) {
                         Log.e(TAG, "Callback failed", e);
                     }
@@ -756,7 +726,12 @@
 
     public final void onBusEvent(final RecentsActivityStartingEvent event) {
         int processUser = sSystemServicesProxy.getProcessUser();
-        if (!sSystemServicesProxy.isSystemUser(processUser)) {
+        if (sSystemServicesProxy.isSystemUser(processUser)) {
+            final Divider divider = getComponent(Divider.class);
+            if (divider != null) {
+                divider.onRecentsActivityStarting();
+            }
+        } else {
             postToSystemUser(new Runnable() {
                 @Override
                 public void run() {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 63a65d0..d95c731 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -49,6 +49,7 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.OverviewProxyService;
 import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.pip.phone.ForegroundThread;
 import com.google.android.collect.Lists;
 
 import com.android.internal.logging.MetricsLogger;
@@ -72,7 +73,6 @@
 import com.android.systemui.recents.events.ui.DraggingInRecentsEvent;
 import com.android.systemui.recents.events.ui.TaskSnapshotChangedEvent;
 import com.android.systemui.recents.misc.DozeTrigger;
-import com.android.systemui.recents.misc.ForegroundThread;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
 import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan;
@@ -690,14 +690,13 @@
         showRelativeAffiliatedTask(false);
     }
 
-    public void splitPrimaryTask(int taskId, int dragMode, int stackCreateMode,
-            Rect initialBounds) {
+    public void splitPrimaryTask(int taskId, int stackCreateMode, Rect initialBounds) {
         SystemServicesProxy ssp = Recents.getSystemServices();
 
         // Make sure we inform DividerView before we actually start the activity so we can change
         // the resize mode already.
         if (ssp.setTaskWindowingModeSplitScreenPrimary(taskId, stackCreateMode, initialBounds)) {
-            EventBus.getDefault().send(new DockedTopTaskEvent(dragMode, initialBounds));
+            EventBus.getDefault().send(new DockedTopTaskEvent(initialBounds));
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java
index beec4b3..a1da785 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java
@@ -87,12 +87,11 @@
     }
 
     @Override
-    public void splitPrimaryTask(int topTaskId, int dragMode, int stackCreateMode,
-            Rect initialBounds) throws RemoteException {
+    public void splitPrimaryTask(int topTaskId, int stackCreateMode, Rect initialBounds)
+            throws RemoteException {
         SomeArgs args = SomeArgs.obtain();
         args.argi1 = topTaskId;
-        args.argi2 = dragMode;
-        args.argi3 = stackCreateMode;
+        args.argi2 = stackCreateMode;
         args.arg1 = initialBounds;
         mHandler.sendMessage(mHandler.obtainMessage(MSG_DOCK_TOP_TASK, args));
     }
@@ -141,7 +140,7 @@
                     break;
                 case MSG_DOCK_TOP_TASK:
                     args = (SomeArgs) msg.obj;
-                    mImpl.splitPrimaryTask(args.argi1, args.argi2, args.argi3 = 0,
+                    mImpl.splitPrimaryTask(args.argi1, args.argi2 = 0,
                             (Rect) args.arg1);
                     break;
                 case MSG_ON_DRAGGING_IN_RECENTS:
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java
index ff1f7dc..c5e9f04 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java
@@ -26,13 +26,13 @@
 
 import com.android.systemui.EventLogConstants;
 import com.android.systemui.EventLogTags;
+import com.android.systemui.pip.phone.ForegroundThread;
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.DockedFirstAnimationFrameEvent;
 import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
 import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
 import com.android.systemui.recents.events.component.SetWaitingForTransitionStartEvent;
 import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
-import com.android.systemui.recents.misc.ForegroundThread;
 
 /**
  * An implementation of the system user's Recents interface to be called remotely by secondary
@@ -99,8 +99,8 @@
     }
 
     @Override
-    public void sendDockingTopTaskEvent(int dragMode, Rect initialRect) throws RemoteException {
-        EventBus.getDefault().post(new DockedTopTaskEvent(dragMode, initialRect));
+    public void sendDockingTopTaskEvent(Rect initialRect) throws RemoteException {
+        EventBus.getDefault().post(new DockedTopTaskEvent(initialRect));
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/DockedTopTaskEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/DockedTopTaskEvent.java
index f1bc214..9e3ced3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/DockedTopTaskEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/DockedTopTaskEvent.java
@@ -26,11 +26,9 @@
  */
 public class DockedTopTaskEvent extends EventBus.Event {
 
-    public int dragMode;
     public Rect initialRect;
 
-    public DockedTopTaskEvent(int dragMode, Rect initialRect) {
-        this.dragMode = dragMode;
+    public DockedTopTaskEvent(Rect initialRect) {
         this.initialRect = initialRect;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index 1178725..3ed5f70 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -460,7 +460,7 @@
 
     private void animateSliderTo(int target) {
         if (!mControlValueInitialized) {
-            // Don't animate the first value since it's default state isn't meaningful to users.
+            // Don't animate the first value since its default state isn't meaningful to users.
             mControl.setValue(target);
             mControlValueInitialized = true;
         }
@@ -470,10 +470,12 @@
         mSliderAnimator = ValueAnimator.ofInt(mControl.getValue(), target);
         mSliderAnimator.addUpdateListener((ValueAnimator animation) -> {
             mExternalChange = true;
-            mControl.setValue((int)animation.getAnimatedValue());
+            mControl.setValue((int) animation.getAnimatedValue());
             mExternalChange = false;
         });
-        mSliderAnimator.setDuration(SLIDER_ANIMATION_DURATION);
+        final long animationDuration = SLIDER_ANIMATION_DURATION * Math.abs(
+                mControl.getValue() - target) / GAMMA_SPACE_MAX;
+        mSliderAnimator.setDuration(animationDuration);
         mSliderAnimator.start();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
index 750002c..64fa8f8 100644
--- a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
@@ -18,11 +18,7 @@
 
 import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT;
 import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
-import static android.os.UserHandle.USER_CURRENT;
 
-import static com.android.systemui.statusbar.phone.NavigationBarGestureHelper.DRAG_MODE_NONE;
-
-import android.app.ActivityManager;
 import android.content.res.Configuration;
 import android.os.RemoteException;
 import android.util.Log;
@@ -30,17 +26,11 @@
 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;
-import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.stackdivider.DividerView;
-import com.android.systemui.statusbar.phone.NavigationBarGestureHelper;
-
-import java.util.List;
 
 /**
  * Dispatches shortcut to System UI components
@@ -94,7 +84,7 @@
             if (dockSide == WindowManager.DOCKED_INVALID) {
                 // Split the screen
                 Recents recents = getComponent(Recents.class);
-                recents.splitPrimaryTask(DRAG_MODE_NONE, (shortcutCode == SC_DOCK_LEFT)
+                recents.splitPrimaryTask((shortcutCode == SC_DOCK_LEFT)
                         ? SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT
                         : SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT, null, -1);
             } else {
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index da0a435..ea194a7 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -16,29 +16,28 @@
 
 package com.android.systemui.stackdivider;
 
-import android.content.res.Configuration;
-import android.os.RemoteException;
-import android.view.IDockedStackListener;
-import android.view.LayoutInflater;
-import android.view.View;
-
-import com.android.systemui.R;
-import com.android.systemui.SystemUI;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
-import com.android.systemui.recents.misc.SystemServicesProxy;
-
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 
+import android.content.res.Configuration;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.IDockedStackListener;
+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;
 
 /**
  * Controls the docked stack divider.
  */
-public class Divider extends SystemUI {
+public class Divider extends SystemUI implements DividerView.DividerCallbacks {
+    private static final String TAG = "Divider";
+
     private DividerWindowManager mWindowManager;
     private DividerView mView;
     private final DividerState mDividerState = new DividerState();
@@ -55,10 +54,13 @@
         update(mContext.getResources().getConfiguration());
         putComponent(Divider.class, this);
         mDockDividerVisibilityListener = new DockDividerVisibilityListener();
-        SystemServicesProxy ssp = Recents.getSystemServices();
-        ssp.registerDockedStackListener(mDockDividerVisibilityListener);
+        try {
+            WindowManagerGlobal.getWindowManagerService().registerDockedStackListener(
+                    mDockDividerVisibilityListener);
+        } catch (Exception e) {
+            Log.e(TAG, "Failed to register docked stack listener", e);
+        }
         mForcedResizableController = new ForcedResizableInfoActivityController(mContext);
-        EventBus.getDefault().register(this);
     }
 
     @Override
@@ -82,7 +84,7 @@
     private void addDivider(Configuration configuration) {
         mView = (DividerView)
                 LayoutInflater.from(mContext).inflate(R.layout.docked_stack_divider, null);
-        mView.injectDependencies(mWindowManager, mDividerState);
+        mView.injectDependencies(mWindowManager, mDividerState, this);
         mView.setVisibility(mVisible ? View.VISIBLE : View.INVISIBLE);
         mView.setMinimizedDockStack(mMinimized, mHomeStackResizable);
         final int size = mContext.getResources().getDimensionPixelSize(
@@ -156,18 +158,64 @@
         mWindowManager.setTouchable((mHomeStackResizable || !mMinimized) && !mAdjustedForIme);
     }
 
+    public void onRecentsActivityStarting() {
+        if (mView != null) {
+            mView.onRecentsActivityStarting();
+        }
+    }
+
     /**
-     * Workaround for b/62528361, at the time RecentsDrawnEvent is sent, it may happen before a
+     * Workaround for b/62528361, at the time recents has drawn, it may happen before a
      * configuration change to the Divider, and internally, the event will be posted to the
      * subscriber, or DividerView, which has been removed and prevented from resizing. Instead,
      * register the event handler here and proxy the event to the current DividerView.
      */
-    public final void onBusEvent(RecentsDrawnEvent drawnEvent) {
+    public void onRecentsDrawn() {
         if (mView != null) {
             mView.onRecentsDrawn();
         }
     }
 
+    public void onUndockingTask() {
+        if (mView != null) {
+            mView.onUndockingTask();
+        }
+    }
+
+    public void onDockedFirstAnimationFrame() {
+        if (mView != null) {
+            mView.onDockedFirstAnimationFrame();
+        }
+    }
+
+    public void onDockedTopTask() {
+        if (mView != null) {
+            mView.onDockedTopTask();
+        }
+    }
+
+    public void onAppTransitionFinished() {
+        mForcedResizableController.onAppTransitionFinished();
+    }
+
+    @Override
+    public void onDraggingStart() {
+        mForcedResizableController.onDraggingStart();
+    }
+
+    @Override
+    public void onDraggingEnd() {
+        mForcedResizableController.onDraggingEnd();
+    }
+
+    @Override
+    public void growRecents() {
+        Recents recents = getComponent(Recents.class);
+        if (recents != null) {
+            recents.growRecents();
+        }
+    }
+
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.print("  mVisible="); pw.println(mVisible);
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 98925b9..fa01af6 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -55,7 +55,6 @@
 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;
@@ -64,17 +63,8 @@
 import com.android.internal.view.SurfaceFlingerVsyncChoreographer;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.DockedFirstAnimationFrameEvent;
-import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
-import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
-import com.android.systemui.recents.events.activity.UndockingTaskEvent;
-import com.android.systemui.recents.events.ui.RecentsGrowingEvent;
-import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.stackdivider.events.StartedDragingEvent;
-import com.android.systemui.stackdivider.events.StoppedDragingEvent;
+import com.android.systemui.shared.system.WindowManagerWrapper;
 import com.android.systemui.statusbar.FlingAnimationUtils;
-import com.android.systemui.statusbar.phone.NavigationBarGestureHelper;
 
 /**
  * Docked stack divider.
@@ -82,6 +72,12 @@
 public class DividerView extends FrameLayout implements OnTouchListener,
         OnComputeInternalInsetsListener {
 
+    public interface DividerCallbacks {
+        void onDraggingStart();
+        void onDraggingEnd();
+        void growRecents();
+    }
+
     static final long TOUCH_ANIMATION_DURATION = 150;
     static final long TOUCH_RELEASE_ANIMATION_DURATION = 200;
 
@@ -149,6 +145,7 @@
     private FlingAnimationUtils mFlingAnimationUtils;
     private DividerSnapAlgorithm mSnapAlgorithm;
     private DividerSnapAlgorithm mMinimizedSnapAlgorithm;
+    private DividerCallbacks mCallback;
     private final Rect mStableInsets = new Rect();
 
     private boolean mGrowRecents;
@@ -162,6 +159,7 @@
     private DividerState mState;
     private final SurfaceFlingerVsyncChoreographer mSfChoreographer;
 
+
     // The view is removed or in the process of been removed from the system.
     private boolean mRemoved;
 
@@ -306,7 +304,6 @@
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
-        EventBus.getDefault().register(this);
 
         // Save the current target if not minimized once attached to window
         if (mHomeStackResizable && mDockSide != WindowManager.DOCKED_INVALID
@@ -315,14 +312,9 @@
         }
     }
 
-    @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-        EventBus.getDefault().unregister(this);
-    }
-
     void onDividerRemoved() {
         mRemoved = true;
+        mCallback = null;
         mHandler.removeMessages(MSG_RESIZE_STACK);
     }
 
@@ -364,13 +356,15 @@
         }
     }
 
-    public void injectDependencies(DividerWindowManager windowManager, DividerState dividerState) {
+    public void injectDependencies(DividerWindowManager windowManager, DividerState dividerState,
+            DividerCallbacks callback) {
         mWindowManager = windowManager;
         mState = dividerState;
+        mCallback = callback;
 
         // Set the previous position ratio before minimized state after attaching this divider
         if (mStableInsets.isEmpty()) {
-            SystemServicesProxy.getInstance(mContext).getStableInsets(mStableInsets);
+            WindowManagerWrapper.getInstance().getStableInsets(mStableInsets);
         }
 
         if (mState.mRatioPositionBeforeMinimized == 0) {
@@ -419,7 +413,9 @@
             mWindowManager.setSlippery(false);
             liftBackground();
         }
-        EventBus.getDefault().send(new StartedDragingEvent());
+        if (mCallback != null) {
+            mCallback.onDraggingStart();
+        }
         return mDockSide != WindowManager.DOCKED_INVALID;
     }
 
@@ -617,7 +613,9 @@
             mCurrentAnimator = null;
             mEntranceAnimationRunning = false;
             mExitAnimationRunning = false;
-            EventBus.getDefault().send(new StoppedDragingEvent());
+            if (mCallback != null) {
+                mCallback.onDraggingEnd();
+            }
 
             // Record last snap target the divider moved to
             if (mHomeStackResizable && !mIsInMinimizeInteraction) {
@@ -776,7 +774,7 @@
             if (mDisplayRotation != mDefaultDisplay.getRotation()) {
                 // Splitscreen to minimize is about to starts after rotating landscape to seascape,
                 // update insets, display info and snap algorithm targets
-                SystemServicesProxy.getInstance(mContext).getStableInsets(mStableInsets);
+                WindowManagerWrapper.getInstance().getStableInsets(mStableInsets);
                 repositionSnapTargetBeforeMinimized();
                 updateDisplayInfo();
             } else {
@@ -910,7 +908,7 @@
         requestLayout();
 
         // Update the snap position to the new docked side with correct insets
-        SystemServicesProxy.getInstance(mContext).getStableInsets(mStableInsets);
+        WindowManagerWrapper.getInstance().getStableInsets(mStableInsets);
         mMinimizedSnapAlgorithm = null;
         initializeSnapAlgorithm();
 
@@ -1271,7 +1269,7 @@
         }
     }
 
-    public final void onBusEvent(RecentsActivityStartingEvent recentsActivityStartingEvent) {
+    void onRecentsActivityStarting() {
         if (mGrowRecents && mDockSide == WindowManager.DOCKED_TOP
                 && getSnapAlgorithm().getMiddleTarget() != getSnapAlgorithm().getLastSplitTarget()
                 && getCurrentPosition() == getSnapAlgorithm().getLastSplitTarget().position) {
@@ -1280,16 +1278,14 @@
         }
     }
 
-    public final void onBusEvent(DockedFirstAnimationFrameEvent event) {
+    void onDockedFirstAnimationFrame() {
         saveSnapTargetBeforeMinimized(mSnapAlgorithm.getMiddleTarget());
     }
 
-    public final void onBusEvent(DockedTopTaskEvent event) {
-        if (event.dragMode == NavigationBarGestureHelper.DRAG_MODE_NONE) {
-            mState.growAfterRecentsDrawn = false;
-            mState.animateAfterRecentsDrawn = true;
-            startDragging(false /* animate */, false /* touching */);
-        }
+    void onDockedTopTask() {
+        mState.growAfterRecentsDrawn = false;
+        mState.animateAfterRecentsDrawn = true;
+        startDragging(false /* animate */, false /* touching */);
         updateDockSide();
         mEntranceAnimationRunning = true;
 
@@ -1297,7 +1293,7 @@
                 mSnapAlgorithm.getMiddleTarget());
     }
 
-    public void onRecentsDrawn() {
+    void onRecentsDrawn() {
         updateDockSide();
         final int position = calculatePositionForInsetBounds();
         if (mState.animateAfterRecentsDrawn) {
@@ -1314,13 +1310,15 @@
         if (mState.growAfterRecentsDrawn) {
             mState.growAfterRecentsDrawn = false;
             updateDockSide();
-            EventBus.getDefault().send(new RecentsGrowingEvent());
+            if (mCallback != null) {
+                mCallback.growRecents();
+            }
             stopDragging(position, getSnapAlgorithm().getMiddleTarget(), 336,
                     Interpolators.FAST_OUT_SLOW_IN);
         }
     }
 
-    public final void onBusEvent(UndockingTaskEvent undockingTaskEvent) {
+    void onUndockingTask() {
         int dockSide = mWindowManagerProxy.getDockSide();
         if (dockSide != WindowManager.DOCKED_INVALID && (mHomeStackResizable
                 || !mDockedStackMinimized)) {
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivity.java b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivity.java
index 4415bd7..02f7505 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivity.java
@@ -52,7 +52,7 @@
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.forced_resizable_activity);
-        TextView tv = (TextView) findViewById(com.android.internal.R.id.message);
+        TextView tv = findViewById(com.android.internal.R.id.message);
         int reason = getIntent().getIntExtra(EXTRA_FORCED_RESIZEABLE_REASON, -1);
         String text;
         switch (reason) {
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
index 826fa6c..f66db48 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
@@ -16,8 +16,7 @@
 
 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;
@@ -26,16 +25,9 @@
 import android.os.UserHandle;
 import android.util.ArraySet;
 import android.widget.Toast;
-
 import com.android.systemui.R;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.AppTransitionFinishedEvent;
-import com.android.systemui.recents.events.component.ShowUserToastEvent;
-import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
-import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.stackdivider.events.StartedDragingEvent;
-import com.android.systemui.stackdivider.events.StoppedDragingEvent;
+import com.android.systemui.shared.system.TaskStackChangeListener;
 
 /**
  * Controller that decides when to show the {@link ForcedResizableInfoActivity}.
@@ -49,7 +41,7 @@
     private final Handler mHandler = new Handler();
     private final ArraySet<PendingTaskRecord> mPendingTasks = new ArraySet<>();
     private final ArraySet<String> mPackagesShownInSession = new ArraySet<>();
-    private boolean mDividerDraging;
+    private boolean mDividerDragging;
 
     private final Runnable mTimeoutRunnable = new Runnable() {
         @Override
@@ -75,9 +67,8 @@
 
     public ForcedResizableInfoActivityController(Context context) {
         mContext = context;
-        EventBus.getDefault().register(this);
         ActivityManagerWrapper.getInstance().registerTaskStackListener(
-                new SysUiTaskStackChangeListener() {
+                new TaskStackChangeListener() {
                     @Override
                     public void onActivityForcedResizable(String packageName, int taskId,
                             int reason) {
@@ -102,19 +93,19 @@
         }
     }
 
-    public final void onBusEvent(AppTransitionFinishedEvent event) {
-        if (!mDividerDraging) {
+    public void onAppTransitionFinished() {
+        if (!mDividerDragging) {
             showPending();
         }
     }
 
-    public final void onBusEvent(StartedDragingEvent event) {
-        mDividerDraging = true;
+    void onDraggingStart() {
+        mDividerDragging = true;
         mHandler.removeCallbacks(mTimeoutRunnable);
     }
 
-    public final void onBusEvent(StoppedDragingEvent event) {
-        mDividerDraging = false;
+    void onDraggingEnd() {
+        mDividerDragging = false;
         showPending();
     }
 
@@ -127,13 +118,13 @@
     }
 
     private void activityDismissingDockedStack() {
-        EventBus.getDefault().send(new ShowUserToastEvent(
-                R.string.dock_non_resizeble_failed_to_dock_text, Toast.LENGTH_SHORT));
+        Toast.makeText(mContext, R.string.dock_non_resizeble_failed_to_dock_text,
+                Toast.LENGTH_SHORT).show();
     }
 
     private void activityLaunchOnSecondaryDisplayFailed() {
-        EventBus.getDefault().send(new ShowUserToastEvent(
-                R.string.activity_launch_on_secondary_display_failed_text, Toast.LENGTH_SHORT));
+        Toast.makeText(mContext, R.string.activity_launch_on_secondary_display_failed_text,
+                Toast.LENGTH_SHORT).show();
     }
 
     private void showPending() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
index 247e3d3..00e0b95 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
@@ -16,6 +16,10 @@
 
 package com.android.systemui.statusbar;
 
+import static android.content.Context.LAYOUT_INFLATER_SERVICE;
+import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_YES;
+import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.AlertDialog;
@@ -30,10 +34,10 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.ResolveInfo;
 import android.content.res.ColorStateList;
-import android.graphics.drawable.Icon;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
 import android.hardware.input.InputManager;
 import android.os.Handler;
 import android.os.Looper;
@@ -51,29 +55,23 @@
 import android.view.View.AccessibilityDelegate;
 import android.view.ViewGroup;
 import android.view.Window;
+import android.view.WindowManager;
 import android.view.WindowManager.KeyboardShortcutsReceiver;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.ImageView;
 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 com.android.systemui.recents.misc.SystemServicesProxy;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 
-import static android.content.Context.LAYOUT_INFLATER_SERVICE;
-import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_YES;
-import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
-
 /**
  * Contains functionality for handling keyboard shortcuts.
  */
@@ -372,19 +370,19 @@
 
     private void showKeyboardShortcuts(int deviceId) {
         retrieveKeyCharacterMap(deviceId);
-        SystemServicesProxy.getInstance(mContext).requestKeyboardShortcuts(mContext,
-                new KeyboardShortcutsReceiver() {
-                    @Override
-                    public void onKeyboardShortcutsReceived(
-                            final List<KeyboardShortcutGroup> result) {
-                        result.add(getSystemShortcuts());
-                        final KeyboardShortcutGroup appShortcuts = getDefaultApplicationShortcuts();
-                        if (appShortcuts != null) {
-                            result.add(appShortcuts);
-                        }
-                        showKeyboardShortcutsDialog(result);
-                    }
-                }, deviceId);
+        WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+        wm.requestAppKeyboardShortcuts(new KeyboardShortcutsReceiver() {
+            @Override
+            public void onKeyboardShortcutsReceived(
+                    final List<KeyboardShortcutGroup> result) {
+                result.add(getSystemShortcuts());
+                final KeyboardShortcutGroup appShortcuts = getDefaultApplicationShortcuts();
+                if (appShortcuts != null) {
+                    result.add(appShortcuts);
+                }
+                showKeyboardShortcutsDialog(result);
+            }
+        }, deviceId);
     }
 
     private void dismissKeyboardShortcuts() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
index d6886f5..89a842e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
@@ -16,6 +16,7 @@
 package com.android.systemui.statusbar;
 
 import android.app.ActivityManager;
+import android.app.KeyguardManager;
 import android.app.Notification;
 import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
@@ -37,12 +38,15 @@
 
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.NotificationVisibility;
+import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.Dependency;
 import com.android.systemui.Dumpable;
 import com.android.systemui.OverviewProxyService;
+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.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 
 import java.io.FileDescriptor;
@@ -52,7 +56,7 @@
  * Handles keeping track of the current user, profiles, and various things related to hiding
  * contents, redacting notifications, and the lockscreen.
  */
-public class NotificationLockscreenUserManager implements Dumpable {
+public class NotificationLockscreenUserManager implements Dumpable, StateListener {
     private static final String TAG = "LockscreenUserManager";
     private static final boolean ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT = false;
     public static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
@@ -67,9 +71,13 @@
             Dependency.get(DeviceProvisionedController.class);
     private final UserManager mUserManager;
     private final IStatusBarService mBarService;
+    private final LockPatternUtils mLockPatternUtils;
+    private final KeyguardManager mKeyguardManager;
+    private StatusBarKeyguardViewManager mKeyguardViewManager;
 
     private boolean mShowLockscreenNotifications;
     private boolean mAllowLockscreenRemoteInput;
+    private int mState = StatusBarState.SHADE;
 
     protected final BroadcastReceiver mAllUsersReceiver = new BroadcastReceiver() {
         @Override
@@ -84,7 +92,9 @@
                 mEntryManager.updateNotifications();
             } else if (Intent.ACTION_DEVICE_LOCKED_CHANGED.equals(action)) {
                 if (userId != mCurrentUserId && isCurrentProfile(userId)) {
+                    updatePublicMode();
                     mPresenter.onWorkChallengeChanged();
+                    mEntryManager.updateNotifications();
                 }
             }
         }
@@ -100,8 +110,9 @@
                 Log.v(TAG, "userId " + mCurrentUserId + " is in the house");
 
                 updateLockscreenNotificationSetting();
-
+                updatePublicMode();
                 mPresenter.onUserSwitched(mCurrentUserId);
+                mEntryManager.getNotificationData().filterAndSort();
             } else if (Intent.ACTION_USER_ADDED.equals(action)) {
                 updateCurrentProfilesCache();
             } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
@@ -150,6 +161,9 @@
         mCurrentUserId = ActivityManager.getCurrentUser();
         mBarService = IStatusBarService.Stub.asInterface(
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+        mLockPatternUtils = new LockPatternUtils(mContext);
+        mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
+        Dependency.get(StatusBarStateController.class).addListener(this);
     }
 
     public void setUpWithPresenter(NotificationPresenter presenter,
@@ -239,6 +253,43 @@
         }
     }
 
+    public void setKeyguardViewManager(StatusBarKeyguardViewManager sbkvm) {
+        mKeyguardViewManager = sbkvm;
+    }
+
+    @Override
+    public void onStateChanged(int newState) {
+        mState = newState;
+        updatePublicMode();
+    }
+
+    public void updatePublicMode() {
+        //TODO: I think there may be a race condition where mKeyguardViewManager.isShowing() returns
+        // false when it should be true. Therefore, if we are not on the SHADE, don't even bother
+        // asking if the keyguard is showing. We still need to check it though because showing the
+        // camera on the keyguard has a state of SHADE but the keyguard is still showing.
+        boolean showingKeyguard = mState != StatusBarState.SHADE
+                || mKeyguardViewManager.isShowing();
+        boolean devicePublic = showingKeyguard && mKeyguardViewManager.isSecure(getCurrentUserId());
+
+        SparseArray<UserInfo> currentProfiles = getCurrentProfiles();
+        for (int i = currentProfiles.size() - 1; i >= 0; i--) {
+            final int userId = currentProfiles.valueAt(i).id;
+            boolean isProfilePublic = devicePublic;
+            if (!devicePublic && userId != mCurrentUserId) {
+                // We can't rely on KeyguardManager#isDeviceLocked() for unified profile challenge
+                // due to a race condition where this code could be called before
+                // TrustManagerService updates its internal records, resulting in an incorrect
+                // state being cached in mLockscreenPublicMode. (b/35951989)
+                if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
+                        && mKeyguardViewManager.isSecure(userId)) {
+                    isProfilePublic = mKeyguardManager.isDeviceLocked(userId);
+                }
+            }
+            setLockscreenPublicMode(isProfilePublic, userId);
+        }
+    }
+
     /**
      * Returns true if notifications are temporarily disabled for this user for security reasons,
      * regardless of the normal settings for that user.
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 304a00f..2450e44 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar.car;
 
 import android.app.ActivityTaskManager;
-import android.car.user.CarUserManagerHelper;
 import android.graphics.PixelFormat;
 import android.graphics.drawable.Drawable;
 import android.util.Log;
@@ -36,8 +35,8 @@
 import com.android.systemui.classifier.FalsingManager;
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.recents.Recents;
-import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.car.hvac.HvacController;
 import com.android.systemui.statusbar.car.hvac.TemperatureView;
@@ -461,16 +460,11 @@
         }
     }
 
-
-    public boolean hasDockedTask() {
-        return Recents.getSystemServices().hasDockedTask();
-    }
-
     /**
-     * An implementation of SysUiTaskStackChangeListener, that listens for changes in the system
+     * An implementation of TaskStackChangeListener, that listens for changes in the system
      * task stack and notifies the navigation bar.
      */
-    private class TaskStackListenerImpl extends SysUiTaskStackChangeListener {
+    private class TaskStackListenerImpl extends TaskStackChangeListener {
         @Override
         public void onTaskStackChanged() {
             try {
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 67e512c..618a4c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
@@ -22,7 +22,7 @@
 import android.app.AlertDialog;
 import android.app.AlertDialog.Builder;
 import android.app.Dialog;
-import android.car.user.CarUserManagerHelper;
+import android.car.userlib.CarUserManagerHelper;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.pm.UserInfo;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
index 53d38c4..f0e5462 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
@@ -29,18 +29,14 @@
 import android.view.RemoteAnimationAdapter;
 import android.view.RemoteAnimationTarget;
 
-import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.shared.system.SurfaceControlCompat;
 import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier;
 import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier.SurfaceParams;
-import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
-import com.android.systemui.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
 import com.android.systemui.statusbar.phone.NotificationPanelView;
-import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.StatusBarWindowView;
 
 /**
@@ -59,28 +55,28 @@
     private final NotificationPanelView mNotificationPanel;
     private final NotificationListContainer mNotificationContainer;
     private final StatusBarWindowView mStatusBarWindow;
-    private final StatusBarStateController mStatusBarStateController;
-    private StatusBar mStatusBar;
+    private Callback mCallback;
     private final Runnable mTimeoutRunnable = () -> {
         setAnimationPending(false);
-        mStatusBar.collapsePanel(true /* animate */);
+        mCallback.onExpandAnimationTimedOut();
     };
     private boolean mAnimationPending;
+    private boolean mAnimationRunning;
+    private boolean mIsLaunchForActivity;
 
     public ActivityLaunchAnimator(StatusBarWindowView statusBarWindow,
-            StatusBar statusBar,
+            Callback callback,
             NotificationPanelView notificationPanel,
             NotificationListContainer container) {
         mNotificationPanel = notificationPanel;
         mNotificationContainer = container;
         mStatusBarWindow = statusBarWindow;
-        mStatusBar = statusBar;
-        mStatusBarStateController = Dependency.get(StatusBarStateController.class);
+        mCallback = callback;
     }
 
     public RemoteAnimationAdapter getLaunchAnimation(
             ExpandableNotificationRow sourceNotification, boolean occluded) {
-        if (mStatusBarStateController.getState() != StatusBarState.SHADE || occluded) {
+        if (!mCallback.areLaunchAnimationsEnabled() || occluded) {
             return null;
         }
         AnimationRunner animationRunner = new AnimationRunner(sourceNotification);
@@ -92,10 +88,21 @@
         return mAnimationPending;
     }
 
-    public void setLaunchResult(int launchResult) {
+    /**
+     * Set the launch result the intent requested
+     *
+     * @param launchResult the launch result
+     * @param wasIntentActivity was this launch for an activity
+     */
+    public void setLaunchResult(int launchResult, boolean wasIntentActivity) {
+        mIsLaunchForActivity = wasIntentActivity;
         setAnimationPending((launchResult == ActivityManager.START_TASK_TO_FRONT
                 || launchResult == ActivityManager.START_SUCCESS)
-                        && mStatusBarStateController.getState() == StatusBarState.SHADE);
+                        && mCallback.areLaunchAnimationsEnabled());
+    }
+
+    public boolean isLaunchForActivity() {
+        return mIsLaunchForActivity;
     }
 
     private void setAnimationPending(boolean pending) {
@@ -108,12 +115,16 @@
         }
     }
 
+    public boolean isAnimationRunning() {
+        return mAnimationRunning;
+    }
+
     class AnimationRunner extends IRemoteAnimationRunner.Stub {
 
         private final ExpandableNotificationRow mSourceNotification;
         private final ExpandAnimationParameters mParams;
         private final Rect mWindowCrop = new Rect();
-        private boolean mInstantCollapsePanel = true;
+        private boolean mIsFullScreenLaunch = true;
         private final SyncRtSurfaceTransactionApplier mSyncRtTransactionApplier;
 
         public AnimationRunner(ExpandableNotificationRow sourceNofitication) {
@@ -136,10 +147,10 @@
                 }
 
                 setExpandAnimationRunning(true);
-                mInstantCollapsePanel = primary.position.y == 0
+                mIsFullScreenLaunch = primary.position.y == 0
                         && primary.sourceContainerBounds.height()
                                 >= mNotificationPanel.getHeight();
-                if (!mInstantCollapsePanel) {
+                if (!mIsFullScreenLaunch) {
                     mNotificationPanel.collapseWithDuration(ANIMATION_DURATION);
                 }
                 ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
@@ -192,9 +203,6 @@
                     @Override
                     public void onAnimationEnd(Animator animation) {
                         setExpandAnimationRunning(false);
-                        if (mInstantCollapsePanel) {
-                            mStatusBar.collapsePanel(false /* animate */);
-                        }
                         invokeCallback(iRemoteAnimationFinishedCallback);
                     }
                 });
@@ -228,7 +236,9 @@
             mSourceNotification.setExpandAnimationRunning(running);
             mStatusBarWindow.setExpandAnimationRunning(running);
             mNotificationContainer.setExpandingNotification(running ? mSourceNotification : null);
+            mAnimationRunning = running;
             if (!running) {
+                mCallback.onExpandAnimationFinished(mIsFullScreenLaunch);
                 applyParamsToNotification(null);
                 applyParamsToNotificationList(null);
             }
@@ -257,7 +267,7 @@
         public void onAnimationCancelled() throws RemoteException {
             mSourceNotification.post(() -> {
                 setAnimationPending(false);
-                mStatusBar.onLaunchAnimationCancelled();
+                mCallback.onLaunchAnimationCancelled();
             });
         }
     };
@@ -319,4 +329,30 @@
             return startTranslationZ;
         }
     }
+
+    public interface Callback {
+
+        /**
+         * Called when the launch animation was cancelled.
+         */
+        void onLaunchAnimationCancelled();
+
+        /**
+         * Called when the launch animation has timed out without starting an actual animation.
+         */
+        void onExpandAnimationTimedOut();
+
+        /**
+         * Called when the expand animation has finished.
+         *
+         * @param launchIsFullScreen True if this launch was fullscreen, such that now the window
+         *                           fills the whole screen
+         */
+        void onExpandAnimationFinished(boolean launchIsFullScreen);
+
+        /**
+         * Are animations currently enabled.
+         */
+        boolean areLaunchAnimationsEnabled();
+    }
 }
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 935eaac..a3e982e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -28,15 +28,19 @@
 import android.content.pm.PackageManager;
 import android.database.ContentObserver;
 import android.os.Build;
+import android.os.Bundle;
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.provider.Settings;
+import android.service.dreams.DreamService;
+import android.service.dreams.IDreamManager;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationStats;
 import android.service.notification.StatusBarNotification;
+import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.EventLog;
@@ -56,7 +60,6 @@
 import com.android.systemui.ForegroundServiceController;
 import com.android.systemui.R;
 import com.android.systemui.UiOffloadThread;
-import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.statusbar.NotificationLifetimeExtender;
 import com.android.systemui.statusbar.AlertingNotificationManager;
 import com.android.systemui.statusbar.AmbientPulseManager;
@@ -125,11 +128,11 @@
             Dependency.get(NotificationListener.class);
     protected AmbientPulseManager mAmbientPulseManager = Dependency.get(AmbientPulseManager.class);
 
+    protected IDreamManager mDreamManager;
     protected IStatusBarService mBarService;
     protected NotificationPresenter mPresenter;
     protected Callback mCallback;
     protected PowerManager mPowerManager;
-    protected SystemServicesProxy mSystemServicesProxy;
     protected NotificationListenerService.RankingMap mLatestRankingMap;
     protected HeadsUpManager mHeadsUpManager;
     protected NotificationData mNotificationData;
@@ -221,8 +224,9 @@
         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mBarService = IStatusBarService.Stub.asInterface(
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+        mDreamManager = IDreamManager.Stub.asInterface(
+                ServiceManager.checkService(DreamService.DREAM_SERVICE));
         mMessagingUtil = new NotificationMessagingUtil(context);
-        mSystemServicesProxy = SystemServicesProxy.getInstance(mContext);
         mGroupManager.setPendingEntries(mPendingNotifications);
     }
 
@@ -685,7 +689,13 @@
             } else {
                 // Stop screensaver if the notification has a fullscreen intent.
                 // (like an incoming phone call)
-                SystemServicesProxy.getInstance(mContext).awakenDreamsAsync();
+                Dependency.get(UiOffloadThread.class).submit(() -> {
+                    try {
+                        mDreamManager.awaken();
+                    } catch (RemoteException e) {
+                        e.printStackTrace();
+                    }
+                });
 
                 // not immersive & a fullscreen alert should be shown
                 if (DEBUG)
@@ -896,7 +906,13 @@
             return false;
         }
 
-        boolean inUse = mPowerManager.isScreenOn() && !mSystemServicesProxy.isDreaming();
+        boolean isDreaming = false;
+        try {
+            isDreaming = mDreamManager.isDreaming();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to query dream manager.", e);
+        }
+        boolean inUse = mPowerManager.isScreenOn() && !isDreaming;
 
         if (!inUse) {
             if (DEBUG) {
@@ -979,6 +995,16 @@
             return false;
         }
 
+        Bundle extras = sbn.getNotification().extras;
+        CharSequence title = extras.getCharSequence(Notification.EXTRA_TITLE);
+        CharSequence text = extras.getCharSequence(Notification.EXTRA_TEXT);
+        if (TextUtils.isEmpty(title) && TextUtils.isEmpty(text)) {
+            if (DEBUG) {
+                Log.d(TAG, "No pulsing: title and text are empty: " + sbn.getKey());
+            }
+            return false;
+        }
+
         return true;
     }
 
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 9b1d334..bce613a 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
@@ -72,7 +72,7 @@
 import com.android.systemui.R;
 import com.android.systemui.classifier.FalsingManager;
 import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
 import com.android.systemui.statusbar.notification.NotificationData;
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 9e2331f..903c272 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
@@ -103,8 +103,15 @@
     };
 
     private OnClickListener mOnStopOrMinimizeNotifications = v -> {
-        mExitReason = NotificationCounters.BLOCKING_HELPER_STOP_NOTIFICATIONS;
-        swapContent(false);
+        Runnable saveImportance = () -> {
+            mExitReason = NotificationCounters.BLOCKING_HELPER_STOP_NOTIFICATIONS;
+            swapContent(false);
+        };
+        if (mCheckSaveListener != null) {
+            mCheckSaveListener.checkSave(saveImportance, mSbn);
+        } else {
+            saveImportance.run();
+        }
     };
 
     private OnClickListener mOnUndo = v -> {
@@ -304,15 +311,7 @@
 
     private void saveImportance() {
         if (!mIsNonblockable) {
-            // Only go through the lock screen/bouncer if the user hit 'Stop notifications'.
-            // Otherwise, update the importance immediately.
-            if (mCheckSaveListener != null
-                    && NotificationCounters.BLOCKING_HELPER_STOP_NOTIFICATIONS.equals(
-                            mExitReason)) {
-                mCheckSaveListener.checkSave(this::updateImportance, mSbn);
-            } else {
-                updateImportance();
-            }
+            updateImportance();
         }
     }
 
@@ -523,6 +522,11 @@
         return getHeight();
     }
 
+    @VisibleForTesting
+    public boolean isAnimating() {
+        return mExpandAnimation != null && mExpandAnimation.isRunning();
+    }
+
     /**
      * Runnable to either update the given channel (with a new importance value) or, if no channel
      * is provided, update notifications enabled state for the package.
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 72c2c0b..9978ec3 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
@@ -87,7 +87,6 @@
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.OnMenuEventListener;
 import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.DragDownHelper.DragDownCallback;
@@ -109,6 +108,7 @@
 import com.android.systemui.statusbar.notification.row.NotificationGuts;
 import com.android.systemui.statusbar.notification.logging.NotificationLogger;
 import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.notification.row.NotificationSnooze;
 import com.android.systemui.statusbar.notification.row.StackScrollerDecorView;
 import com.android.systemui.statusbar.StatusBarStateController;
@@ -146,11 +146,9 @@
  * A layout which handles a dynamic amount of notifications and presents them in a scrollable stack.
  */
 public class NotificationStackScrollLayout extends ViewGroup
-        implements Callback, ExpandHelper.Callback, ScrollAdapter,
-        OnHeightChangedListener, OnGroupChangeListener,
-        OnMenuEventListener, VisibilityLocationProvider,
-        NotificationListContainer, ConfigurationListener, DragDownCallback, AnimationStateHandler,
-        Dumpable {
+        implements ExpandHelper.Callback, ScrollAdapter, OnHeightChangedListener,
+        OnGroupChangeListener, VisibilityLocationProvider, NotificationListContainer,
+        ConfigurationListener, DragDownCallback, AnimationStateHandler, Dumpable {
 
     public static final float BACKGROUND_ALPHA_DIMMED = 0.7f;
     private static final String TAG = "StackScroller";
@@ -164,7 +162,7 @@
     private static final int INVALID_POINTER = -1;
 
     private ExpandHelper mExpandHelper;
-    private NotificationSwipeHelper mSwipeHelper;
+    private final NotificationSwipeHelper mSwipeHelper;
     private boolean mSwipingInProgress;
     private int mCurrentStackHeight = Integer.MAX_VALUE;
     private final Paint mBackgroundPaint = new Paint();
@@ -291,10 +289,6 @@
      */
     private int mMaxScrollAfterExpand;
     private ExpandableNotificationRow.LongPressListener mLongPressListener;
-
-    private NotificationMenuRowPlugin mCurrMenuRow;
-    private View mTranslatingParentView;
-    private View mMenuExposedView;
     boolean mCheckForLeavebehind;
 
     /**
@@ -466,6 +460,9 @@
     private Interpolator mDarkXInterpolator = Interpolators.FAST_OUT_SLOW_IN;
     private NotificationPanelView mNotificationPanel;
 
+    private final NotificationGutsManager
+            mNotificationGutsManager = Dependency.get(NotificationGutsManager.class);
+
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public NotificationStackScrollLayout(Context context) {
         this(context, null);
@@ -495,7 +492,8 @@
                 minHeight, maxHeight);
         mExpandHelper.setEventSource(this);
         mExpandHelper.setScrollAdapter(this);
-        mSwipeHelper = new NotificationSwipeHelper(SwipeHelper.X, this, getContext());
+        mSwipeHelper = new NotificationSwipeHelper(SwipeHelper.X, new SwipeHelperCallback(),
+                getContext(), new NotificationMenuListener());
         mStackScrollAlgorithm = createStackScrollAlgorithm(context);
         initView(context);
         mFalsingManager = FalsingManager.getInstance(context);
@@ -639,41 +637,6 @@
     }
 
     @Override
-    @ShadeViewRefactor(RefactorComponent.INPUT)
-    public void onMenuClicked(View view, int x, int y, MenuItem item) {
-        if (mLongPressListener == null) {
-            return;
-        }
-        if (view instanceof ExpandableNotificationRow) {
-            ExpandableNotificationRow row = (ExpandableNotificationRow) view;
-            MetricsLogger.action(mContext, MetricsEvent.ACTION_TOUCH_GEAR,
-                    row.getStatusBarNotification().getPackageName());
-        }
-        mLongPressListener.onLongPress(view, x, y, item);
-    }
-
-    @Override
-    @ShadeViewRefactor(RefactorComponent.INPUT)
-    public void onMenuReset(View row) {
-        if (mTranslatingParentView != null && row == mTranslatingParentView) {
-            mMenuExposedView = null;
-            mTranslatingParentView = null;
-        }
-    }
-
-    @Override
-    @ShadeViewRefactor(RefactorComponent.INPUT)
-    public void onMenuShown(View row) {
-        mMenuExposedView = mTranslatingParentView;
-        if (row instanceof ExpandableNotificationRow) {
-            MetricsLogger.action(mContext, MetricsEvent.ACTION_REVEAL_GEAR,
-                    ((ExpandableNotificationRow) row).getStatusBarNotification()
-                            .getPackageName());
-        }
-        mSwipeHelper.onMenuShown(row);
-    }
-
-    @Override
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void onUiModeChanged() {
         mBgColor = mContext.getColor(R.color.notification_shade_background_color);
@@ -1295,111 +1258,6 @@
         mQsContainer = qsContainer;
     }
 
-    /**
-     * Handles cleanup after the given {@code view} has been fully swiped out (including
-     * re-invoking dismiss logic in case the notification has not made its way out yet).
-     */
-    @Override
-    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
-    public void onChildDismissed(View view) {
-        ExpandableNotificationRow row = (ExpandableNotificationRow) view;
-        if (!row.isDismissed()) {
-            handleChildViewDismissed(view);
-        }
-        ViewGroup transientContainer = row.getTransientContainer();
-        if (transientContainer != null) {
-            transientContainer.removeTransientView(view);
-        }
-    }
-
-    /**
-     * Starts up notification dismiss and tells the notification, if any, to remove itself from
-     * layout.
-     *
-     * @param view view (e.g. notification) to dismiss from the layout
-     */
-
-    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
-    private void handleChildViewDismissed(View view) {
-        if (mDismissAllInProgress) {
-            return;
-        }
-
-        boolean isBlockingHelperShown = false;
-
-        setSwipingInProgress(false);
-        if (mDragAnimPendingChildren.contains(view)) {
-            // We start the swipe and finish it in the same frame; we don't want a drag animation.
-            mDragAnimPendingChildren.remove(view);
-        }
-        mAmbientState.onDragFinished(view);
-        updateContinuousShadowDrawing();
-
-        if (view instanceof ExpandableNotificationRow) {
-            ExpandableNotificationRow row = (ExpandableNotificationRow) view;
-            if (row.isHeadsUp()) {
-                mHeadsUpManager.addSwipedOutNotification(row.getStatusBarNotification().getKey());
-            }
-            isBlockingHelperShown =
-                    row.performDismissWithBlockingHelper(false /* fromAccessibility */);
-        }
-
-        if (!isBlockingHelperShown) {
-            mSwipedOutViews.add(view);
-        }
-        mFalsingManager.onNotificationDismissed();
-        if (mFalsingManager.shouldEnforceBouncer()) {
-            mStatusBar.executeRunnableDismissingKeyguard(
-                    null,
-                    null /* cancelAction */,
-                    false /* dismissShade */,
-                    true /* afterKeyguardGone */,
-                    false /* deferred */);
-        }
-    }
-
-    @Override
-    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
-    public void onChildSnappedBack(View animView, float targetLeft) {
-        mAmbientState.onDragFinished(animView);
-        updateContinuousShadowDrawing();
-        if (!mDragAnimPendingChildren.contains(animView)) {
-            if (mAnimationsEnabled) {
-                mSnappedBackChildren.add(animView);
-                mNeedsAnimation = true;
-            }
-            requestChildrenUpdate();
-        } else {
-            // We start the swipe and snap back in the same frame, we don't want any animation
-            mDragAnimPendingChildren.remove(animView);
-        }
-        if (mCurrMenuRow != null && targetLeft == 0) {
-            mCurrMenuRow.resetMenu();
-            mCurrMenuRow = null;
-        }
-    }
-
-    @Override
-    @ShadeViewRefactor(RefactorComponent.INPUT)
-    public boolean updateSwipeProgress(View animView, boolean dismissable, float swipeProgress) {
-        // Returning true prevents alpha fading.
-        return !mFadeNotificationsOnDismiss;
-    }
-
-    @Override
-    @ShadeViewRefactor(RefactorComponent.INPUT)
-    public void onBeginDrag(View v) {
-        mFalsingManager.onNotificatonStartDismissing();
-        setSwipingInProgress(true);
-        mAmbientState.onBeginDrag(v);
-        updateContinuousShadowDrawing();
-        if (mAnimationsEnabled && (mIsExpanded || !isPinnedHeadsUp(v))) {
-            mDragAnimPendingChildren.add(v);
-            mNeedsAnimation = true;
-        }
-        requestChildrenUpdate();
-    }
-
     @ShadeViewRefactor(RefactorComponent.ADAPTER)
     public static boolean isPinnedHeadsUp(View v) {
         if (v instanceof ExpandableNotificationRow) {
@@ -1418,41 +1276,6 @@
         return false;
     }
 
-    @Override
-    @ShadeViewRefactor(RefactorComponent.INPUT)
-    public void onDragCancelled(View v) {
-        mFalsingManager.onNotificatonStopDismissing();
-        setSwipingInProgress(false);
-    }
-
-    @Override
-    @ShadeViewRefactor(RefactorComponent.INPUT)
-    public float getFalsingThresholdFactor() {
-        return mStatusBar.isWakeUpComingFromTouch() ? 1.5f : 1.0f;
-    }
-
-    @Override
-    @ShadeViewRefactor(RefactorComponent.INPUT)
-    public View getChildAtPosition(MotionEvent ev) {
-        View child = getChildAtPosition(ev.getX(), ev.getY());
-        if (child instanceof ExpandableNotificationRow) {
-            ExpandableNotificationRow row = (ExpandableNotificationRow) child;
-            ExpandableNotificationRow parent = row.getNotificationParent();
-            if (parent != null && parent.areChildrenExpanded()
-                    && (parent.areGutsExposed()
-                    || mMenuExposedView == parent
-                    || (parent.getNotificationChildren().size() == 1
-                    && parent.isClearable()))) {
-                // In this case the group is expanded and showing the menu for the
-                // group, further interaction should apply to the group, not any
-                // child notifications so we use the parent of the child. We also do the same
-                // if we only have a single child.
-                child = parent;
-            }
-        }
-        return child;
-    }
-
     @ShadeViewRefactor(RefactorComponent.INPUT)
     public ExpandableView getClosestChildAtRawPosition(float touchX, float touchY) {
         getLocationOnScreen(mTempInt2);
@@ -1696,18 +1519,11 @@
         return mScrollingEnabled;
     }
 
-    @Override
     @ShadeViewRefactor(RefactorComponent.ADAPTER)
-    public boolean canChildBeDismissed(View v) {
+    private boolean canChildBeDismissed(View v) {
         return StackScrollAlgorithm.canChildBeDismissed(v);
     }
 
-    @Override
-    @ShadeViewRefactor(RefactorComponent.INPUT)
-    public boolean isAntiFalsingNeeded() {
-        return onKeyguard();
-    }
-
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private boolean onKeyguard() {
         return mStatusBarState == StatusBarState.KEYGUARD;
@@ -1787,8 +1603,8 @@
         }
 
         // Check if we need to clear any snooze leavebehinds
-        NotificationGuts guts = mStatusBar.getGutsManager().getExposedGuts();
-        if (guts != null && !isTouchInView(ev, guts)
+        NotificationGuts guts = mNotificationGutsManager.getExposedGuts();
+        if (guts != null && !NotificationSwipeHelper.isTouchInView(ev, guts)
                 && guts.getGutsContent() instanceof NotificationSnooze) {
             NotificationSnooze ns = (NotificationSnooze) guts.getGutsContent();
             if ((ns.isExpanded() && isCancelOrUp)
@@ -3013,11 +2829,11 @@
         }
         // Check if we need to clear any snooze leavebehinds
         boolean isUp = ev.getActionMasked() == MotionEvent.ACTION_UP;
-        NotificationGuts guts = mStatusBar.getGutsManager().getExposedGuts();
-        if (!isTouchInView(ev, guts) && isUp && !swipeWantsIt && !expandWantsIt
-                && !scrollWantsIt) {
+        NotificationGuts guts = mNotificationGutsManager.getExposedGuts();
+        if (!NotificationSwipeHelper.isTouchInView(ev, guts) && isUp && !swipeWantsIt &&
+                !expandWantsIt && !scrollWantsIt) {
             mCheckForLeavebehind = false;
-            mStatusBar.getGutsManager().closeAndSaveGuts(true /* removeLeavebehind */,
+            mNotificationGutsManager.closeAndSaveGuts(true /* removeLeavebehind */,
                     false /* force */, false /* removeControls */, -1 /* x */, -1 /* y */,
                     false /* resetMenu */);
         }
@@ -3077,8 +2893,8 @@
     @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     @Override
     public void cleanUpViewState(View child) {
-        if (child == mTranslatingParentView) {
-            mTranslatingParentView = null;
+        if (child == mSwipeHelper.getTranslatingParentView()) {
+            mSwipeHelper.clearTranslatingParentView();
         }
         mCurrentStackScrollState.removeViewStateForView(child);
     }
@@ -3986,7 +3802,7 @@
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void checkSnoozeLeavebehind() {
         if (mCheckForLeavebehind) {
-            mStatusBar.getGutsManager().closeAndSaveGuts(true /* removeLeavebehind */,
+            mNotificationGutsManager.closeAndSaveGuts(true /* removeLeavebehind */,
                     false /* force */, false /* removeControls */, -1 /* x */, -1 /* y */,
                     false /* resetMenu */);
             mCheckForLeavebehind = false;
@@ -4068,7 +3884,7 @@
     }
 
     @ShadeViewRefactor(RefactorComponent.COORDINATOR)
-    private void setIsExpanded(boolean isExpanded) {
+    public void setIsExpanded(boolean isExpanded) {
         boolean changed = isExpanded != mIsExpanded;
         mIsExpanded = isExpanded;
         mStackScrollAlgorithm.setIsExpanded(isExpanded);
@@ -5242,8 +5058,8 @@
         setFooterView(footerView);
     }
 
-  @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
-  private void inflateEmptyShadeView() {
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
+    private void inflateEmptyShadeView() {
         EmptyShadeView view = (EmptyShadeView) LayoutInflater.from(mContext).inflate(
                 R.layout.status_bar_no_notifications, this, false);
         view.setText(R.string.empty_shade_text);
@@ -5274,8 +5090,8 @@
         mScrimController.setNotificationCount(getNotGoneChildCount());
     }
 
-  @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
-  public void setNotificationPanel(NotificationPanelView notificationPanelView) {
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
+    public void setNotificationPanel(NotificationPanelView notificationPanelView) {
         mNotificationPanel = notificationPanelView;
     }
 
@@ -5293,306 +5109,29 @@
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public interface OnOverscrollTopChangedListener {
 
-        /**
-         * Notifies a listener that the overscroll has changed.
-         *
-         * @param amount         the amount of overscroll, in pixels
-         * @param isRubberbanded if true, this is a rubberbanded overscroll; if false, this is an
-         *                       unrubberbanded motion to directly expand overscroll view (e.g
-         *                       expand
-         *                       QS)
-         */
-        void onOverscrollTopChanged(float amount, boolean isRubberbanded);
+    /**
+     * Notifies a listener that the overscroll has changed.
+     *
+     * @param amount         the amount of overscroll, in pixels
+     * @param isRubberbanded if true, this is a rubberbanded overscroll; if false, this is an
+     *                       unrubberbanded motion to directly expand overscroll view (e.g
+     *                       expand
+     *                       QS)
+     */
+    void onOverscrollTopChanged(float amount, boolean isRubberbanded);
 
-        /**
-         * Notify a listener that the scroller wants to escape from the scrolling motion and
-         * start a fling animation to the expanded or collapsed overscroll view (e.g expand the QS)
-         *
-         * @param velocity The velocity that the Scroller had when over flinging
-         * @param open     Should the fling open or close the overscroll view.
-         */
-        void flingTopOverscroll(float velocity, boolean open);
-    }
+    /**
+     * Notify a listener that the scroller wants to escape from the scrolling motion and
+     * start a fling animation to the expanded or collapsed overscroll view (e.g expand the QS)
+     *
+     * @param velocity The velocity that the Scroller had when over flinging
+     * @param open     Should the fling open or close the overscroll view.
+     */
+    void flingTopOverscroll(float velocity, boolean open);
+  }
 
-    @ShadeViewRefactor(RefactorComponent.INPUT)
-    private class NotificationSwipeHelper extends SwipeHelper
-            implements NotificationSwipeActionHelper {
-        private static final long COVER_MENU_DELAY = 4000;
-        private Runnable mFalsingCheck;
-        private Handler mHandler;
-
-        private static final long SWIPE_MENU_TIMING = 200;
-
-        public NotificationSwipeHelper(int swipeDirection, Callback callback, Context context) {
-            super(swipeDirection, callback, context);
-            mHandler = new Handler();
-            mFalsingCheck = new Runnable() {
-                @Override
-                public void run() {
-                    resetExposedMenuView(true /* animate */, true /* force */);
-                }
-            };
-        }
-
-        @Override
-        public void onDownUpdate(View currView, MotionEvent ev) {
-            mTranslatingParentView = currView;
-            if (mCurrMenuRow != null) {
-                mCurrMenuRow.onTouchStart();
-            }
-            mCurrMenuRow = null;
-            mHandler.removeCallbacks(mFalsingCheck);
-
-            // Slide back any notifications that might be showing a menu
-            resetExposedMenuView(true /* animate */, false /* force */);
-
-            if (currView instanceof ExpandableNotificationRow) {
-                ExpandableNotificationRow row = (ExpandableNotificationRow) currView;
-
-                if (row.getEntry().hasFinishedInitialization()) {
-                    mCurrMenuRow = row.createMenu();
-                    mCurrMenuRow.setMenuClickListener(NotificationStackScrollLayout.this);
-                    mCurrMenuRow.onTouchStart();
-                }
-            }
-        }
-
-        private boolean swipedEnoughToShowMenu(NotificationMenuRowPlugin menuRow) {
-            return !swipedFarEnough() && menuRow.isSwipedEnoughToShowMenu();
-        }
-
-        @Override
-        public void onMoveUpdate(View view, MotionEvent ev, float translation, float delta) {
-            mHandler.removeCallbacks(mFalsingCheck);
-            if (mCurrMenuRow != null) {
-                mCurrMenuRow.onTouchMove(delta);
-            }
-        }
-
-        @Override
-        public boolean handleUpEvent(MotionEvent ev, View animView, float velocity,
-                float translation) {
-            if (mCurrMenuRow != null) {
-                mCurrMenuRow.onTouchEnd();
-                handleMenuRowSwipe(ev, animView, velocity, mCurrMenuRow);
-                return true;
-            }
-            return false;
-        }
-
-        @Override
-        public boolean swipedFarEnough(float translation, float viewSize) {
-            return swipedFarEnough();
-        }
-
-        private void handleMenuRowSwipe(MotionEvent ev, View animView, float velocity,
-                NotificationMenuRowPlugin menuRow) {
-            if (!menuRow.shouldShowMenu()) {
-                // If the menu should not be shown, then there is no need to check if the a swipe
-                // should result in a snapping to the menu. As a result, just check if the swipe
-                // was enough to dismiss the notification.
-                if (isDismissGesture(ev)) {
-                    dismiss(animView, velocity);
-                } else {
-                    snapBack(animView, velocity);
-                    menuRow.onSnapClosed();
-                }
-                return;
-            }
-
-            if (menuRow.isSnappedAndOnSameSide()) {
-                // Menu was snapped to previously and we're on the same side
-                handleSwipeFromSnap(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);
-            }
-        }
-
-        private void handleSwipeFromNonSnap(MotionEvent ev, View animView, float velocity,
-                NotificationMenuRowPlugin menuRow) {
-            boolean isDismissGesture = isDismissGesture(ev);
-            final boolean gestureTowardsMenu = menuRow.isTowardsMenu(velocity);
-            final boolean gestureFastEnough =
-                    mSwipeHelper.getMinDismissVelocity() <= Math.abs(velocity);
-
-            final double timeForGesture = ev.getEventTime() - ev.getDownTime();
-            final boolean showMenuForSlowOnGoing = !menuRow.canBeDismissed()
-                    && timeForGesture >= SWIPE_MENU_TIMING;
-
-            if (!isFalseGesture(ev)
-                    && (swipedEnoughToShowMenu(menuRow)
-                    && (!gestureFastEnough || showMenuForSlowOnGoing))
-                    || (gestureTowardsMenu && !isDismissGesture)) {
-                // Menu has not been snapped to previously and this is menu revealing gesture
-                snapOpen(animView, menuRow.getMenuSnapTarget(), velocity);
-                menuRow.onSnapOpen();
-            } else if (isDismissGesture(ev) && !gestureTowardsMenu) {
-                dismiss(animView, velocity);
-                menuRow.onDismiss();
-            } else {
-                snapBack(animView, velocity);
-                menuRow.onSnapClosed();
-            }
-        }
-
-        private void handleSwipeFromSnap(MotionEvent ev, View animView, float velocity,
-                NotificationMenuRowPlugin menuRow) {
-            boolean isDismissGesture = isDismissGesture(ev);
-
-            final boolean withinSnapMenuThreshold =
-                    menuRow.isWithinSnapMenuThreshold();
-
-            if (withinSnapMenuThreshold && !isDismissGesture) {
-                // Haven't moved enough to unsnap from the menu
-                menuRow.onSnapOpen();
-                snapOpen(animView, menuRow.getMenuSnapTarget(), velocity);
-            } else if (isDismissGesture && !menuRow.shouldSnapBack()) {
-                // Only dismiss if we're not moving towards the menu
-                dismiss(animView, velocity);
-                menuRow.onDismiss();
-            } else {
-                snapBack(animView, velocity);
-                menuRow.onSnapClosed();
-            }
-        }
-
-        @Override
-        public void dismissChild(final View view, float velocity,
-                boolean useAccelerateInterpolator) {
-            super.dismissChild(view, velocity, useAccelerateInterpolator);
-            if (mIsExpanded) {
-                // We don't want to quick-dismiss when it's a heads up as this might lead to closing
-                // of the panel early.
-                handleChildViewDismissed(view);
-            }
-            mStatusBar.getGutsManager().closeAndSaveGuts(true /* removeLeavebehind */,
-                    false /* force */, false /* removeControls */, -1 /* x */, -1 /* y */,
-                    false /* resetMenu */);
-            handleMenuCoveredOrDismissed();
-        }
-
-        @Override
-        public void snapChild(final View animView, final float targetLeft, float velocity) {
-            super.snapChild(animView, targetLeft, velocity);
-            onDragCancelled(animView);
-            if (targetLeft == 0) {
-                handleMenuCoveredOrDismissed();
-            }
-        }
-
-        @Override
-        public void snooze(StatusBarNotification sbn, SnoozeOption snoozeOption) {
-            mStatusBar.setNotificationSnoozed(sbn, snoozeOption);
-        }
-
-        private void handleMenuCoveredOrDismissed() {
-            if (mMenuExposedView != null && mMenuExposedView == mTranslatingParentView) {
-                mMenuExposedView = null;
-            }
-        }
-
-        @Override
-        public Animator getViewTranslationAnimator(View v, float target,
-                AnimatorUpdateListener listener) {
-            if (v instanceof ExpandableNotificationRow) {
-                return ((ExpandableNotificationRow) v).getTranslateViewAnimator(target, listener);
-            } else {
-                return super.getViewTranslationAnimator(v, target, listener);
-            }
-        }
-
-        @Override
-        public void setTranslation(View v, float translate) {
-            ((ExpandableView) v).setTranslation(translate);
-        }
-
-        @Override
-        public float getTranslation(View v) {
-            return ((ExpandableView) v).getTranslation();
-        }
-
-        @Override
-        public void dismiss(View animView, float velocity) {
-            dismissChild(animView, velocity,
-                    !swipedFastEnough(0, 0) /* useAccelerateInterpolator */);
-        }
-
-        @Override
-        public void snapOpen(View animView, int targetLeft, float velocity) {
-            snapChild(animView, targetLeft, velocity);
-        }
-
-        private void snapBack(View animView, float velocity) {
-            snapChild(animView, 0, velocity);
-        }
-
-        @Override
-        public boolean swipedFastEnough(float translation, float velocity) {
-            return swipedFastEnough();
-        }
-
-        @Override
-        public float getMinDismissVelocity() {
-            return getEscapeVelocity();
-        }
-
-        public void onMenuShown(View animView) {
-            onDragCancelled(animView);
-
-            // If we're on the lockscreen we want to false this.
-            if (isAntiFalsingNeeded()) {
-                mHandler.removeCallbacks(mFalsingCheck);
-                mHandler.postDelayed(mFalsingCheck, COVER_MENU_DELAY);
-            }
-        }
-
-        public void closeControlsIfOutsideTouch(MotionEvent ev) {
-            NotificationGuts guts = mStatusBar.getGutsManager().getExposedGuts();
-            View view = null;
-            if (guts != null && !guts.getGutsContent().isLeavebehind()) {
-                // Only close visible guts if they're not a leavebehind.
-                view = guts;
-            } else if (mCurrMenuRow != null && mCurrMenuRow.isMenuVisible()
-                    && mTranslatingParentView != null) {
-                // Checking menu
-                view = mTranslatingParentView;
-            }
-            if (view != null && !isTouchInView(ev, view)) {
-                // Touch was outside visible guts / menu notification, close what's visible
-                mStatusBar.getGutsManager().closeAndSaveGuts(false /* removeLeavebehind */,
-                        false /* force */, true /* removeControls */, -1 /* x */, -1 /* y */,
-                        false /* resetMenu */);
-                resetExposedMenuView(true /* animate */, true /* force */);
-            }
-        }
-
-        public void resetExposedMenuView(boolean animate, boolean force) {
-            if (mMenuExposedView == null
-                    || (!force && mMenuExposedView == mTranslatingParentView)) {
-                // If no menu is showing or it's showing for this view we do nothing.
-                return;
-            }
-            final View prevMenuExposedView = mMenuExposedView;
-            if (animate) {
-                Animator anim = getViewTranslationAnimator(prevMenuExposedView,
-                        0 /* leftTarget */, null /* updateListener */);
-                if (anim != null) {
-                    anim.start();
-                }
-            } else if (mMenuExposedView instanceof ExpandableNotificationRow) {
-                ExpandableNotificationRow row = (ExpandableNotificationRow) mMenuExposedView;
-                if (!row.isRemoved()) {
-                    row.resetTranslation();
-                }
-            }
-            mMenuExposedView = null;
-        }
-    }
-
-  @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
-  public boolean hasActiveNotifications() {
+    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
+    public boolean hasActiveNotifications() {
         return !mEntryManager.getNotificationData().getActiveNotifications().isEmpty();
     }
 
@@ -5656,8 +5195,8 @@
         return mStatusBarState == StatusBarState.KEYGUARD;
     }
 
-  @ShadeViewRefactor(RefactorComponent.INPUT)
-  public void updateSpeedBumpIndex() {
+    @ShadeViewRefactor(RefactorComponent.INPUT)
+    public void updateSpeedBumpIndex() {
         int speedBumpIndex = 0;
         int currentIndex = 0;
         final int N = getChildCount();
@@ -5677,24 +5216,6 @@
         updateSpeedBumpIndex(speedBumpIndex, noAmbient);
     }
 
-    @ShadeViewRefactor(RefactorComponent.INPUT)
-    private boolean isTouchInView(MotionEvent ev, View view) {
-        if (view == null) {
-            return false;
-        }
-        final int height = (view instanceof ExpandableView)
-                ? ((ExpandableView) view).getActualHeight()
-                : view.getHeight();
-        final int rx = (int) ev.getRawX();
-        final int ry = (int) ev.getRawY();
-        view.getLocationOnScreen(mTempInt2);
-        final int x = mTempInt2[0];
-        final int y = mTempInt2[1];
-        Rect rect = new Rect(x, y, x + view.getWidth(), y + height);
-        boolean ret = rect.contains(rx, ry);
-        return ret;
-    }
-
     @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void updateContinuousShadowDrawing() {
         boolean continuousShadowUpdate = mAnimationRunning
@@ -5718,11 +5239,29 @@
 
     @ShadeViewRefactor(RefactorComponent.INPUT)
     public void closeControlsIfOutsideTouch(MotionEvent ev) {
-        mSwipeHelper.closeControlsIfOutsideTouch(ev);
+        NotificationGuts guts = mNotificationGutsManager.getExposedGuts();
+        NotificationMenuRowPlugin menuRow = mSwipeHelper.getCurrentMenuRow();
+        View translatingParentView = mSwipeHelper.getTranslatingParentView();
+        View view = null;
+        if (guts != null && !guts.getGutsContent().isLeavebehind()) {
+            // Only close visible guts if they're not a leavebehind.
+            view = guts;
+        } else if (menuRow != null && menuRow.isMenuVisible()
+                && translatingParentView != null) {
+            // Checking menu
+            view = translatingParentView;
+        }
+        if (view != null && !NotificationSwipeHelper.isTouchInView(ev, view)) {
+            // Touch was outside visible guts / menu notification, close what's visible
+            mNotificationGutsManager.closeAndSaveGuts(false /* removeLeavebehind */,
+                    false /* force */, true /* removeControls */, -1 /* x */, -1 /* y */,
+                    false /* resetMenu */);
+            resetExposedMenuView(true /* animate */, true /* force */);
+        }
     }
 
-  @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
-  static class AnimationEvent {
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
+    static class AnimationEvent {
 
         static AnimationFilter[] FILTERS = new AnimationFilter[]{
 
@@ -6022,8 +5561,8 @@
         }
     }
 
-  @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
-  private final StateListener mStateListener = new StateListener() {
+    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
+    private final StateListener mStateListener = new StateListener() {
         @Override
         public void onStatePreChange(int oldState, int newState) {
             if (oldState == StatusBarState.SHADE_LOCKED && newState == StatusBarState.KEYGUARD) {
@@ -6036,9 +5575,222 @@
             setStatusBarState(newState);
         }
 
-      @Override
-      public void onStatePostChange() {
+        @Override
+        public void onStatePostChange() {
           NotificationStackScrollLayout.this.onStatePostChange();
       }
-  };
+    };
+
+    class NotificationMenuListener implements NotificationMenuRowPlugin.OnMenuEventListener {
+        @Override
+        @ShadeViewRefactor(RefactorComponent.INPUT)
+        public void onMenuClicked(View view, int x, int y, MenuItem item) {
+            if (mLongPressListener == null) {
+                return;
+            }
+            if (view instanceof ExpandableNotificationRow) {
+                ExpandableNotificationRow row = (ExpandableNotificationRow) view;
+                MetricsLogger.action(mContext, MetricsEvent.ACTION_TOUCH_GEAR,
+                        row.getStatusBarNotification().getPackageName());
+            }
+            mLongPressListener.onLongPress(view, x, y, item);
+        }
+
+        @Override
+        @ShadeViewRefactor(RefactorComponent.INPUT)
+        public void onMenuReset(View row) {
+            View translatingParentView = mSwipeHelper.getTranslatingParentView();
+            if (translatingParentView != null && row == translatingParentView) {
+                mSwipeHelper.clearExposedMenuView();
+                mSwipeHelper.clearTranslatingParentView();
+            }
+        }
+
+        @Override
+        @ShadeViewRefactor(RefactorComponent.INPUT)
+        public void onMenuShown(View row) {
+            if (row instanceof ExpandableNotificationRow) {
+                MetricsLogger.action(mContext, MetricsEvent.ACTION_REVEAL_GEAR,
+                        ((ExpandableNotificationRow) row).getStatusBarNotification()
+                                .getPackageName());
+            }
+            mSwipeHelper.onMenuShown(row);
+        }
+    }
+
+    class SwipeHelperCallback implements NotificationSwipeHelper.NotificationCallback {
+        @Override
+        public void onDismiss() {
+            mNotificationGutsManager.closeAndSaveGuts(true /* removeLeavebehind */,
+                    false /* force */, false /* removeControls */, -1 /* x */, -1 /* y */,
+                    false /* resetMenu */);
+        }
+
+        @Override
+        public void onSnooze(StatusBarNotification sbn,
+                NotificationSwipeActionHelper.SnoozeOption snoozeOption) {
+            mStatusBar.setNotificationSnoozed(sbn, snoozeOption);
+        }
+
+        @Override
+        public boolean isExpanded() {
+            return NotificationStackScrollLayout.this.isExpanded();
+        }
+
+        @Override
+        @ShadeViewRefactor(RefactorComponent.INPUT)
+        public void onDragCancelled(View v) {
+            mFalsingManager.onNotificatonStopDismissing();
+            setSwipingInProgress(false);
+        }
+
+        /**
+         * Handles cleanup after the given {@code view} has been fully swiped out (including
+         * re-invoking dismiss logic in case the notification has not made its way out yet).
+         */
+        @Override
+        @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
+        public void onChildDismissed(View view) {
+            ExpandableNotificationRow row = (ExpandableNotificationRow) view;
+            if (!row.isDismissed()) {
+                handleChildViewDismissed(view);
+            }
+            ViewGroup transientContainer = row.getTransientContainer();
+            if (transientContainer != null) {
+                transientContainer.removeTransientView(view);
+            }
+        }
+
+        /**
+         * Starts up notification dismiss and tells the notification, if any, to remove itself from
+         * layout.
+         *
+         * @param view view (e.g. notification) to dismiss from the layout
+         */
+
+        @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
+        public void handleChildViewDismissed(View view) {
+            if (mDismissAllInProgress) {
+                return;
+            }
+
+            boolean isBlockingHelperShown = false;
+
+            setSwipingInProgress(false);
+            if (mDragAnimPendingChildren.contains(view)) {
+                // We start the swipe and finish it in the same frame; we don't want a drag
+                // animation.
+                mDragAnimPendingChildren.remove(view);
+            }
+            mAmbientState.onDragFinished(view);
+            updateContinuousShadowDrawing();
+
+            if (view instanceof ExpandableNotificationRow) {
+                ExpandableNotificationRow row = (ExpandableNotificationRow) view;
+                if (row.isHeadsUp()) {
+                    mHeadsUpManager.addSwipedOutNotification(
+                            row.getStatusBarNotification().getKey());
+                }
+                isBlockingHelperShown =
+                        row.performDismissWithBlockingHelper(false /* fromAccessibility */);
+            }
+
+            if (!isBlockingHelperShown) {
+                mSwipedOutViews.add(view);
+            }
+            mFalsingManager.onNotificationDismissed();
+            if (mFalsingManager.shouldEnforceBouncer()) {
+                mStatusBar.executeRunnableDismissingKeyguard(
+                        null,
+                        null /* cancelAction */,
+                        false /* dismissShade */,
+                        true /* afterKeyguardGone */,
+                        false /* deferred */);
+            }
+        }
+
+        @Override
+        @ShadeViewRefactor(RefactorComponent.INPUT)
+        public boolean isAntiFalsingNeeded() {
+            return onKeyguard();
+        }
+
+        @Override
+        @ShadeViewRefactor(RefactorComponent.INPUT)
+        public View getChildAtPosition(MotionEvent ev) {
+            View child = NotificationStackScrollLayout.this.getChildAtPosition(ev.getX(),
+                    ev.getY());
+            if (child instanceof ExpandableNotificationRow) {
+                ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+                ExpandableNotificationRow parent = row.getNotificationParent();
+                if (parent != null && parent.areChildrenExpanded()
+                        && (parent.areGutsExposed()
+                        || mSwipeHelper.getExposedMenuView() == parent
+                        || (parent.getNotificationChildren().size() == 1
+                        && parent.isClearable()))) {
+                    // In this case the group is expanded and showing the menu for the
+                    // group, further interaction should apply to the group, not any
+                    // child notifications so we use the parent of the child. We also do the same
+                    // if we only have a single child.
+                    child = parent;
+                }
+            }
+            return child;
+        }
+
+        @Override
+        @ShadeViewRefactor(RefactorComponent.INPUT)
+        public void onBeginDrag(View v) {
+            mFalsingManager.onNotificatonStartDismissing();
+            setSwipingInProgress(true);
+            mAmbientState.onBeginDrag(v);
+            updateContinuousShadowDrawing();
+            if (mAnimationsEnabled && (mIsExpanded || !isPinnedHeadsUp(v))) {
+                mDragAnimPendingChildren.add(v);
+                mNeedsAnimation = true;
+            }
+            requestChildrenUpdate();
+        }
+
+        @Override
+        @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
+        public void onChildSnappedBack(View animView, float targetLeft) {
+            mAmbientState.onDragFinished(animView);
+            updateContinuousShadowDrawing();
+            if (!mDragAnimPendingChildren.contains(animView)) {
+                if (mAnimationsEnabled) {
+                    mSnappedBackChildren.add(animView);
+                    mNeedsAnimation = true;
+                }
+                requestChildrenUpdate();
+            } else {
+                // We start the swipe and snap back in the same frame, we don't want any animation
+                mDragAnimPendingChildren.remove(animView);
+            }
+            NotificationMenuRowPlugin menuRow = mSwipeHelper.getCurrentMenuRow();
+            if (menuRow != null && targetLeft == 0) {
+                menuRow.resetMenu();
+                mSwipeHelper.clearCurrentMenuRow();
+            }
+        }
+
+        @Override
+        @ShadeViewRefactor(RefactorComponent.INPUT)
+        public boolean updateSwipeProgress(View animView, boolean dismissable,
+                float swipeProgress) {
+            // Returning true prevents alpha fading.
+            return !mFadeNotificationsOnDismiss;
+        }
+
+        @Override
+        @ShadeViewRefactor(RefactorComponent.INPUT)
+        public float getFalsingThresholdFactor() {
+            return mStatusBar.isWakeUpComingFromTouch() ? 1.5f : 1.0f;
+        }
+
+        @Override
+        public boolean canChildBeDismissed(View v) {
+            return NotificationStackScrollLayout.this.canChildBeDismissed(v);
+        }
+    }
 }
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
new file mode 100644
index 0000000..028957d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.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 Licen
+ */
+
+
+package com.android.systemui.statusbar.notification.stack;
+
+import android.animation.Animator;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.service.notification.StatusBarNotification;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.SwipeHelper;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
+import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
+import com.android.systemui.statusbar.notification.ShadeViewRefactor;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableView;
+
+@ShadeViewRefactor(ShadeViewRefactor.RefactorComponent.INPUT)
+class NotificationSwipeHelper extends SwipeHelper
+        implements NotificationSwipeActionHelper {
+    @VisibleForTesting
+    protected static final long COVER_MENU_DELAY = 4000;
+    private static final String TAG = "NotificationSwipeHelper";
+    private final Runnable mFalsingCheck;
+    private View mTranslatingParentView;
+    private View mMenuExposedView;
+    private final NotificationCallback mCallback;
+    private final NotificationMenuRowPlugin.OnMenuEventListener mMenuListener;
+
+    private static final long SWIPE_MENU_TIMING = 200;
+
+    private NotificationMenuRowPlugin mCurrMenuRow;
+
+    public NotificationSwipeHelper(int swipeDirection, NotificationCallback callback,
+            Context context, NotificationMenuRowPlugin.OnMenuEventListener menuListener) {
+        super(swipeDirection, callback, context);
+        mMenuListener = menuListener;
+        mCallback = callback;
+        mFalsingCheck = new Runnable() {
+            @Override
+            public void run() {
+                resetExposedMenuView(true /* animate */, true /* force */);
+            }
+        };
+    }
+
+    public View getTranslatingParentView() {
+        return mTranslatingParentView;
+    }
+
+    public void clearTranslatingParentView() { setTranslatingParentView(null); }
+
+    @VisibleForTesting
+    protected void setTranslatingParentView(View view) { mTranslatingParentView = view; };
+
+    public void setExposedMenuView(View view) {
+        mMenuExposedView = view;
+    }
+
+    public void clearExposedMenuView() { setExposedMenuView(null); }
+
+    public void clearCurrentMenuRow() { setCurrentMenuRow(null); }
+
+    public View getExposedMenuView() {
+        return mMenuExposedView;
+    }
+
+    public void setCurrentMenuRow(NotificationMenuRowPlugin menuRow) {
+        mCurrMenuRow = menuRow;
+    }
+
+    public NotificationMenuRowPlugin getCurrentMenuRow() {  return mCurrMenuRow; }
+
+    @VisibleForTesting
+    protected Handler getHandler() { return mHandler; }
+
+    @VisibleForTesting
+    protected Runnable getFalsingCheck() { return mFalsingCheck; };
+
+    @Override
+    public void onDownUpdate(View currView, MotionEvent ev) {
+        mTranslatingParentView = currView;
+        NotificationMenuRowPlugin menuRow = getCurrentMenuRow();
+        if (menuRow != null) {
+            menuRow.onTouchStart();
+        }
+        clearCurrentMenuRow();
+        getHandler().removeCallbacks(getFalsingCheck());
+
+        // Slide back any notifications that might be showing a menu
+        resetExposedMenuView(true /* animate */, false /* force */);
+
+        if (currView instanceof ExpandableNotificationRow) {
+            initializeRow((ExpandableNotificationRow) currView);
+        }
+    }
+
+    @VisibleForTesting
+    protected void initializeRow(ExpandableNotificationRow row) {
+        if (row.getEntry().hasFinishedInitialization()) {
+            mCurrMenuRow = row.createMenu();
+            mCurrMenuRow.setMenuClickListener(mMenuListener);
+            mCurrMenuRow.onTouchStart();
+        }
+    }
+
+    private boolean swipedEnoughToShowMenu(NotificationMenuRowPlugin menuRow) {
+        return !swipedFarEnough() && menuRow.isSwipedEnoughToShowMenu();
+    }
+
+    @Override
+    public void onMoveUpdate(View view, MotionEvent ev, float translation, float delta) {
+        getHandler().removeCallbacks(getFalsingCheck());
+        NotificationMenuRowPlugin menuRow = getCurrentMenuRow();
+        if (menuRow != null) {
+            menuRow.onTouchMove(delta);
+        }
+    }
+
+    @Override
+    public boolean handleUpEvent(MotionEvent ev, View animView, float velocity,
+            float translation) {
+        NotificationMenuRowPlugin menuRow = getCurrentMenuRow();
+        if (menuRow != null) {
+            menuRow.onTouchEnd();
+            handleMenuRowSwipe(ev, animView, velocity, menuRow);
+            return true;
+        }
+        return false;
+    }
+
+    @VisibleForTesting
+    protected void handleMenuRowSwipe(MotionEvent ev, View animView, float velocity,
+            NotificationMenuRowPlugin menuRow) {
+        if (!menuRow.shouldShowMenu()) {
+            // If the menu should not be shown, then there is no need to check if the a swipe
+            // should result in a snapping to the menu. As a result, just check if the swipe
+            // was enough to dismiss the notification.
+            if (isDismissGesture(ev)) {
+                dismiss(animView, velocity);
+            } else {
+                snapClosed(animView, velocity);
+                menuRow.onSnapClosed();
+            }
+            return;
+        }
+
+        if (menuRow.isSnappedAndOnSameSide()) {
+            // Menu was snapped to previously and we're on the same side
+            handleSwipeFromSnap(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);
+        }
+    }
+
+    private void handleSwipeFromNonSnap(MotionEvent ev, View animView, float velocity,
+            NotificationMenuRowPlugin menuRow) {
+        boolean isDismissGesture = isDismissGesture(ev);
+        final boolean gestureTowardsMenu = menuRow.isTowardsMenu(velocity);
+        final boolean gestureFastEnough = getEscapeVelocity() <= Math.abs(velocity);
+
+        final double timeForGesture = ev.getEventTime() - ev.getDownTime();
+        final boolean showMenuForSlowOnGoing = !menuRow.canBeDismissed()
+                && timeForGesture >= SWIPE_MENU_TIMING;
+
+        if (!isFalseGesture(ev)
+                && (swipedEnoughToShowMenu(menuRow)
+                && (!gestureFastEnough || showMenuForSlowOnGoing))
+                || (gestureTowardsMenu && !isDismissGesture)) {
+            // Menu has not been snapped to previously and this is menu revealing gesture
+            snapOpen(animView, menuRow.getMenuSnapTarget(), velocity);
+            menuRow.onSnapOpen();
+        } else if (isDismissGesture(ev) && !gestureTowardsMenu) {
+            dismiss(animView, velocity);
+            menuRow.onDismiss();
+        } else {
+            snapClosed(animView, velocity);
+            menuRow.onSnapClosed();
+        }
+    }
+
+    private void handleSwipeFromSnap(MotionEvent ev, View animView, float velocity,
+            NotificationMenuRowPlugin menuRow) {
+        boolean isDismissGesture = isDismissGesture(ev);
+
+        final boolean withinSnapMenuThreshold =
+                menuRow.isWithinSnapMenuThreshold();
+
+        if (withinSnapMenuThreshold && !isDismissGesture) {
+            // Haven't moved enough to unsnap from the menu
+            menuRow.onSnapOpen();
+            snapOpen(animView, menuRow.getMenuSnapTarget(), velocity);
+        } else if (isDismissGesture && !menuRow.shouldSnapBack()) {
+            // Only dismiss if we're not moving towards the menu
+            dismiss(animView, velocity);
+            menuRow.onDismiss();
+        } else {
+            snapClosed(animView, velocity);
+            menuRow.onSnapClosed();
+        }
+    }
+
+    @Override
+    public void dismissChild(final View view, float velocity,
+            boolean useAccelerateInterpolator) {
+        superDismissChild(view, velocity, useAccelerateInterpolator);
+        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.
+            mCallback.handleChildViewDismissed(view);
+        }
+        mCallback.onDismiss();
+        handleMenuCoveredOrDismissed();
+    }
+
+    @VisibleForTesting
+    protected void superDismissChild(final View view, float velocity, boolean useAccelerateInterpolator) {
+        super.dismissChild(view, velocity, useAccelerateInterpolator);
+    }
+
+    @VisibleForTesting
+    protected void superSnapChild(final View animView, final float targetLeft, float velocity) {
+        super.snapChild(animView, targetLeft, velocity);
+    }
+
+    @Override
+    public void snapChild(final View animView, final float targetLeft, float velocity) {
+        superSnapChild(animView, targetLeft, velocity);
+        mCallback.onDragCancelled(animView);
+        if (targetLeft == 0) {
+            handleMenuCoveredOrDismissed();
+        }
+    }
+
+    @Override
+    public void snooze(StatusBarNotification sbn, SnoozeOption snoozeOption) {
+        mCallback.onSnooze(sbn, snoozeOption);
+    }
+
+    @VisibleForTesting
+    protected void handleMenuCoveredOrDismissed() {
+        View exposedMenuView = getExposedMenuView();
+        if (exposedMenuView != null && exposedMenuView == mTranslatingParentView) {
+            clearExposedMenuView();
+        }
+    }
+
+    @VisibleForTesting
+    protected Animator superGetViewTranslationAnimator(View v, float target,
+            ValueAnimator.AnimatorUpdateListener listener) {
+        return super.getViewTranslationAnimator(v, target, listener);
+    }
+
+    @Override
+    public Animator getViewTranslationAnimator(View v, float target,
+            ValueAnimator.AnimatorUpdateListener listener) {
+        if (v instanceof ExpandableNotificationRow) {
+            return ((ExpandableNotificationRow) v).getTranslateViewAnimator(target, listener);
+        } else {
+            return superGetViewTranslationAnimator(v, target, listener);
+        }
+    }
+
+    @Override
+    public void setTranslation(View v, float translate) {
+        if (v instanceof ExpandableNotificationRow) {
+            ((ExpandableNotificationRow) v).setTranslation(translate);
+        } else {
+            Log.wtf(TAG, "setTranslation should only be called on an ExpandableNotificationRow.");
+        }
+    }
+
+    @Override
+    public float getTranslation(View v) {
+        if (v instanceof ExpandableNotificationRow) {
+            return ((ExpandableNotificationRow) v).getTranslation();
+        }
+        else {
+            Log.wtf(TAG, "getTranslation should only be called on an ExpandableNotificationRow.");
+            return 0f;
+        }
+    }
+
+    @Override
+    public boolean swipedFastEnough(float translation, float viewSize) {
+        return swipedFastEnough();
+    }
+
+    @Override
+    @VisibleForTesting
+    protected boolean swipedFastEnough() {
+        return super.swipedFastEnough();
+    }
+
+    @Override
+    public boolean swipedFarEnough(float translation, float viewSize) {
+        return swipedFarEnough();
+    }
+
+    @Override
+    @VisibleForTesting
+    protected boolean swipedFarEnough() {
+        return super.swipedFarEnough();
+    }
+
+    @Override
+    public void dismiss(View animView, float velocity) {
+        dismissChild(animView, velocity,
+                !swipedFastEnough() /* useAccelerateInterpolator */);
+    }
+
+    @Override
+    public void snapOpen(View animView, int targetLeft, float velocity) {
+        snapChild(animView, targetLeft, velocity);
+    }
+
+    @VisibleForTesting
+    protected void snapClosed(View animView, float velocity) {
+        snapChild(animView, 0, velocity);
+    }
+
+    @Override
+    @VisibleForTesting
+    protected float getEscapeVelocity() {
+        return super.getEscapeVelocity();
+    }
+
+    @Override
+    public float getMinDismissVelocity() {
+        return getEscapeVelocity();
+    }
+
+    public void onMenuShown(View animView) {
+        setExposedMenuView(getTranslatingParentView());
+        mCallback.onDragCancelled(animView);
+        Handler handler = getHandler();
+
+        // If we're on the lockscreen we want to false this.
+        if (mCallback.isAntiFalsingNeeded()) {
+            handler.removeCallbacks(getFalsingCheck());
+            handler.postDelayed(getFalsingCheck(), COVER_MENU_DELAY);
+        }
+    }
+
+    @VisibleForTesting
+    protected boolean shouldResetMenu(boolean force) {
+        if (mMenuExposedView == null
+                || (!force && mMenuExposedView == mTranslatingParentView)) {
+            // If no menu is showing or it's showing for this view we do nothing.
+            return false;
+        }
+        return true;
+    }
+
+    public void resetExposedMenuView(boolean animate, boolean force) {
+        if (!shouldResetMenu(force)) {
+            return;
+        }
+        final View prevMenuExposedView = getExposedMenuView();
+        if (animate) {
+            Animator anim = getViewTranslationAnimator(prevMenuExposedView,
+                    0 /* leftTarget */, null /* updateListener */);
+            if (anim != null) {
+                anim.start();
+            }
+        } else if (prevMenuExposedView instanceof ExpandableNotificationRow) {
+            ExpandableNotificationRow row = (ExpandableNotificationRow) prevMenuExposedView;
+            if (!row.isRemoved()) {
+                row.resetTranslation();
+            }
+        }
+        clearExposedMenuView();
+    }
+
+    public static boolean isTouchInView(MotionEvent ev, View view) {
+        if (view == null) {
+            return false;
+        }
+        final int height = (view instanceof ExpandableView)
+                ? ((ExpandableView) view).getActualHeight()
+                : view.getHeight();
+        final int rx = (int) ev.getRawX();
+        final int ry = (int) ev.getRawY();
+        int[] temp = new int[2];
+        view.getLocationOnScreen(temp);
+        final int x = temp[0];
+        final int y = temp[1];
+        Rect rect = new Rect(x, y, x + view.getWidth(), y + height);
+        boolean ret = rect.contains(rx, ry);
+        return ret;
+    }
+
+    public interface NotificationCallback extends SwipeHelper.Callback{
+        boolean isExpanded();
+
+        void handleChildViewDismissed(View view);
+
+        void onSnooze(StatusBarNotification sbn, SnoozeOption snoozeOption);
+
+        void onDismiss();
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButton.java
index 4f957bf..c7ab27b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButton.java
@@ -67,9 +67,15 @@
     }
 
     protected KeyButtonDrawable getNewDrawable() {
-        return KeyButtonDrawable.create(getContext(), mIconResId, false /* shadow */);
+        return KeyButtonDrawable.create(getContext().getApplicationContext(), mIconResId,
+                false /* shadow */);
     }
 
+    /**
+     * This context is from the view that could be stale after rotation or config change. To get
+     * correct resources use getApplicationContext() as well.
+     * @return current view context
+     */
     protected Context getContext() {
         return getCurrentView().getContext();
     }
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 cbbb0e3..9c579da 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -35,6 +35,7 @@
 import android.animation.ObjectAnimator;
 import android.annotation.IdRes;
 import android.annotation.Nullable;
+import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
 import android.app.Fragment;
 import android.app.IActivityManager;
@@ -88,8 +89,8 @@
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
 import com.android.systemui.recents.Recents;
-import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.CommandQueue.Callbacks;
@@ -284,7 +285,7 @@
         mNavigationBarView = (NavigationBarView) view;
 
         mNavigationBarView.setDisabledFlags(mDisabledFlags1);
-        mNavigationBarView.setComponents(mRecents, mDivider, mStatusBar.getPanel());
+        mNavigationBarView.setComponents(mStatusBar.getPanel());
         mNavigationBarView.setOnVerticalChangedListener(this::onVerticalChanged);
         mNavigationBarView.setOnTouchListener(this::onNavigationTouch);
         if (savedInstanceState != null) {
@@ -946,7 +947,7 @@
     private boolean onLongPressRecents() {
         if (mRecents == null || !ActivityTaskManager.supportsMultiWindow(getContext())
                 || !mDivider.getView().getSnapAlgorithm().isSplitScreenFeasible()
-                || Recents.getConfiguration().isLowRamDevice
+                || ActivityManager.isLowRamDeviceStatic()
                 // If we are connected to the overview service, then disable the recents button
                 || mOverviewProxyService.getProxy() != null) {
             return false;
@@ -1110,7 +1111,7 @@
         }
     };
 
-    class TaskStackListenerImpl extends SysUiTaskStackChangeListener {
+    class TaskStackListenerImpl extends TaskStackChangeListener {
         // Invalidate any rotation suggestion on task change or activity orientation change
         // Note: all callbacks happen on main thread
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
deleted file mode 100644
index 8c02e1f..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.phone;
-
-import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT;
-import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
-import static android.view.WindowManager.DOCKED_INVALID;
-import static android.view.WindowManager.DOCKED_LEFT;
-import static android.view.WindowManager.DOCKED_TOP;
-
-import android.app.ActivityManager;
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.view.MotionEvent;
-import android.view.VelocityTracker;
-import android.view.View;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
-import com.android.systemui.Dependency;
-import com.android.systemui.R;
-import com.android.systemui.RecentsComponent;
-import com.android.systemui.SysUiServiceProvider;
-import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
-import com.android.systemui.stackdivider.Divider;
-import com.android.systemui.tuner.TunerService;
-
-/**
- * Class to detect gestures on the navigation bar.
- */
-public class NavigationBarGestureHelper implements TunerService.Tunable, GestureHelper {
-
-    private static final String TAG = "NavBarGestureHelper";
-    private static final String KEY_DOCK_WINDOW_GESTURE = "overview_nav_bar_gesture";
-    /**
-     * When dragging from the navigation bar, we drag in recents.
-     */
-    public static final int DRAG_MODE_NONE = -1;
-
-    /**
-     * When dragging from the navigation bar, we drag in recents.
-     */
-    public static final int DRAG_MODE_RECENTS = 0;
-
-    /**
-     * When dragging from the navigation bar, we drag the divider.
-     */
-    public static final int DRAG_MODE_DIVIDER = 1;
-
-    private RecentsComponent mRecentsComponent;
-    private Divider mDivider;
-    private Context mContext;
-    private NavigationBarView mNavigationBarView;
-    private boolean mIsVertical;
-
-    private final QuickStepController mQuickStepController;
-    private final int mScrollTouchSlop;
-    private final StatusBar mStatusBar;
-    private int mTouchDownX;
-    private int mTouchDownY;
-    private boolean mDownOnRecents;
-    private VelocityTracker mVelocityTracker;
-
-    private boolean mDockWindowEnabled;
-    private boolean mDockWindowTouchSlopExceeded;
-    private int mDragMode;
-
-    public NavigationBarGestureHelper(Context context) {
-        mContext = context;
-        mStatusBar = SysUiServiceProvider.getComponent(context, StatusBar.class);
-        Resources r = context.getResources();
-        mScrollTouchSlop = r.getDimensionPixelSize(R.dimen.navigation_bar_min_swipe_distance);
-        mQuickStepController = new QuickStepController(context);
-        Dependency.get(TunerService.class).addTunable(this, KEY_DOCK_WINDOW_GESTURE);
-    }
-
-    public void destroy() {
-        Dependency.get(TunerService.class).removeTunable(this);
-    }
-
-    public void setComponents(RecentsComponent recentsComponent, Divider divider,
-            NavigationBarView navigationBarView) {
-        mRecentsComponent = recentsComponent;
-        mDivider = divider;
-        mNavigationBarView = navigationBarView;
-        mQuickStepController.setComponents(mNavigationBarView);
-    }
-
-    public void setBarState(boolean isVertical, boolean isRTL) {
-        mIsVertical = isVertical;
-        mQuickStepController.setBarState(isVertical, isRTL);
-    }
-
-    public boolean onInterceptTouchEvent(MotionEvent event) {
-        if (!canHandleGestures()) {
-            return false;
-        }
-        boolean result = mQuickStepController.onInterceptTouchEvent(event);
-        if (mDockWindowEnabled) {
-            result |= interceptDockWindowEvent(event);
-        }
-        return result;
-    }
-
-    public boolean onTouchEvent(MotionEvent event) {
-        if (!canHandleGestures()) {
-            return false;
-        }
-        boolean result = mQuickStepController.onTouchEvent(event);
-        if (mDockWindowEnabled) {
-            result |= handleDockWindowEvent(event);
-        }
-        return result;
-    }
-
-    public void onDraw(Canvas canvas) {
-        mQuickStepController.onDraw(canvas);
-    }
-
-    public void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        mQuickStepController.onLayout(changed, left, top, right, bottom);
-    }
-
-    public void onDarkIntensityChange(float intensity) {
-        mQuickStepController.onDarkIntensityChange(intensity);
-    }
-
-    public void onNavigationButtonLongPress(View v) {
-        mQuickStepController.onNavigationButtonLongPress(v);
-    }
-
-    private boolean interceptDockWindowEvent(MotionEvent event) {
-        switch (event.getActionMasked()) {
-            case MotionEvent.ACTION_DOWN:
-                handleDragActionDownEvent(event);
-                break;
-            case MotionEvent.ACTION_MOVE:
-                return handleDragActionMoveEvent(event);
-            case MotionEvent.ACTION_UP:
-            case MotionEvent.ACTION_CANCEL:
-                handleDragActionUpEvent(event);
-                break;
-        }
-        return false;
-    }
-
-    private boolean handleDockWindowEvent(MotionEvent event) {
-        switch (event.getActionMasked()) {
-            case MotionEvent.ACTION_DOWN:
-                handleDragActionDownEvent(event);
-                break;
-            case MotionEvent.ACTION_MOVE:
-                handleDragActionMoveEvent(event);
-                break;
-            case MotionEvent.ACTION_UP:
-            case MotionEvent.ACTION_CANCEL:
-                handleDragActionUpEvent(event);
-                break;
-        }
-        return true;
-    }
-
-    private void handleDragActionDownEvent(MotionEvent event) {
-        mVelocityTracker = VelocityTracker.obtain();
-        mVelocityTracker.addMovement(event);
-        mDockWindowTouchSlopExceeded = false;
-        mTouchDownX = (int) event.getX();
-        mTouchDownY = (int) event.getY();
-
-        if (mNavigationBarView != null) {
-            View recentsButton = mNavigationBarView.getRecentsButton().getCurrentView();
-            if (recentsButton != null) {
-                mDownOnRecents = mTouchDownX >= recentsButton.getLeft()
-                        && mTouchDownX <= recentsButton.getRight()
-                        && mTouchDownY >= recentsButton.getTop()
-                        && mTouchDownY <= recentsButton.getBottom();
-            } else {
-                mDownOnRecents = false;
-            }
-        }
-    }
-
-    private boolean handleDragActionMoveEvent(MotionEvent event) {
-        mVelocityTracker.addMovement(event);
-        int x = (int) event.getX();
-        int y = (int) event.getY();
-        int xDiff = Math.abs(x - mTouchDownX);
-        int yDiff = Math.abs(y - mTouchDownY);
-        if (mDivider == null || mRecentsComponent == null) {
-            return false;
-        }
-        if (!mDockWindowTouchSlopExceeded) {
-            boolean touchSlopExceeded = !mIsVertical
-                    ? yDiff > mScrollTouchSlop && yDiff > xDiff
-                    : xDiff > mScrollTouchSlop && xDiff > yDiff;
-            if (mDownOnRecents && touchSlopExceeded
-                    && mDivider.getView().getWindowManagerProxy().getDockSide() == DOCKED_INVALID) {
-                Rect initialBounds = null;
-                int dragMode = calculateDragMode();
-                int createMode = SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
-                if (dragMode == DRAG_MODE_DIVIDER) {
-                    initialBounds = new Rect();
-                    mDivider.getView().calculateBoundsForPosition(mIsVertical
-                                    ? (int) event.getRawX()
-                                    : (int) event.getRawY(),
-                            mDivider.getView().isHorizontalDivision()
-                                    ? DOCKED_TOP
-                                    : DOCKED_LEFT,
-                            initialBounds);
-                } else if (dragMode == DRAG_MODE_RECENTS && mTouchDownX
-                        < mContext.getResources().getDisplayMetrics().widthPixels / 2) {
-                    createMode = SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT;
-                }
-                boolean docked = mRecentsComponent.splitPrimaryTask(dragMode, createMode,
-                        initialBounds, MetricsEvent.ACTION_WINDOW_DOCK_SWIPE);
-                if (docked) {
-                    mDragMode = dragMode;
-                    if (mDragMode == DRAG_MODE_DIVIDER) {
-                        mDivider.getView().startDragging(false /* animate */, true /* touching*/);
-                    }
-                    mDockWindowTouchSlopExceeded = true;
-                    return true;
-                }
-            }
-        } else {
-            if (mDragMode == DRAG_MODE_DIVIDER) {
-                int position = !mIsVertical ? (int) event.getRawY() : (int) event.getRawX();
-                SnapTarget snapTarget = mDivider.getView().getSnapAlgorithm()
-                        .calculateSnapTarget(position, 0f /* velocity */, false /* hardDismiss */);
-                mDivider.getView().resizeStack(position, snapTarget.position, snapTarget);
-            } else if (mDragMode == DRAG_MODE_RECENTS) {
-                mRecentsComponent.onDraggingInRecents(event.getRawY());
-            }
-        }
-        return false;
-    }
-
-    private void handleDragActionUpEvent(MotionEvent event) {
-        mVelocityTracker.addMovement(event);
-        mVelocityTracker.computeCurrentVelocity(1000);
-        if (mDockWindowTouchSlopExceeded && mDivider != null && mRecentsComponent != null) {
-            if (mDragMode == DRAG_MODE_DIVIDER) {
-                mDivider.getView().stopDragging(mIsVertical
-                                ? (int) event.getRawX()
-                                : (int) event.getRawY(),
-                        mIsVertical
-                                ? mVelocityTracker.getXVelocity()
-                                : mVelocityTracker.getYVelocity(),
-                        true /* avoidDismissStart */, false /* logMetrics */);
-            } else if (mDragMode == DRAG_MODE_RECENTS) {
-                mRecentsComponent.onDraggingInRecentsEnded(mVelocityTracker.getYVelocity());
-            }
-        }
-        mVelocityTracker.recycle();
-        mVelocityTracker = null;
-    }
-
-    private boolean canHandleGestures() {
-        return !mStatusBar.isKeyguardShowing();
-    }
-
-    private int calculateDragMode() {
-        if (mIsVertical && !mDivider.getView().isHorizontalDivision()) {
-            return DRAG_MODE_DIVIDER;
-        }
-        if (!mIsVertical && mDivider.getView().isHorizontalDivision()) {
-            return DRAG_MODE_DIVIDER;
-        }
-        return DRAG_MODE_RECENTS;
-    }
-
-    @Override
-    public void onTuningChanged(String key, String newValue) {
-        switch (key) {
-            case KEY_DOCK_WINDOW_GESTURE:
-                mDockWindowEnabled = newValue != null && (Integer.parseInt(newValue) != 0);
-                break;
-        }
-    }
-}
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 e6f2c33..52134d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -37,7 +37,7 @@
 import com.android.systemui.OverviewProxyService;
 import com.android.systemui.R;
 import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider;
 import com.android.systemui.statusbar.phone.ReverseLinearLayout.ReverseRelativeLayout;
 import com.android.systemui.statusbar.policy.KeyButtonView;
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 aebcb9f..16b2987 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -40,7 +40,6 @@
 import android.os.Handler;
 import android.os.Message;
 import android.os.SystemProperties;
-import androidx.annotation.ColorInt;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.SparseArray;
@@ -64,12 +63,11 @@
 import com.android.systemui.RecentsComponent;
 import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.plugins.PluginManager;
+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.Recents;
 import com.android.systemui.recents.RecentsOnboarding;
-import com.android.systemui.shared.recents.IOverviewProxy;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.NavigationBarCompat;
 import com.android.systemui.shared.system.WindowManagerWrapper;
@@ -144,8 +142,6 @@
     private Configuration mConfiguration;
 
     private NavigationBarInflaterView mNavigationInflaterView;
-    private RecentsComponent mRecentsComponent;
-    private Divider mDivider;
     private RecentsOnboarding mRecentsOnboarding;
     private NotificationPanelView mPanelView;
 
@@ -314,14 +310,10 @@
         return mBarTransitions.getLightTransitionsController();
     }
 
-    public void setComponents(RecentsComponent recentsComponent, Divider divider,
-            NotificationPanelView panel) {
-        mRecentsComponent = recentsComponent;
-        mDivider = divider;
+    public void setComponents(NotificationPanelView panel) {
         mPanelView = panel;
-        if (mGestureHelper instanceof NavigationBarGestureHelper) {
-            ((NavigationBarGestureHelper) mGestureHelper).setComponents(
-                    recentsComponent, divider, this);
+        if (mGestureHelper instanceof QuickStepController) {
+            ((QuickStepController) mGestureHelper).setComponents(this);
         }
     }
 
@@ -595,6 +587,10 @@
 
         boolean disableHome = ((mDisabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);
 
+        // TODO(b/113914868): investigation log for disappearing home button
+        Log.i(TAG, "updateNavButtonIcons (b/113914868): home disabled=" + disableHome
+                + " mDisabledFlags=" + mDisabledFlags);
+
         // Always disable recents when alternate car mode UI is active.
         boolean disableRecent = mUseCarModeUi || !isOverviewEnabled();
 
@@ -1073,8 +1069,8 @@
 
     @Override
     public void onPluginDisconnected(NavGesture plugin) {
-        NavigationBarGestureHelper defaultHelper = new NavigationBarGestureHelper(getContext());
-        defaultHelper.setComponents(mRecentsComponent, mDivider, this);
+        QuickStepController defaultHelper = new QuickStepController(getContext());
+        defaultHelper.setComponents(this);
         if (mGestureHelper != null) {
             mGestureHelper.destroy();
         }
@@ -1119,6 +1115,7 @@
         pw.println("    }");
 
         mContextualButtonGroup.dump(pw);
+        mGestureHelper.dump(pw);
         mRecentsOnboarding.dump(pw);
     }
 
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 09833d4..1524f80 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java
@@ -95,6 +95,9 @@
     }
 
     private View findNearestChild(MotionEvent event) {
+        if (mClickableChildren.isEmpty()) {
+            return null;
+        }
         return mClickableChildren
                 .stream()
                 .filter(v -> v.isAttachedToWindow())
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationListenerWithPlugins.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationListenerWithPlugins.java
index 9ff907b..9e561d1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationListenerWithPlugins.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationListenerWithPlugins.java
@@ -24,7 +24,7 @@
 import com.android.systemui.plugins.NotificationListenerController;
 import com.android.systemui.plugins.NotificationListenerController.NotificationProvider;
 import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.shared.plugins.PluginManager;
 
 import java.util.ArrayList;
 
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 a900c14..553165b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -67,8 +67,8 @@
 import com.android.systemui.UiOffloadThread;
 import com.android.systemui.qs.tiles.DndTile;
 import com.android.systemui.qs.tiles.RotationLockTile;
-import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.CommandQueue.Callbacks;
 import com.android.systemui.statusbar.policy.BluetoothController;
@@ -595,16 +595,29 @@
         extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
                 mContext.getString(R.string.instant_apps));
         mCurrentNotifs.add(new Pair<>(pkg, userId));
-        String message = mContext.getString(R.string.instant_apps_message);
+
+        String helpUrl = mContext.getString(R.string.instant_apps_help_url);
+        boolean hasHelpUrl = !helpUrl.isEmpty();
+        String message = mContext.getString(hasHelpUrl
+                ? R.string.instant_apps_message_with_help
+                : R.string.instant_apps_message);
+
         UserHandle user = UserHandle.of(userId);
         PendingIntent appInfoAction = PendingIntent.getActivityAsUser(mContext, 0,
                 new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
                         .setData(Uri.fromParts("package", pkg, null)), 0, null, user);
         Action action = new Notification.Action.Builder(null, mContext.getString(R.string.app_info),
                 appInfoAction).build();
+        PendingIntent helpCenterIntent = hasHelpUrl
+                ? PendingIntent.getActivityAsUser(mContext, 0,
+                new Intent(Intent.ACTION_VIEW).setData(Uri.parse(
+                        helpUrl)),
+                0, null, user)
+                : null;
 
         Intent browserIntent = getTaskIntent(taskId, userId);
-        Notification.Builder builder = new Notification.Builder(mContext, NotificationChannels.GENERAL);
+        Notification.Builder builder = new Notification.Builder(mContext,
+                NotificationChannels.GENERAL);
         if (browserIntent != null && browserIntent.isWebIntent()) {
             // Make sure that this doesn't resolve back to an instant app
             browserIntent.setComponent(null)
@@ -632,7 +645,8 @@
 
             PendingIntent webPendingIntent = PendingIntent.getActivityAsUser(mContext, 0,
                     goToWebIntent, 0, null, user);
-            Action webAction = new Notification.Action.Builder(null, mContext.getString(R.string.go_to_web),
+            Action webAction = new Notification.Action.Builder(null,
+                    mContext.getString(R.string.go_to_web),
                     webPendingIntent).build();
             builder.addAction(webAction);
         }
@@ -640,13 +654,15 @@
         noMan.notifyAsUser(pkg, SystemMessage.NOTE_INSTANT_APPS, builder
                         .addExtras(extras)
                         .addAction(action)
-                        .setContentIntent(appInfoAction)
+                        .setContentIntent(helpCenterIntent)
                         .setColor(mContext.getColor(R.color.instant_apps_color))
-                        .setContentTitle(appInfo.loadLabel(mContext.getPackageManager()))
+                        .setContentTitle(mContext.getString(R.string.instant_apps_title,
+                                appInfo.loadLabel(mContext.getPackageManager())))
                         .setLargeIcon(Icon.createWithResource(pkg, appInfo.icon))
                         .setSmallIcon(Icon.createWithResource(mContext.getPackageName(),
                                 R.drawable.instant_icon))
                         .setContentText(message)
+                        .setStyle(new Notification.BigTextStyle().bigText(message))
                         .setOngoing(true)
                         .build(),
                 new UserHandle(userId));
@@ -781,7 +797,7 @@
         mIconController.setIconVisibility(mSlotDataSaver, isDataSaving);
     }
 
-    private final SysUiTaskStackChangeListener mTaskListener = new SysUiTaskStackChangeListener() {
+    private final TaskStackChangeListener mTaskListener = new TaskStackChangeListener() {
         @Override
         public void onTaskStackChanged() {
             // Listen for changes to stacks and then check which instant apps are foreground.
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 30e6afa..bce52a2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
@@ -58,10 +58,12 @@
 import com.android.systemui.Interpolators;
 import com.android.systemui.OverviewProxyService;
 import com.android.systemui.R;
+import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
 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.
@@ -117,6 +119,7 @@
     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();
@@ -195,6 +198,7 @@
     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);
@@ -218,6 +222,10 @@
      */
     @Override
     public boolean onInterceptTouchEvent(MotionEvent event) {
+        if (mStatusBar.isKeyguardShowing()) {
+            // Disallow any handling when the keyguard is showing
+            return false;
+        }
         return handleTouchEvent(event);
     }
 
@@ -227,6 +235,11 @@
      */
     @Override
     public boolean onTouchEvent(MotionEvent event) {
+        if (mStatusBar.isKeyguardShowing()) {
+            // Disallow any handling when the keyguard is showing
+            return false;
+        }
+
         // The same down event was just sent on intercept and therefore can be ignored here
         final boolean ignoreProxyDownEvent = event.getAction() == MotionEvent.ACTION_DOWN
                 && mOverviewEventSender.getProxy() != null;
@@ -483,6 +496,21 @@
         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("mIsRTL=" + mIsRTL);
+        pw.print("    "); pw.println("mIsInScreenPinning=" + mIsInScreenPinning);
+        pw.println("}");
+    }
+
     private void startQuickStep(MotionEvent event) {
         if (mIsInScreenPinning) {
             mNavigationBarView.showPinningEscapeToast();
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 103781b..c3b87af 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -102,6 +102,8 @@
 import android.os.VibrationEffect;
 import android.os.Vibrator;
 import android.provider.Settings;
+import android.service.dreams.DreamService;
+import android.service.dreams.IDreamManager;
 import android.service.notification.StatusBarNotification;
 import android.service.vr.IVrManager;
 import android.service.vr.IVrStateCallbacks;
@@ -154,6 +156,7 @@
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.RecentsComponent;
+import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.SystemUI;
 import com.android.systemui.SystemUIFactory;
 import com.android.systemui.UiOffloadThread;
@@ -179,10 +182,6 @@
 import com.android.systemui.qs.car.CarQSFragment;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.ScreenPinningRequest;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.AppTransitionFinishedEvent;
-import com.android.systemui.recents.events.activity.UndockingTaskEvent;
-import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.shared.system.WindowManagerWrapper;
 import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.stackdivider.WindowManagerProxy;
@@ -255,7 +254,8 @@
         ActivityStarter, OnUnlockMethodChangedListener,
         OnHeadsUpChangedListener, CommandQueue.Callbacks, ZenModeController.Callback,
         ColorExtractor.OnColorsChangedListener, ConfigurationListener, NotificationPresenter,
-        StatusBarStateController.StateListener,  AmbientPulseManager.OnAmbientChangedListener {
+        StatusBarStateController.StateListener,  AmbientPulseManager.OnAmbientChangedListener,
+        ActivityLaunchAnimator.Callback {
     public static final boolean MULTIUSER_DEBUG = false;
 
     public static final boolean ENABLE_CHILD_NOTIFICATIONS
@@ -634,6 +634,8 @@
         mStatusBarStateController.addListener(this, StatusBarStateController.RANK_STATUS_BAR);
 
         mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+        mDreamManager = IDreamManager.Stub.asInterface(
+                ServiceManager.checkService(DreamService.DREAM_SERVICE));
 
         mDisplay = mWindowManager.getDefaultDisplay();
         updateDisplaySize();
@@ -1166,6 +1168,8 @@
                 mScrimController, this, UnlockMethodCache.getInstance(mContext));
         mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
                 getBouncerContainer(), mNotificationPanel, mBiometricUnlockController);
+        //TODO: Can we put the keyguard view manager in Dependency?
+        mLockscreenUserManager.setKeyguardViewManager(mStatusBarKeyguardViewManager);
         mKeyguardIndicationController
                 .setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
         mBiometricUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
@@ -1211,17 +1215,18 @@
             int createMode = navbarPos == NAV_BAR_POS_LEFT
                     ? SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT
                     : SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
-            return mRecents.splitPrimaryTask(NavigationBarGestureHelper.DRAG_MODE_NONE, createMode,
-                    null, metricsDockAction);
+            return mRecents.splitPrimaryTask(createMode, null, metricsDockAction);
         } else {
             Divider divider = getComponent(Divider.class);
-            if (divider != null && divider.isMinimized() && !divider.isHomeStackResizable()) {
-                // Undocking from the minimized state is not supported
-                return false;
-            } else {
-                EventBus.getDefault().send(new UndockingTaskEvent());
-                if (metricsUndockAction != -1) {
-                    mMetricsLogger.action(metricsUndockAction);
+            if (divider != null) {
+                if (divider.isMinimized() && !divider.isHomeStackResizable()) {
+                    // Undocking from the minimized state is not supported
+                    return false;
+                } else {
+                    divider.onUndockingTask();
+                    if (metricsUndockAction != -1) {
+                        mMetricsLogger.action(metricsUndockAction);
+                    }
                 }
             }
         }
@@ -1906,6 +1911,7 @@
         }
     }
 
+    @Override
     public void onLaunchAnimationCancelled() {
         if (!isCollapsing()) {
             onClosingFinished();
@@ -1916,6 +1922,31 @@
         return mHeadsUpAppearanceController.shouldBeVisible();
     }
 
+    @Override
+    public void onExpandAnimationFinished(boolean launchIsFullScreen) {
+        if (!isCollapsing()) {
+            onClosingFinished();
+        }
+        if (launchIsFullScreen) {
+            instantCollapseNotificationPanel();
+        }
+    }
+
+    @Override
+    public void onExpandAnimationTimedOut() {
+        if (isPresenterFullyCollapsed() && !isCollapsing()
+                && !mActivityLaunchAnimator.isLaunchForActivity()) {
+            onClosingFinished();
+        } else {
+            collapsePanel(true /* animate */);
+        }
+    }
+
+    @Override
+    public boolean areLaunchAnimationsEnabled() {
+        return mState == StatusBarState.SHADE;
+    }
+
     /**
      * All changes to the status bar and notifications funnel through here and are batched.
      */
@@ -2151,7 +2182,7 @@
     }
 
     @Override
-    public void animateExpandSettingsPanel(String subPanel) {
+    public void animateExpandSettingsPanel(@Nullable String subPanel) {
         if (SPEW) Log.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible);
         if (!panelsEnabled()) {
             return;
@@ -2160,7 +2191,6 @@
         // Settings are not available in setup
         if (!mUserSetup) return;
 
-
         if (subPanel != null) {
             mQSPanel.openDetails(subPanel);
         }
@@ -2919,8 +2949,6 @@
         // End old BaseStatusBar.userSwitched
         if (MULTIUSER_DEBUG) mNotificationPanelDebugText.setText("USER " + newUserId);
         animateCollapsePanels();
-        updatePublicMode();
-        mEntryManager.getNotificationData().filterAndSort();
         if (mReinflateNotificationsOnUserSwitched) {
             mEntryManager.updateNotificationsOnDensityOrFontScaleChanged();
             mReinflateNotificationsOnUserSwitched = false;
@@ -3353,7 +3381,9 @@
     }
 
     public boolean isCollapsing() {
-        return mNotificationPanel.isCollapsing() || mActivityLaunchAnimator.isAnimationPending();
+        return mNotificationPanel.isCollapsing()
+                || mActivityLaunchAnimator.isAnimationPending()
+                || mActivityLaunchAnimator.isAnimationRunning();
     }
 
     public void addPostCollapseAction(Runnable r) {
@@ -3464,7 +3494,7 @@
             // notify listeners.
 
             // If the state didn't change, we may still need to update public mode
-            updatePublicMode();
+            mLockscreenUserManager.updatePublicMode();
             mEntryManager.updateNotifications();
         }
         View viewToClick = null;
@@ -3552,34 +3582,6 @@
         mScrimController.setExpansionAffectsAlpha(true);
     }
 
-    // TODO: Move this to NotificationLockscreenUserManager.
-    private void updatePublicMode() {
-        final boolean showingKeyguard = mStatusBarKeyguardViewManager.isShowing();
-        final boolean devicePublic = showingKeyguard
-                && mStatusBarKeyguardViewManager.isSecure(
-                        mLockscreenUserManager.getCurrentUserId());
-
-        // Look for public mode users. Users are considered public in either case of:
-        //   - device keyguard is shown in secure mode;
-        //   - profile is locked with a work challenge.
-        SparseArray<UserInfo> currentProfiles = mLockscreenUserManager.getCurrentProfiles();
-        for (int i = currentProfiles.size() - 1; i >= 0; i--) {
-            final int userId = currentProfiles.valueAt(i).id;
-            boolean isProfilePublic = devicePublic;
-            if (!devicePublic && userId != mLockscreenUserManager.getCurrentUserId()) {
-                // We can't rely on KeyguardManager#isDeviceLocked() for unified profile challenge
-                // due to a race condition where this code could be called before
-                // TrustManagerService updates its internal records, resulting in an incorrect
-                // state being cached in mLockscreenPublicMode. (b/35951989)
-                if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
-                        && mStatusBarKeyguardViewManager.isSecure(userId)) {
-                    isProfilePublic = mKeyguardManager.isDeviceLocked(userId);
-                }
-            }
-            mLockscreenUserManager.setLockscreenPublicMode(isProfilePublic, userId);
-        }
-    }
-
     /**
      * Switches theme from light to dark and vice-versa.
      */
@@ -3770,8 +3772,6 @@
             }
         }
         updateDozingState();
-        updatePublicMode();
-        mEntryManager.updateNotifications();
         checkBarModes();
         updateScrimController();
         updateMediaMetaData(false, mState != StatusBarState.KEYGUARD);
@@ -4024,8 +4024,6 @@
 
     @Override
     public void onWorkChallengeChanged() {
-        updatePublicMode();
-        mEntryManager.updateNotifications();
         if (mPendingWorkRemoteInputView != null
                 && !mLockscreenUserManager.isAnyProfilePublicMode()) {
             // Expand notification panel and the notification row, then click on remote input view
@@ -4249,12 +4247,12 @@
 
     @Override
     public void appTransitionCancelled() {
-        EventBus.getDefault().send(new AppTransitionFinishedEvent());
+        getComponent(Divider.class).onAppTransitionFinished();
     }
 
     @Override
     public void appTransitionFinished() {
-        EventBus.getDefault().send(new AppTransitionFinishedEvent());
+        getComponent(Divider.class).onAppTransitionFinished();
     }
 
     @Override
@@ -4666,6 +4664,7 @@
 
     protected WindowManager mWindowManager;
     protected IWindowManager mWindowManagerService;
+    private IDreamManager mDreamManager;
 
     protected Display mDisplay;
 
@@ -4738,7 +4737,8 @@
                 : notification.fullScreenIntent;
         final String notificationKey = sbn.getKey();
 
-        final boolean afterKeyguardGone = intent.isActivity()
+        boolean isActivityIntent = intent.isActivity();
+        final boolean afterKeyguardGone = isActivityIntent
                 && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(),
                 mLockscreenUserManager.getCurrentUserId());
         final boolean wasOccluded = mIsOccluded;
@@ -4779,7 +4779,7 @@
                     // If we are launching a work activity and require to launch
                     // separate work challenge, we defer the activity action and cancel
                     // notification until work challenge is unlocked.
-                    if (intent.isActivity()) {
+                    if (isActivityIntent) {
                         final int userId = intent.getCreatorUserHandle().getIdentifier();
                         if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
                                 && mKeyguardManager.isDeviceLocked(userId)) {
@@ -4815,7 +4815,7 @@
                         }
                         launchResult = intent.sendAndReturnResult(mContext, 0, fillInIntent, null,
                                 null, null, getActivityOptions(adapter));
-                        mActivityLaunchAnimator.setLaunchResult(launchResult);
+                        mActivityLaunchAnimator.setLaunchResult(launchResult, isActivityIntent);
                     } catch (RemoteException | PendingIntent.CanceledException e) {
                         // the stack trace isn't very helpful here.
                         // Just log the exception message.
@@ -4823,7 +4823,7 @@
 
                         // TODO: Dismiss Keyguard.
                     }
-                    if (intent.isActivity()) {
+                    if (isActivityIntent) {
                         mAssistManager.hideAssist();
                     }
                 }
@@ -4942,7 +4942,7 @@
                         .startActivities(getActivityOptions(
                                 mActivityLaunchAnimator.getLaunchAnimation(row, mIsOccluded)),
                                 new UserHandle(UserHandle.getUserId(appUid)));
-                mActivityLaunchAnimator.setLaunchResult(launchResult);
+                mActivityLaunchAnimator.setLaunchResult(launchResult, true /* isActivityIntent */);
                 if (shouldCollapse()) {
                     // Putting it back on the main thread, since we're touching views
                     mStatusBarWindow.post(() -> animateCollapsePanels(
@@ -4969,7 +4969,13 @@
     }
 
     void awakenDreams() {
-        SystemServicesProxy.getInstance(mContext).awakenDreamsAsync();
+        Dependency.get(UiOffloadThread.class).submit(() -> {
+            try {
+                mDreamManager.awaken();
+            } catch (RemoteException e) {
+                e.printStackTrace();
+            }
+        });
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java
index 6d75cfc..a6146a6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java
@@ -22,7 +22,7 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.plugins.Plugin;
 import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
@@ -71,7 +71,7 @@
 
         @Override
         public <P extends T> ExtensionController.ExtensionBuilder<T> withPlugin(Class<P> cls) {
-            return withPlugin(cls, PluginManager.getAction(cls));
+            return withPlugin(cls, PluginManager.Helper.getAction(cls));
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
index e9efaa1..0a72c3f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
@@ -17,10 +17,7 @@
 package com.android.systemui.statusbar.policy;
 
 import android.app.ActivityManager;
-import android.content.BroadcastReceiver;
 import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.net.ConnectivityManager;
 import android.net.wifi.WifiManager;
 import android.os.UserManager;
@@ -38,14 +35,13 @@
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private final ArrayList<Callback> mCallbacks = new ArrayList<>();
-    private final WifiStateReceiver mWifiStateReceiver = new WifiStateReceiver();
     private final ConnectivityManager mConnectivityManager;
     private final WifiManager mWifiManager;
     private final Context mContext;
 
     private int mHotspotState;
     private int mNumConnectedDevices;
-    private boolean mWaitingForCallback;
+    private boolean mWaitingForTerminalState;
 
     public HotspotControllerImpl(Context context) {
         mContext = context;
@@ -63,7 +59,9 @@
 
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("HotspotController state:");
-        pw.print("  mHotspotEnabled="); pw.println(stateToString(mHotspotState));
+        pw.print("  mHotspotState="); pw.println(stateToString(mHotspotState));
+        pw.print("  mNumConnectedDevices="); pw.println(mNumConnectedDevices);
+        pw.print("  mWaitingForTerminalState="); pw.println(mWaitingForTerminalState);
     }
 
     private static String stateToString(int hotspotState) {
@@ -99,7 +97,6 @@
         if (DEBUG) Log.d(TAG, "removeCallback " + callback);
         synchronized (mCallbacks) {
             mCallbacks.remove(callback);
-
             updateWifiStateListeners(!mCallbacks.isEmpty());
         }
     }
@@ -112,7 +109,6 @@
      * @param shouldListen whether we should start listening to various wifi statuses
      */
     private void updateWifiStateListeners(boolean shouldListen) {
-        mWifiStateReceiver.setListening(shouldListen);
         if (shouldListen) {
             mWifiManager.registerSoftApCallback(
                     this,
@@ -129,21 +125,27 @@
 
     @Override
     public boolean isHotspotTransient() {
-        return mWaitingForCallback || (mHotspotState == WifiManager.WIFI_AP_STATE_ENABLING);
+        return mWaitingForTerminalState || (mHotspotState == WifiManager.WIFI_AP_STATE_ENABLING);
     }
 
     @Override
     public void setHotspotEnabled(boolean enabled) {
-        if (mWaitingForCallback) {
-            if (DEBUG) Log.d(TAG, "Ignoring setHotspotEnabled; waiting for callback.");
+        if (mWaitingForTerminalState) {
+            if (DEBUG) Log.d(TAG, "Ignoring setHotspotEnabled; waiting for terminal state.");
             return;
         }
         if (enabled) {
-            OnStartTetheringCallback callback = new OnStartTetheringCallback();
-            mWaitingForCallback = true;
+            mWaitingForTerminalState = true;
             if (DEBUG) Log.d(TAG, "Starting tethering");
-            mConnectivityManager.startTethering(
-                    ConnectivityManager.TETHERING_WIFI, false, callback);
+            mConnectivityManager.startTethering(ConnectivityManager.TETHERING_WIFI, false,
+                    new ConnectivityManager.OnStartTetheringCallback() {
+                        @Override
+                        public void onTetheringFailed() {
+                            if (DEBUG) Log.d(TAG, "onTetheringFailed");
+                            maybeResetSoftApState();
+                            fireHotspotChangedCallback();
+                        }
+                    });
         } else {
             mConnectivityManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
         }
@@ -155,99 +157,56 @@
     }
 
     /**
-     * Sends a hotspot changed callback with the new enabled status. Wraps
-     * {@link #fireHotspotChangedCallback(boolean, int)} and assumes that the number of devices has
-     * not changed.
-     *
-     * @param enabled whether the hotspot is enabled
+     * Sends a hotspot changed callback.
+     * Be careful when calling over multiple threads, especially if one of them is the main thread
+     * (as it can be blocked).
      */
-    private void fireHotspotChangedCallback(boolean enabled) {
-        fireHotspotChangedCallback(enabled, mNumConnectedDevices);
-    }
-
-    /**
-     * Sends a hotspot changed callback with the new enabled status & the number of devices
-     * connected to the hotspot. Be careful when calling over multiple threads, especially if one of
-     * them is the main thread (as it can be blocked).
-     *
-     * @param enabled whether the hotspot is enabled
-     * @param numConnectedDevices number of devices connected to the hotspot
-     */
-    private void fireHotspotChangedCallback(boolean enabled, int numConnectedDevices) {
+    private void fireHotspotChangedCallback() {
         synchronized (mCallbacks) {
             for (Callback callback : mCallbacks) {
-                callback.onHotspotChanged(enabled, numConnectedDevices);
+                callback.onHotspotChanged(isHotspotEnabled(), mNumConnectedDevices);
             }
         }
     }
 
     @Override
     public void onStateChanged(int state, int failureReason) {
-        // Do nothing - we don't care about changing anything here.
+        // Update internal hotspot state for tracking before using any enabled/callback methods.
+        mHotspotState = state;
+
+        maybeResetSoftApState();
+        if (!isHotspotEnabled()) {
+            // Reset num devices if the hotspot is no longer enabled so we don't get ghost
+            // counters.
+            mNumConnectedDevices = 0;
+        }
+
+        fireHotspotChangedCallback();
+    }
+
+    private void maybeResetSoftApState() {
+        if (!mWaitingForTerminalState) {
+            return; // Only reset soft AP state if enabled from this controller.
+        }
+        switch (mHotspotState) {
+            case WifiManager.WIFI_AP_STATE_FAILED:
+                // TODO(b/110697252): must be called to reset soft ap state after failure
+                mConnectivityManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
+                // Fall through
+            case WifiManager.WIFI_AP_STATE_ENABLED:
+            case WifiManager.WIFI_AP_STATE_DISABLED:
+                mWaitingForTerminalState = false;
+                break;
+            case WifiManager.WIFI_AP_STATE_ENABLING:
+            case WifiManager.WIFI_AP_STATE_DISABLING:
+            default:
+                break;
+        }
     }
 
     @Override
     public void onNumClientsChanged(int numConnectedDevices) {
         mNumConnectedDevices = numConnectedDevices;
-        fireHotspotChangedCallback(isHotspotEnabled(), numConnectedDevices);
-    }
-
-    private final class OnStartTetheringCallback extends
-            ConnectivityManager.OnStartTetheringCallback {
-        @Override
-        public void onTetheringStarted() {
-            if (DEBUG) Log.d(TAG, "onTetheringStarted");
-            mWaitingForCallback = false;
-            // Don't fire a callback here, instead wait for the next update from wifi.
-        }
-
-        @Override
-        public void onTetheringFailed() {
-            if (DEBUG) Log.d(TAG, "onTetheringFailed");
-            mWaitingForCallback = false;
-            // TODO(b/110697252): stopTethering must be called to reset soft ap state after failure
-            mConnectivityManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
-            fireHotspotChangedCallback(isHotspotEnabled());
-          // TODO: Show error.
-        }
-    }
-
-    /**
-     * Class to listen in on wifi state and update the hotspot state
-     */
-    private final class WifiStateReceiver extends BroadcastReceiver {
-        private boolean mRegistered;
-
-        public void setListening(boolean listening) {
-            if (listening && !mRegistered) {
-                if (DEBUG) Log.d(TAG, "Registering receiver");
-                final IntentFilter filter = new IntentFilter();
-                filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
-                mContext.registerReceiver(this, filter);
-                mRegistered = true;
-            } else if (!listening && mRegistered) {
-                if (DEBUG) Log.d(TAG, "Unregistering receiver");
-                mContext.unregisterReceiver(this);
-                mRegistered = false;
-            }
-        }
-
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            int state = intent.getIntExtra(
-                    WifiManager.EXTRA_WIFI_AP_STATE, WifiManager.WIFI_AP_STATE_FAILED);
-            if (DEBUG) Log.d(TAG, "onReceive " + state);
-
-            // Update internal hotspot state for tracking before using any enabled/callback methods.
-            mHotspotState = state;
-
-            if (!isHotspotEnabled()) {
-                // Reset num devices if the hotspot is no longer enabled so we don't get ghost
-                // counters.
-                mNumConnectedDevices = 0;
-            }
-
-            fireHotspotChangedCallback(isHotspotEnabled());
-        }
+        fireHotspotChangedCallback();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index cf39404..24a28cb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -668,6 +668,7 @@
         Locale current = mContext.getResources().getConfiguration().locale;
         if (!current.equals(mLocale)) {
             mLocale = current;
+            mWifiSignalController.refreshLocale();
             notifyAllListeners();
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
index 0233ad1..693df88 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -73,6 +73,10 @@
         return new WifiState();
     }
 
+    void refreshLocale() {
+        mWifiTracker.refreshLocale();
+    }
+
     @Override
     public void notifyListeners(SignalCallback callback) {
         // only show wifi in the cluster if connected or if wifi-only
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java
index c294806..71414a2 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java
@@ -34,11 +34,10 @@
 import android.view.View;
 
 import com.android.systemui.R;
-import com.android.systemui.plugins.PluginInstanceManager;
-import com.android.systemui.plugins.PluginManager;
-import com.android.systemui.plugins.PluginPrefs;
+import com.android.systemui.shared.plugins.PluginInstanceManager;
+import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.shared.plugins.PluginPrefs;
 
-import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
 
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
index 088630f..5aa3035 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
@@ -32,7 +32,7 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
-import com.android.systemui.plugins.PluginPrefs;
+import com.android.systemui.shared.plugins.PluginPrefs;
 
 public class TunerFragment extends PreferenceFragment {
 
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 13c43f7..4810b0b 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -18,6 +18,7 @@
 
 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;
 import static android.media.AudioManager.RINGER_MODE_VIBRATE;
@@ -34,6 +35,7 @@
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.animation.ObjectAnimator;
 import android.annotation.SuppressLint;
+import android.app.ActivityManager;
 import android.app.Dialog;
 import android.app.KeyguardManager;
 import android.content.ContentResolver;
@@ -129,6 +131,7 @@
     private ConfigurableTexts mConfigurableTexts;
     private final SparseBooleanArray mDynamic = new SparseBooleanArray();
     private final KeyguardManager mKeyguard;
+    private final ActivityManager mActivityManager;
     private final AccessibilityManagerWrapper mAccessibilityMgr;
     private final Object mSafetyWarningLock = new Object();
     private final Accessibility mAccessibility = new Accessibility();
@@ -154,6 +157,7 @@
         mContext = new ContextThemeWrapper(context, com.android.systemui.R.style.qs_theme);
         mController = Dependency.get(VolumeDialogController.class);
         mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
+        mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
         mAccessibilityMgr = Dependency.get(AccessibilityManagerWrapper.class);
         mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
         mShowActiveStreamOnly = showActiveStreamOnly();
@@ -431,7 +435,9 @@
     public void initSettingsH() {
         if (mSettingsView != null) {
             mSettingsView.setVisibility(
-                    mDeviceProvisionedController.isCurrentUserSetup() ? VISIBLE : GONE);
+                    mDeviceProvisionedController.isCurrentUserSetup() &&
+                            mActivityManager.getLockTaskModeState() == LOCK_TASK_MODE_NONE ?
+                            VISIBLE : GONE);
         }
         if (mSettingsIcon != null) {
             mSettingsIcon.setOnClickListener(v -> {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
index e6e4857..62ca3f3 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
@@ -40,7 +40,7 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.ClockPlugin;
 import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.shared.plugins.PluginManager;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewTest.kt
new file mode 100644
index 0000000..cfe9818
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewTest.kt
@@ -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
+ */
+
+package com.android.keyguard
+
+import android.support.test.filters.SmallTest
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.view.LayoutInflater
+
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+class KeyguardPatternViewTest : SysuiTestCase() {
+
+    private lateinit var mKeyguardPatternView: KeyguardPatternView
+    private lateinit var mSecurityMessage: KeyguardMessageArea
+
+    @Before
+    fun setup() {
+        val inflater = LayoutInflater.from(context)
+        mKeyguardPatternView = inflater.inflate(R.layout.keyguard_pattern_view, null)
+                as KeyguardPatternView
+        mSecurityMessage = KeyguardMessageArea.findSecurityMessageDisplay(mKeyguardPatternView)
+                as KeyguardMessageArea
+    }
+
+    @Test
+    fun onResume_clearsTextField() {
+        mSecurityMessage.setMessage("an old message")
+        mKeyguardPatternView.onResume(KeyguardSecurityView.SCREEN_ON)
+        assertThat(mSecurityMessage.text).isEqualTo("")
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
index eaa0dcf..1cf73b0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
@@ -33,6 +33,7 @@
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 
+import android.content.Intent;
 import android.os.PowerManager;
 import android.os.UserHandle;
 import android.provider.Settings;
@@ -71,7 +72,8 @@
         mSensor = mSensorManager.getFakeLightSensor();
         mScreen = new DozeScreenBrightness(mContext, mServiceFake, mSensorManager,
                 mSensor.getSensor(), mHostFake, null /* handler */,
-                DEFAULT_BRIGHTNESS, SENSOR_TO_BRIGHTNESS, SENSOR_TO_OPACITY);
+                DEFAULT_BRIGHTNESS, SENSOR_TO_BRIGHTNESS, SENSOR_TO_OPACITY,
+                true /* debuggable */);
     }
 
     @Test
@@ -93,6 +95,19 @@
     }
 
     @Test
+    public void testAod_usesDebugValue() throws Exception {
+        mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+        mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+
+        Intent intent = new Intent(DozeScreenBrightness.ACTION_AOD_BRIGHTNESS);
+        intent.putExtra(DozeScreenBrightness.BRIGHTNESS_BUCKET, 1);
+        mScreen.onReceive(mContext, intent);
+        mSensor.sendSensorEvent(3);
+
+        assertEquals(1, mServiceFake.screenBrightness);
+    }
+
+    @Test
     public void testAod_usesLightSensorRespectingUserSetting() throws Exception {
         int maxBrightness = 3;
         Settings.System.putIntForUser(mContext.getContentResolver(),
@@ -160,7 +175,8 @@
     public void testNullSensor() throws Exception {
         mScreen = new DozeScreenBrightness(mContext, mServiceFake, mSensorManager,
                 null /* sensor */, mHostFake, null /* handler */,
-                DEFAULT_BRIGHTNESS, SENSOR_TO_BRIGHTNESS, SENSOR_TO_OPACITY);
+                DEFAULT_BRIGHTNESS, SENSOR_TO_BRIGHTNESS, SENSOR_TO_OPACITY,
+                true /* debuggable */);
 
         mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
         mScreen.transitionTo(INITIALIZED, DOZE_AOD);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java
index f8aa28d..199c4c2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java
@@ -40,9 +40,9 @@
 import android.support.test.runner.AndroidJUnit4;
 
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 
+import com.android.systemui.shared.system.TaskStackChangeListener;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -65,7 +65,7 @@
     private @Mock IActivityTaskManager mIActivityTaskManager;
 
     private WorkLockActivityController mController;
-    private SysUiTaskStackChangeListener mTaskStackListener;
+    private TaskStackChangeListener mTaskStackListener;
 
     @Before
     public void setUp() throws Exception {
@@ -75,8 +75,8 @@
         doReturn("com.example.test").when(mContext).getPackageName();
 
         // Construct controller. Save the TaskStackListener for injecting events.
-        final ArgumentCaptor<SysUiTaskStackChangeListener> listenerCaptor =
-                ArgumentCaptor.forClass(SysUiTaskStackChangeListener.class);
+        final ArgumentCaptor<TaskStackChangeListener> listenerCaptor =
+                ArgumentCaptor.forClass(TaskStackChangeListener.class);
         mController = new WorkLockActivityController(mContext, mActivityManager,
                 mIActivityTaskManager);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java
index 85cdfcc..12a122a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java
@@ -14,8 +14,12 @@
 
 package com.android.systemui.qs;
 
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -23,15 +27,21 @@
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.plugins.qs.QSTileView;
 import com.android.systemui.qs.customize.QSCustomizer;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 
 import java.util.Collections;
 
@@ -41,19 +51,37 @@
 public class QSPanelTest extends SysuiTestCase {
 
     private MetricsLogger mMetricsLogger;
+    private TestableLooper mTestableLooper;
     private QSPanel mQsPanel;
+    @Mock
     private QSTileHost mHost;
+    @Mock
     private QSCustomizer mCustomizer;
+    @Mock
+    private QSTile dndTile;
+    private ViewGroup mParentView;
+    @Mock
+    private QSDetail.Callback mCallback;
 
     @Before
     public void setup() throws Exception {
-        TestableLooper.get(this).runWithLooper(() -> {
+        MockitoAnnotations.initMocks(this);
+
+        mTestableLooper = TestableLooper.get(this);
+        mTestableLooper.runWithLooper(() -> {
             mMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class);
             mQsPanel = new QSPanel(mContext, null);
-            mHost = mock(QSTileHost.class);
+            // Provides a parent with non-zero size for QSPanel
+            mParentView = new FrameLayout(mContext);
+            mParentView.addView(mQsPanel);
+
+            when(dndTile.getTileSpec()).thenReturn("dnd");
             when(mHost.getTiles()).thenReturn(Collections.emptyList());
-            mCustomizer = mock(QSCustomizer.class);
+            when(mHost.createTileView(any(), anyBoolean())).thenReturn(mock(QSTileView.class));
+
             mQsPanel.setHost(mHost, mCustomizer);
+            mQsPanel.addTile(dndTile, true);
+            mQsPanel.setCallback(mCallback);
         });
     }
 
@@ -64,4 +92,31 @@
         mQsPanel.setExpanded(false);
         verify(mMetricsLogger).visibility(eq(MetricsEvent.QS_PANEL), eq(false));
     }
+
+    @Test
+    public void testOpenDetailsWithExistingTile_NoException() {
+        mTestableLooper.processAllMessages();
+        mQsPanel.openDetails("dnd");
+        mTestableLooper.processAllMessages();
+
+        verify(mCallback).onShowingDetail(any(), anyInt(), anyInt());
+    }
+
+/*    @Test
+    public void testOpenDetailsWithNullParameter_NoException() {
+        mTestableLooper.processAllMessages();
+        mQsPanel.openDetails(null);
+        mTestableLooper.processAllMessages();
+
+        verify(mCallback, never()).onShowingDetail(any(), anyInt(), anyInt());
+    }*/
+
+    @Test
+    public void testOpenDetailsWithNonExistingTile_NoException() {
+        mTestableLooper.processAllMessages();
+        mQsPanel.openDetails("invalid-name");
+        mTestableLooper.processAllMessages();
+
+        verify(mCallback, never()).onShowingDetail(any(), anyInt(), anyInt());
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginInstanceManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceManagerTest.java
similarity index 97%
rename from packages/SystemUI/tests/src/com/android/systemui/plugins/PluginInstanceManagerTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceManagerTest.java
index 19974f8..6d1ff8c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginInstanceManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceManagerTest.java
@@ -12,7 +12,7 @@
  * permissions and limitations under the License.
  */
 
-package com.android.systemui.plugins;
+package com.android.systemui.shared.plugins;
 
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertNotNull;
@@ -27,8 +27,10 @@
 
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.PluginInstanceManager.PluginInfo;
-import com.android.systemui.plugins.VersionInfo.InvalidVersionException;
+import com.android.systemui.plugins.Plugin;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.shared.plugins.PluginInstanceManager.PluginInfo;
+import com.android.systemui.shared.plugins.VersionInfo.InvalidVersionException;
 import com.android.systemui.plugins.annotations.Requires;
 
 import org.junit.After;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginManagerTest.java
similarity index 87%
rename from packages/SystemUI/tests/src/com/android/systemui/plugins/PluginManagerTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginManagerTest.java
index 438f9e4..3c70205 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginManagerTest.java
@@ -11,7 +11,7 @@
  * KIND, either express or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
-package com.android.systemui.plugins;
+package com.android.systemui.shared.plugins;
 
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
@@ -27,6 +27,7 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.net.Uri;
+import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -35,9 +36,12 @@
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.systemui.Dependency;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.PluginInstanceManager.PluginInfo;
-import com.android.systemui.plugins.PluginManagerImpl.PluginInstanceManagerFactory;
+import com.android.systemui.plugins.Plugin;
+import com.android.systemui.plugins.PluginInitializerImpl;
+import com.android.systemui.plugins.PluginListener;
 import com.android.systemui.plugins.annotations.ProvidesInterface;
+import com.android.systemui.shared.plugins.PluginInstanceManager.PluginInfo;
+import com.android.systemui.shared.plugins.PluginManagerImpl.PluginInstanceManagerFactory;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -74,8 +78,14 @@
         when(mMockFactory.createPluginInstanceManager(Mockito.any(), Mockito.any(), Mockito.any(),
                 Mockito.anyBoolean(), Mockito.any(), Mockito.any(), Mockito.any()))
                 .thenReturn(mMockPluginInstance);
-        mPluginManager = new PluginManagerImpl(getContext(), mMockFactory, true, new String[0],
-                mMockExceptionHandler);
+
+        mPluginManager = new PluginManagerImpl(getContext(), mMockFactory, true,
+                mMockExceptionHandler, new PluginInitializerImpl() {
+            @Override
+            public String[] getWhitelistedPlugins(Context context) {
+                return new String[0];
+            }
+        });
         resetExceptionHandler();
         mMockListener = mock(PluginListener.class);
     }
@@ -109,7 +119,12 @@
     @RunWithLooper(setAsMainLooper = true)
     public void testNonDebuggable_noWhitelist() {
         mPluginManager = new PluginManagerImpl(getContext(), mMockFactory, false,
-                new String[0], mMockExceptionHandler);
+                mMockExceptionHandler, new PluginInitializerImpl() {
+            @Override
+            public String[] getWhitelistedPlugins(Context context) {
+                return new String[0];
+            }
+        });
         resetExceptionHandler();
 
         mPluginManager.addPluginListener("myAction", mMockListener, TestPlugin.class);
@@ -121,7 +136,12 @@
     @RunWithLooper(setAsMainLooper = true)
     public void testNonDebuggable_whitelistedPkg() {
         mPluginManager = new PluginManagerImpl(getContext(), mMockFactory, false,
-                new String[] {WHITELISTED_PACKAGE}, mMockExceptionHandler);
+                mMockExceptionHandler, new PluginInitializerImpl() {
+            @Override
+            public String[] getWhitelistedPlugins(Context context) {
+                return new String[] {WHITELISTED_PACKAGE};
+            }
+        });
         resetExceptionHandler();
 
         mPluginManager.addPluginListener("myAction", mMockListener, TestPlugin.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/plugins/VersionInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/VersionInfoTest.java
similarity index 94%
rename from packages/SystemUI/tests/src/com/android/systemui/plugins/VersionInfoTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/shared/plugins/VersionInfoTest.java
index 0b4d9b5..9bad78d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/plugins/VersionInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/VersionInfoTest.java
@@ -12,7 +12,7 @@
  * permissions and limitations under the License.
  */
 
-package com.android.systemui.plugins;
+package com.android.systemui.shared.plugins;
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
@@ -20,7 +20,8 @@
 import android.support.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.VersionInfo.InvalidVersionException;
+import com.android.systemui.plugins.OverlayPlugin;
+import com.android.systemui.shared.plugins.VersionInfo.InvalidVersionException;
 import com.android.systemui.plugins.annotations.Requires;
 import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.plugins.qs.DetailAdapter;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
index 09c1931..da59450 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
@@ -79,13 +79,14 @@
                 Dependency.get(NotificationLockscreenUserManager.class);
         NotificationViewHierarchyManager viewHierarchyManager =
                 Dependency.get(NotificationViewHierarchyManager.class);
+        NotificationGroupManager groupManager = Dependency.get(NotificationGroupManager.class);
 
         when(mPresenter.getNotificationLockscreenUserManager()).thenReturn(lockscreenUserManager);
-        when(mPresenter.getGroupManager()).thenReturn(
-                Dependency.get(NotificationGroupManager.class));
+        when(mPresenter.getGroupManager()).thenReturn(groupManager);
 
         entryManager.setUpWithPresenter(mPresenter, mListContainer, mEntryManagerCallback,
                 mHeadsUpManager);
+        groupManager.setHeadsUpManager(mHeadsUpManager);
         gutsManager.setUpWithPresenter(mPresenter, mListContainer, mCheckSaveListener,
                 mOnClickListener);
         notificationLogger.setUpWithEntryManager(entryManager, mListContainer);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
index a7758a6..515c109 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
@@ -40,8 +40,11 @@
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 
+import android.util.Log;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 
 import com.google.android.collect.Lists;
@@ -61,7 +64,9 @@
 
     // Dependency mocks:
     @Mock private NotificationEntryManager mEntryManager;
+    @Mock private NotificationData mNotificationData;
     @Mock private DeviceProvisionedController mDeviceProvisionedController;
+    @Mock private StatusBarKeyguardViewManager mKeyguardViewManager;
 
     private int mCurrentUserId;
     private TestNotificationLockscreenUserManager mLockscreenUserManager;
@@ -79,9 +84,11 @@
         when(mUserManager.getProfiles(mCurrentUserId)).thenReturn(Lists.newArrayList(
                 new UserInfo(mCurrentUserId, "", 0), new UserInfo(mCurrentUserId + 1, "", 0)));
         when(mPresenter.getHandler()).thenReturn(Handler.createAsync(Looper.myLooper()));
+        when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);
 
         mLockscreenUserManager = new TestNotificationLockscreenUserManager(mContext);
         mLockscreenUserManager.setUpWithPresenter(mPresenter, mEntryManager);
+        mLockscreenUserManager.setKeyguardViewManager(mKeyguardViewManager);
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java
new file mode 100644
index 0000000..435ede4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyObject;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.ActivityManager;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.testing.TestableLooper.RunWithLooper;
+import android.view.RemoteAnimationAdapter;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.NotificationTestHelper;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.statusbar.phone.NotificationPanelView;
+import com.android.systemui.statusbar.phone.StatusBarWindowView;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.stubbing.Answer;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class ActivityLaunchAnimatorTest extends SysuiTestCase {
+
+    private ActivityLaunchAnimator mLaunchAnimator;
+    private ActivityLaunchAnimator.Callback mCallback = mock(ActivityLaunchAnimator.Callback.class);
+    private StatusBarWindowView mStatusBarWindowView = mock(StatusBarWindowView.class);
+    private NotificationListContainer mNotificationContainer
+            = mock(NotificationListContainer.class);
+    private ExpandableNotificationRow mRow = mock(ExpandableNotificationRow.class);
+
+    @Before
+    public void setUp() throws Exception {
+        when(mCallback.areLaunchAnimationsEnabled()).thenReturn(true);
+        mLaunchAnimator = new ActivityLaunchAnimator(
+                mStatusBarWindowView,
+                mCallback,
+                mock(NotificationPanelView.class),
+                mNotificationContainer);
+
+    }
+
+    @Test
+    public void testReturnsNullIfNotEnabled() {
+        when(mCallback.areLaunchAnimationsEnabled()).thenReturn(false);
+        RemoteAnimationAdapter launchAnimation = mLaunchAnimator.getLaunchAnimation(mRow,
+                false /* occluded */);
+        Assert.assertTrue("The LaunchAnimator generated an animation even though animations are "
+                        + "disabled", launchAnimation == null);
+    }
+
+    @Test
+    public void testNotWorkingWhenOccluded() {
+        when(mCallback.areLaunchAnimationsEnabled()).thenReturn(false);
+        RemoteAnimationAdapter launchAnimation = mLaunchAnimator.getLaunchAnimation(mRow,
+                true /* occluded */);
+        Assert.assertTrue("The LaunchAnimator generated an animation even though we're occluded",
+                launchAnimation == null);
+    }
+
+    @Test
+    public void testTimeoutCalled() {
+        RemoteAnimationAdapter launchAnimation = mLaunchAnimator.getLaunchAnimation(mRow,
+                false /* occluded */);
+        Assert.assertTrue("No animation generated", launchAnimation != null);
+        executePostsImmediately(mStatusBarWindowView);
+        mLaunchAnimator.setLaunchResult(ActivityManager.START_SUCCESS,
+                true /* wasIntentActivity */);
+        verify(mCallback).onExpandAnimationTimedOut();
+    }
+
+    private void executePostsImmediately(View view) {
+        doAnswer((i) -> {
+            Runnable run = i.getArgument(0);
+            run.run();
+            return null;
+        }).when(view).post(any());
+        doAnswer((i) -> {
+            Runnable run = i.getArgument(0);
+            run.run();
+            return null;
+        }).when(view).postDelayed(any(), anyLong());
+    }
+}
+
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 c236fbe..ca968a8 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
@@ -158,6 +158,11 @@
         PollingCheck.waitFor(1000,
                 () -> VISIBLE == mNotificationInfo.findViewById(R.id.confirmation).getVisibility());
     }
+    private void ensureNoUndoButton() {
+        PollingCheck.waitFor(1000,
+                () -> GONE == mNotificationInfo.findViewById(R.id.confirmation).getVisibility()
+                        && !mNotificationInfo.isAnimating());
+    }
     private void waitForStopButton() {
         PollingCheck.waitFor(1000,
                 () -> VISIBLE == mNotificationInfo.findViewById(R.id.prompt).getVisibility());
@@ -583,9 +588,6 @@
                 true /* isUserSentimentNegative */);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
-        waitForUndoButton();
-        mNotificationInfo.handleCloseControls(true /* save */, false /* force */);
-
         mTestableLooper.processAllMessages();
         verify(listener).checkSave(any(Runnable.class), eq(mSbn));
     }
@@ -805,7 +807,7 @@
     }
 
     @Test
-    public void testCloseControlsDoesNotUpdateIfCheckSaveListenerIsNoOp() throws Exception {
+    public void testBlockDoesNothingIfCheckSaveListenerIsNoOp() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
@@ -813,10 +815,10 @@
                 }, null, null, true, true);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
-        waitForUndoButton();
+        mTestableLooper.processAllMessages();
+        ensureNoUndoButton();
         mNotificationInfo.handleCloseControls(true, false);
 
-        mTestableLooper.processAllMessages();
         verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
                 eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(mNotificationChannel));
     }
@@ -831,6 +833,10 @@
                 }, null, null, true, false);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
+        mTestableLooper.processAllMessages();
+        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+                eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(mNotificationChannel));
+
         waitForUndoButton();
         mNotificationInfo.handleCloseControls(true, false);
 
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 1e3d42b..b545e61 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
@@ -32,6 +32,7 @@
 import android.os.IPowerManager;
 import android.os.Looper;
 import android.os.PowerManager;
+import android.service.dreams.IDreamManager;
 import android.support.test.annotation.UiThreadTest;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -39,7 +40,6 @@
 import com.android.systemui.ExpandHelper;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.statusbar.EmptyShadeView;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.NotificationPresenter;
@@ -91,7 +91,7 @@
     @Mock private NotificationData mNotificationData;
     @Mock private NotificationRemoteInputManager mRemoteInputManager;
     @Mock private RemoteInputController mRemoteInputController;
-    @Mock private SystemServicesProxy mSystemServicesProxy;
+    @Mock private IDreamManager mDreamManager;
     private PowerManager mPowerManager;
     private TestableNotificationEntryManager mEntryManager;
 
@@ -111,7 +111,7 @@
         mPowerManager = new PowerManager(mContext, powerManagerService,
                 Handler.createAsync(Looper.myLooper()));
 
-        mEntryManager = new TestableNotificationEntryManager(mSystemServicesProxy, mPowerManager,
+        mEntryManager = new TestableNotificationEntryManager(mDreamManager, mPowerManager,
                 mContext);
         mEntryManager.setUpForTest(mock(NotificationPresenter.class), null, null, mHeadsUpManager,
                 mNotificationData);
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
new file mode 100644
index 0000000..b5f67c0
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
@@ -0,0 +1,511 @@
+/*
+ * 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 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;
+import static org.mockito.Mockito.when;
+
+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.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.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
+@RunWith(AndroidJUnit4.class)
+public class NotificationSwipeHelperTest extends SysuiTestCase {
+
+    private NotificationSwipeHelper mSwipeHelper;
+    private NotificationSwipeHelper.NotificationCallback mCallback;
+    private NotificationMenuRowPlugin.OnMenuEventListener mListener;
+    private View mView;
+    private MotionEvent mEvent;
+    private NotificationMenuRowPlugin mMenuRow;
+    private Handler mHandler;
+    private ExpandableNotificationRow mNotificationRow;
+    private Runnable mFalsingCheck;
+
+    @Rule public MockitoRule mockito = MockitoJUnit.rule();
+
+    @Before
+    @UiThreadTest
+    public void setUp() throws Exception {
+        mCallback = mock(NotificationSwipeHelper.NotificationCallback.class);
+        mListener = mock(NotificationMenuRowPlugin.OnMenuEventListener.class);
+        mSwipeHelper = spy(new NotificationSwipeHelper(SwipeHelper.X, mCallback, mContext, mListener));
+        mView = mock(View.class);
+        mEvent = mock(MotionEvent.class);
+        mMenuRow = mock(NotificationMenuRowPlugin.class);
+        mNotificationRow = mock(ExpandableNotificationRow.class);
+        mHandler = mock(Handler.class);
+        mFalsingCheck = mock(Runnable.class);
+    }
+
+    @Test
+    public void testSetExposedMenuView() {
+        assertEquals("intialized with null exposed menu view", null,
+                mSwipeHelper.getExposedMenuView());
+        mSwipeHelper.setExposedMenuView(mView);
+        assertEquals("swipe helper has correct exposedMenuView after setExposedMenuView to a view",
+                mView, mSwipeHelper.getExposedMenuView());
+        mSwipeHelper.setExposedMenuView(null);
+        assertEquals("swipe helper has null exposedMenuView after setExposedMenuView to null",
+                null, mSwipeHelper.getExposedMenuView());
+    }
+
+    @Test
+    public void testClearExposedMenuView() {
+        doNothing().when(mSwipeHelper).setExposedMenuView(mView);
+        mSwipeHelper.clearExposedMenuView();
+        verify(mSwipeHelper, times(1)).setExposedMenuView(null);
+    }
+
+    @Test
+    public void testGetTranslatingParentView() {
+        assertEquals("intialized with null translating parent view", null,
+                mSwipeHelper.getTranslatingParentView());
+        mSwipeHelper.setTranslatingParentView(mView);
+        assertEquals("has translating parent view after setTranslatingParentView with a view",
+                mView, mSwipeHelper.getTranslatingParentView());
+    }
+
+    @Test
+    public void testClearTranslatingParentView() {
+        doNothing().when(mSwipeHelper).setTranslatingParentView(null);
+        mSwipeHelper.clearTranslatingParentView();
+        verify(mSwipeHelper, times(1)).setTranslatingParentView(null);
+    }
+
+    @Test
+    public void testSetCurrentMenuRow() {
+        assertEquals("currentMenuRow initializes to null", null,
+                mSwipeHelper.getCurrentMenuRow());
+        mSwipeHelper.setCurrentMenuRow(mMenuRow);
+        assertEquals("currentMenuRow set correctly after setCurrentMenuRow", mMenuRow,
+                mSwipeHelper.getCurrentMenuRow());
+        mSwipeHelper.setCurrentMenuRow(null);
+        assertEquals("currentMenuRow set to null after setCurrentMenuRow to null",
+                null, mSwipeHelper.getCurrentMenuRow());
+    }
+
+    @Test
+    public void testClearCurrentMenuRow() {
+        doNothing().when(mSwipeHelper).setCurrentMenuRow(null);
+        mSwipeHelper.clearCurrentMenuRow();
+        verify(mSwipeHelper, times(1)).setCurrentMenuRow(null);
+    }
+
+    @Test
+    public void testOnDownUpdate_ExpandableNotificationRow() {
+        when(mSwipeHelper.getHandler()).thenReturn(mHandler);
+        when(mSwipeHelper.getFalsingCheck()).thenReturn(mFalsingCheck);
+        doNothing().when(mSwipeHelper).resetExposedMenuView(true, false);
+        doNothing().when(mSwipeHelper).clearCurrentMenuRow();
+        doNothing().when(mSwipeHelper).initializeRow(any());
+
+        mSwipeHelper.onDownUpdate(mNotificationRow, mEvent);
+
+        verify(mSwipeHelper, times(1)).clearCurrentMenuRow();
+        verify(mHandler, times(1)).removeCallbacks(mFalsingCheck);
+        verify(mSwipeHelper, times(1)).resetExposedMenuView(true, false);
+        verify(mSwipeHelper, times(1)).initializeRow(mNotificationRow);
+    }
+
+    @Test
+    public void testOnDownUpdate_notExpandableNotificationRow() {
+        when(mSwipeHelper.getHandler()).thenReturn(mHandler);
+        when(mSwipeHelper.getFalsingCheck()).thenReturn(mFalsingCheck);
+        doNothing().when(mSwipeHelper).resetExposedMenuView(true, false);
+        doNothing().when(mSwipeHelper).clearCurrentMenuRow();
+        doNothing().when(mSwipeHelper).initializeRow(any());
+
+        mSwipeHelper.onDownUpdate(mView, mEvent);
+
+        verify(mSwipeHelper, times(1)).clearCurrentMenuRow();
+        verify(mHandler, times(1)).removeCallbacks(mFalsingCheck);
+        verify(mSwipeHelper, times(1)).resetExposedMenuView(true, false);
+        verify(mSwipeHelper, times(0)).initializeRow(any());
+    }
+
+    @Test
+    public void testOnMoveUpdate_menuRow() {
+        when(mSwipeHelper.getCurrentMenuRow()).thenReturn(mMenuRow);
+        when(mSwipeHelper.getHandler()).thenReturn(mHandler);
+        when(mSwipeHelper.getFalsingCheck()).thenReturn(mFalsingCheck);
+
+        mSwipeHelper.onMoveUpdate(mView, mEvent, 0, 10);
+
+        verify(mHandler, times(1)).removeCallbacks(mFalsingCheck);
+        verify(mMenuRow, times(1)).onTouchMove(10);
+    }
+
+    @Test
+    public void testOnMoveUpdate_noMenuRow() {
+        when(mSwipeHelper.getHandler()).thenReturn(mHandler);
+        when(mSwipeHelper.getFalsingCheck()).thenReturn(mFalsingCheck);
+
+        mSwipeHelper.onMoveUpdate(mView, mEvent, 0, 10);
+
+        verify(mHandler, times(1)).removeCallbacks(mFalsingCheck);
+    }
+
+    @Test
+    public void testHandleUpEvent_noMenuRow() {
+        assertFalse("Menu row does not exist",
+                mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
+    }
+
+    @Test
+    public void testHandleUpEvent_menuRow() {
+        when(mSwipeHelper.getCurrentMenuRow()).thenReturn(mMenuRow);
+        doNothing().when(mSwipeHelper).handleMenuRowSwipe(mEvent, mView, 0, mMenuRow);
+
+        assertTrue("Menu row exists",
+                mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
+        verify(mMenuRow, times(1)).onTouchEnd();
+        verify(mSwipeHelper, times(1)).handleMenuRowSwipe(mEvent, mView, 0, mMenuRow);
+    }
+
+    @Test
+    public void testDismissChild_notExpanded() {
+        when(mCallback.isExpanded()).thenReturn(false);
+        doNothing().when(mSwipeHelper).superDismissChild(mView, 0, false);
+        doNothing().when(mSwipeHelper).handleMenuCoveredOrDismissed();
+
+        mSwipeHelper.dismissChild(mView, 0, false);
+
+        verify(mSwipeHelper, times(1)).superDismissChild(mView, 0, false);
+        verify(mCallback, times(0)).handleChildViewDismissed(mView);
+        verify(mCallback, times(1)).onDismiss();
+        verify(mSwipeHelper, times(1)).handleMenuCoveredOrDismissed();
+    }
+
+    @Test
+    public void testSnapchild_targetIsZero() {
+        doNothing().when(mSwipeHelper).superSnapChild(mView, 0, 0);
+        mSwipeHelper.snapChild(mView, 0, 0);
+
+        verify(mCallback, times(1)).onDragCancelled(mView);
+        verify(mSwipeHelper, times(1)).superSnapChild(mView, 0, 0);
+        verify(mSwipeHelper, times(1)).handleMenuCoveredOrDismissed();
+    }
+
+
+    @Test
+    public void testSnapchild_targetNotZero() {
+        doNothing().when(mSwipeHelper).superSnapChild(mView, 10, 0);
+        mSwipeHelper.snapChild(mView, 10, 0);
+
+        verify(mCallback, times(1)).onDragCancelled(mView);
+        verify(mSwipeHelper, times(1)).superSnapChild(mView, 10, 0);
+        verify(mSwipeHelper, times(0)).handleMenuCoveredOrDismissed();
+    }
+
+    @Test
+    public void testSnooze() {
+        StatusBarNotification sbn = mock(StatusBarNotification.class);
+        SnoozeOption snoozeOption = mock(SnoozeOption.class);
+        mSwipeHelper.snooze(sbn, snoozeOption);
+        verify(mCallback, times(1)).onSnooze(sbn, snoozeOption);
+    }
+
+    @Test
+    public void testGetViewTranslationAnimator_notExpandableNotificationRow() {
+        Animator animator = mock(Animator.class);
+        AnimatorUpdateListener listener = mock(AnimatorUpdateListener.class);
+        doReturn(animator).when(mSwipeHelper).superGetViewTranslationAnimator(mView, 0, listener);
+
+        assertEquals("returns the correct animator from super", animator,
+                mSwipeHelper.getViewTranslationAnimator(mView, 0, listener));
+
+        verify(mSwipeHelper, times(1)).superGetViewTranslationAnimator(mView, 0, listener);
+    }
+
+    @Test
+    public void testGetViewTranslationAnimator_expandableNotificationRow() {
+        Animator animator = mock(Animator.class);
+        AnimatorUpdateListener listener = mock(AnimatorUpdateListener.class);
+        doReturn(animator).when(mNotificationRow).getTranslateViewAnimator(0, listener);
+
+        assertEquals("returns the correct animator from super when view is an ENR", animator,
+                mSwipeHelper.getViewTranslationAnimator(mNotificationRow, 0, listener));
+
+        verify(mNotificationRow, times(1)).getTranslateViewAnimator(0, listener);
+    }
+
+    @Test
+    public void testSetTranslation() {
+        mSwipeHelper.setTranslation(mNotificationRow, 0);
+        verify(mNotificationRow, times(1)).setTranslation(0);
+    }
+
+    @Test
+    public void testGetTranslation() {
+        doReturn(30f).when(mNotificationRow).getTranslation();
+
+        assertEquals("Returns getTranslation for the ENR",
+                mSwipeHelper.getTranslation(mNotificationRow), 30f);
+
+        verify(mNotificationRow, times(1)).getTranslation();
+    }
+
+    @Test
+    public void testDismiss() {
+        doNothing().when(mSwipeHelper).dismissChild(mView, 0, true);
+        doReturn(false).when(mSwipeHelper).swipedFastEnough();
+
+        mSwipeHelper.dismiss(mView, 0);
+
+        verify(mSwipeHelper, times(1)).swipedFastEnough();
+        verify(mSwipeHelper, times(1)).dismissChild(mView, 0, true);
+    }
+
+    @Test
+    public void testSnapOpen() {
+        doNothing().when(mSwipeHelper).snapChild(mView, 30, 0);
+
+        mSwipeHelper.snapOpen(mView, 30, 0);
+
+        verify(mSwipeHelper, times(1)).snapChild(mView, 30, 0);
+    }
+
+    @Test
+    public void testSnapClosed() {
+        doNothing().when(mSwipeHelper).snapChild(mView, 0, 0);
+
+        mSwipeHelper.snapClosed(mView, 0);
+
+        verify(mSwipeHelper, times(1)).snapChild(mView, 0, 0);
+    }
+
+    @Test
+    public void testGetMinDismissVelocity() {
+        doReturn(30f).when(mSwipeHelper).getEscapeVelocity();
+
+        assertEquals("Returns getEscapeVelocity", 30f, mSwipeHelper.getMinDismissVelocity());
+    }
+
+    @Test
+    public void onMenuShown_noAntiFalsing() {
+        doNothing().when(mSwipeHelper).setExposedMenuView(mView);
+        doReturn(mView).when(mSwipeHelper).getTranslatingParentView();
+        doReturn(mHandler).when(mSwipeHelper).getHandler();
+        doReturn(false).when(mCallback).isAntiFalsingNeeded();
+        doReturn(mFalsingCheck).when(mSwipeHelper).getFalsingCheck();
+
+        mSwipeHelper.onMenuShown(mView);
+
+        verify(mSwipeHelper, times(1)).setExposedMenuView(mView);
+        verify(mCallback, times(1)).onDragCancelled(mView);
+        verify(mCallback, times(1)).isAntiFalsingNeeded();
+
+        verify(mHandler, times(0)).removeCallbacks(mFalsingCheck);
+        verify(mHandler, times(0)).postDelayed(mFalsingCheck, mSwipeHelper.COVER_MENU_DELAY);
+    }
+
+    @Test
+    public void onMenuShown_antiFalsing() {
+        doNothing().when(mSwipeHelper).setExposedMenuView(mView);
+        doReturn(mView).when(mSwipeHelper).getTranslatingParentView();
+        doReturn(mHandler).when(mSwipeHelper).getHandler();
+        doReturn(true).when(mCallback).isAntiFalsingNeeded();
+        doReturn(mFalsingCheck).when(mSwipeHelper).getFalsingCheck();
+
+        mSwipeHelper.onMenuShown(mView);
+
+        verify(mSwipeHelper, times(1)).setExposedMenuView(mView);
+        verify(mCallback, times(1)).onDragCancelled(mView);
+        verify(mCallback, times(1)).isAntiFalsingNeeded();
+
+        verify(mHandler, times(1)).removeCallbacks(mFalsingCheck);
+        verify(mHandler, times(1)).postDelayed(mFalsingCheck, mSwipeHelper.COVER_MENU_DELAY);
+    }
+
+    @Test
+    public void testResetExposedMenuView_noReset() {
+        doReturn(false).when(mSwipeHelper).shouldResetMenu(false);
+        doNothing().when(mSwipeHelper).clearExposedMenuView();
+
+        mSwipeHelper.resetExposedMenuView(false, false);
+
+        verify(mSwipeHelper, times(1)).shouldResetMenu(false);
+
+        // should not clear exposed menu row
+        verify(mSwipeHelper, times(0)).clearExposedMenuView();
+    }
+
+    @Test
+    public void testResetExposedMenuView_animate() {
+        Animator animator = mock(Animator.class);
+
+        doReturn(true).when(mSwipeHelper).shouldResetMenu(false);
+        doReturn(mNotificationRow).when(mSwipeHelper).getExposedMenuView();
+        doReturn(false).when(mNotificationRow).isRemoved();
+        doReturn(animator).when(mSwipeHelper).getViewTranslationAnimator(mNotificationRow, 0, null);
+        doNothing().when(mSwipeHelper).clearExposedMenuView();
+
+        mSwipeHelper.resetExposedMenuView(true, false);
+
+        verify(mSwipeHelper, times(1)).shouldResetMenu(false);
+
+        // should retrieve and start animator
+        verify(mSwipeHelper, times(1)).getViewTranslationAnimator(mNotificationRow, 0, null);
+        verify(animator, times(1)).start();
+
+        // should not reset translation on row directly
+        verify(mNotificationRow, times(0)).resetTranslation();
+
+        // should clear exposed menu row
+        verify(mSwipeHelper, times(1)).clearExposedMenuView();
+    }
+
+
+    @Test
+    public void testResetExposedMenuView_noAnimate() {
+        Animator animator = mock(Animator.class);
+
+        doReturn(true).when(mSwipeHelper).shouldResetMenu(false);
+        doReturn(mNotificationRow).when(mSwipeHelper).getExposedMenuView();
+        doReturn(false).when(mNotificationRow).isRemoved();
+        doReturn(animator).when(mSwipeHelper).getViewTranslationAnimator(mNotificationRow, 0, null);
+        doNothing().when(mSwipeHelper).clearExposedMenuView();
+
+        mSwipeHelper.resetExposedMenuView(false, false);
+
+        verify(mSwipeHelper, times(1)).shouldResetMenu(false);
+
+        // should not retrieve and start animator
+        verify(mSwipeHelper, times(0)).getViewTranslationAnimator(mNotificationRow, 0, null);
+        verify(animator, times(0)).start();
+
+        // should reset translation on row directly
+        verify(mNotificationRow, times(1)).resetTranslation();
+
+        // should clear exposed menu row
+        verify(mSwipeHelper, times(1)).clearExposedMenuView();
+    }
+
+    @Test
+    public void testIsTouchInView() {
+        assertEquals("returns false when view is null", false,
+                NotificationSwipeHelper.isTouchInView(mEvent, null));
+
+        doReturn(5f).when(mEvent).getRawX();
+        doReturn(10f).when(mEvent).getRawY();
+
+        doReturn(20).when(mView).getWidth();
+        doReturn(20).when(mView).getHeight();
+
+        Answer answer = (Answer) invocation -> {
+            int[] arr = invocation.getArgument(0);
+            arr[0] = 0;
+            arr[1] = 0;
+            return null;
+        };
+        doAnswer(answer).when(mView).getLocationOnScreen(any());
+
+        assertTrue("Touch is within the view",
+                mSwipeHelper.isTouchInView(mEvent, mView));
+
+        doReturn(50f).when(mEvent).getRawX();
+
+        assertFalse("Touch is not within the view",
+                mSwipeHelper.isTouchInView(mEvent, mView));
+    }
+
+    @Test
+    public void testIsTouchInView_expandable() {
+        assertEquals("returns false when view is null", false,
+                NotificationSwipeHelper.isTouchInView(mEvent, null));
+
+        doReturn(5f).when(mEvent).getRawX();
+        doReturn(10f).when(mEvent).getRawY();
+
+        doReturn(20).when(mNotificationRow).getWidth();
+        doReturn(20).when(mNotificationRow).getActualHeight();
+
+        Answer answer = (Answer) invocation -> {
+            int[] arr = invocation.getArgument(0);
+            arr[0] = 0;
+            arr[1] = 0;
+            return null;
+        };
+        doAnswer(answer).when(mNotificationRow).getLocationOnScreen(any());
+
+        assertTrue("Touch is within the view",
+                mSwipeHelper.isTouchInView(mEvent, mNotificationRow));
+
+        doReturn(50f).when(mEvent).getRawX();
+
+        assertFalse("Touch is not within the view",
+                mSwipeHelper.isTouchInView(mEvent, mNotificationRow));
+    }
+}
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 5006b0b..da93327 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
@@ -50,6 +50,7 @@
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.service.dreams.IDreamManager;
 import android.service.notification.StatusBarNotification;
 import android.support.test.filters.SmallTest;
 import android.support.test.metricshelper.MetricsAsserts;
@@ -119,9 +120,9 @@
     @Mock private KeyguardIndicationController mKeyguardIndicationController;
     @Mock private NotificationStackScrollLayout mStackScroller;
     @Mock private HeadsUpManagerPhone mHeadsUpManager;
-    @Mock private SystemServicesProxy mSystemServicesProxy;
     @Mock private NotificationPanelView mNotificationPanelView;
     @Mock private IStatusBarService mBarService;
+    @Mock private IDreamManager mDreamManager;
     @Mock private ScrimController mScrimController;
     @Mock private ArrayList<Entry> mNotificationList;
     @Mock private BiometricUnlockController mBiometricUnlockController;
@@ -194,8 +195,7 @@
             return null;
         }).when(mStatusBarKeyguardViewManager).addAfterKeyguardGoneRunnable(any());
 
-        mEntryManager = new TestableNotificationEntryManager(mSystemServicesProxy, mPowerManager,
-                mContext);
+        mEntryManager = new TestableNotificationEntryManager(mDreamManager, mPowerManager, mContext);
         when(mRemoteInputManager.getController()).thenReturn(mRemoteInputController);
         mStatusBar = new TestableStatusBar(mStatusBarKeyguardViewManager, mUnlockMethodCache,
                 mKeyguardIndicationController, mStackScroller, mHeadsUpManager,
@@ -358,12 +358,12 @@
     }
 
     @Test
-    public void testShouldHeadsUp_nonSuppressedGroupSummary() {
+    public void testShouldHeadsUp_nonSuppressedGroupSummary() throws Exception {
         when(mPowerManager.isScreenOn()).thenReturn(true);
         when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
         when(mNotificationData.shouldSuppressStatusBar(any())).thenReturn(false);
         when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
-        when(mSystemServicesProxy.isDreaming()).thenReturn(false);
+        when(mDreamManager.isDreaming()).thenReturn(false);
         when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
 
         Notification n = new Notification.Builder(getContext(), "a")
@@ -379,12 +379,12 @@
     }
 
     @Test
-    public void testShouldHeadsUp_suppressedGroupSummary() {
+    public void testShouldHeadsUp_suppressedGroupSummary() throws Exception {
         when(mPowerManager.isScreenOn()).thenReturn(true);
         when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
         when(mNotificationData.shouldSuppressStatusBar(any())).thenReturn(false);
         when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
-        when(mSystemServicesProxy.isDreaming()).thenReturn(false);
+        when(mDreamManager.isDreaming()).thenReturn(false);
         when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
 
         Notification n = new Notification.Builder(getContext(), "a")
@@ -400,11 +400,11 @@
     }
 
     @Test
-    public void testShouldHeadsUp_suppressedHeadsUp() {
+    public void testShouldHeadsUp_suppressedHeadsUp() throws Exception {
         when(mPowerManager.isScreenOn()).thenReturn(true);
         when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
         when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
-        when(mSystemServicesProxy.isDreaming()).thenReturn(false);
+        when(mDreamManager.isDreaming()).thenReturn(false);
         when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
 
         when(mNotificationData.shouldSuppressPeek(any())).thenReturn(true);
@@ -418,11 +418,11 @@
     }
 
     @Test
-    public void testShouldHeadsUp_noSuppressedHeadsUp() {
+    public void testShouldHeadsUp_noSuppressedHeadsUp() throws Exception {
         when(mPowerManager.isScreenOn()).thenReturn(true);
         when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
         when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
-        when(mSystemServicesProxy.isDreaming()).thenReturn(false);
+        when(mDreamManager.isDreaming()).thenReturn(false);
         when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
 
         when(mNotificationData.shouldSuppressPeek(any())).thenReturn(false);
@@ -690,10 +690,10 @@
 
     public static class TestableNotificationEntryManager extends NotificationEntryManager {
 
-        public TestableNotificationEntryManager(SystemServicesProxy systemServicesProxy,
+        public TestableNotificationEntryManager(IDreamManager dreamManager,
                 PowerManager powerManager, Context context) {
             super(context);
-            mSystemServicesProxy = systemServicesProxy;
+            mDreamManager = dreamManager;
             mPowerManager = powerManager;
         }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java
index b22a646..1cceefa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java
@@ -33,7 +33,7 @@
 import com.android.systemui.plugins.OverlayPlugin;
 import com.android.systemui.plugins.Plugin;
 import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
 import com.android.systemui.statusbar.policy.ExtensionController.Extension;
 import com.android.systemui.statusbar.policy.ExtensionController.TunerFactory;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakePluginManager.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakePluginManager.java
index 0a83a89..5f54bce 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakePluginManager.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakePluginManager.java
@@ -14,12 +14,11 @@
 
 package com.android.systemui.utils.leaks;
 
-import android.content.Context;
 import android.testing.LeakCheck;
 
 import com.android.systemui.plugins.Plugin;
 import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.shared.plugins.PluginManager;
 
 public class FakePluginManager implements PluginManager {
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/LeakCheckedTest.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/LeakCheckedTest.java
index ecda9620..f479126 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/LeakCheckedTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/LeakCheckedTest.java
@@ -20,7 +20,7 @@
 import android.util.ArrayMap;
 
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.statusbar.phone.ManagedProfileController;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.policy.BatteryController;
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index 41b3feb..5e87707 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -4026,6 +4026,8 @@
     // - AUTOFILL_DATASET_AUTHENTICATED
     // - AUTOFILL_INVALID_AUTHENTICATION
     // - AUTOFILL_INVALID_DATASET_AUTHENTICATION
+    // NOTE: starting on OS Q, it also added the following fields:
+    // Tag FIELD_AUTOFILL_TEXT_LEN: length of the error message provided by the service
     AUTOFILL_REQUEST = 907;
 
     // Tag of a field for a package of an autofill service
@@ -4102,6 +4104,8 @@
     // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
     // Tag FIELD_AUTOFILL_SESSION_ID: id of the autofill session associated with this metric.
     // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+    // NOTE: starting on OS Q, it also added the following fields:
+    // Tag FIELD_AUTOFILL_TEXT_LEN: length of the error message provided by the service
     AUTOFILL_DATA_SAVE_REQUEST = 918;
 
     // An auto-fill session was finished
@@ -5922,7 +5926,7 @@
     // Tag used to determine what type of charging was started/ended
     // 1 = Plugged AC
     // 2 = Plugged USB
-    // 3 = Wireless
+    // 4 = Wireless
     FIELD_PLUG_TYPE = 1421;
 
     // ACTION: USB-C Connector connected.
@@ -6443,7 +6447,7 @@
 
     // OPEN: Settings > System > Input & Gesture > Reach up gesture
     // OS: Q
-    SETTINGS_GESTURE_REACH = 1557;
+    SETTINGS_GESTURE_WAKE_LOCK_SCREEN = 1557;
 
     // OPEN: Emergency dialer opened
     // CLOSE: Emergency dialer closed
@@ -6517,6 +6521,34 @@
     // OS: Q
     MOBILE_NETWORK = 1571;
 
+    // Tag of a field for the length of a text
+    FIELD_AUTOFILL_TEXT_LEN = 1572;
+
+    // Action: the notification assistant is changing a notification
+    // OS: Q
+    NOTIFICATION_ASSISTANT_ADJUSTMENT = 1573;
+
+    // Subtype: The people attached to a notification was changed
+    ADJUSTMENT_KEY_PEOPLE = 1574;
+
+    // Subtype: The snooze options attached to a notification was changed
+    ADJUSTMENT_KEY_SNOOZE_CRITERIA = 1575;
+
+    // Subtype: The group of a notification was changed
+    ADJUSTMENT_KEY_GROUP_KEY = 1576;
+
+    // Subtype: The user sentiment of a notification was changed
+    ADJUSTMENT_KEY_USER_SENTIMENT = 1577;
+
+    // Subtype: New actions have been added to a notification
+    ADJUSTMENT_KEY_SMART_ACTIONS = 1578;
+
+    // Subtype: New smart replies have been added to a notification
+    ADJUSTMENT_KEY_SMART_REPLIES = 1579;
+
+    // Subtype: The importance of a notification has been changed
+    ADJUSTMENT_KEY_IMPORTANCE = 1580;
+
     // ---- End Q Constants, all Q constants go above this line ----
 
     // Add new aosp constants above this line.
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 8c8352f..78facf8 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -235,6 +235,13 @@
         }
     }
 
+    int getTargedSdkLocked() {
+        if (mInfo == null) {
+            return 0;
+        }
+        return mInfo.getServiceInfo().applicationInfo.targetSdkVersion;
+    }
+
     private boolean isSetupCompletedLocked() {
         final String setupComplete = Settings.Secure.getStringForUser(
                 mContext.getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, mUserId);
@@ -953,6 +960,7 @@
             pw.println();
             mInfo.dump(prefix2, pw);
             pw.print(prefix); pw.print("Service Label: "); pw.println(getServiceLabel());
+            pw.print(prefix); pw.print("Target SDK: "); pw.println(getTargedSdkLocked());
         }
         pw.print(prefix); pw.print("Component from settings: ");
             pw.println(getComponentNameFromSettings());
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
index 2671327..d1b09ca 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
@@ -29,6 +29,7 @@
 import android.content.Intent;
 import android.content.IntentSender;
 import android.content.ServiceConnection;
+import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.IBinder.DeathRecipient;
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index bf6964f..cf323fb 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -50,6 +50,7 @@
 import android.graphics.Rect;
 import android.metrics.LogMaker;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -63,6 +64,7 @@
 import android.service.autofill.Dataset;
 import android.service.autofill.FieldClassification;
 import android.service.autofill.FieldClassification.Match;
+import android.text.TextUtils;
 import android.service.autofill.FillContext;
 import android.service.autofill.FillRequest;
 import android.service.autofill.FillResponse;
@@ -744,12 +746,17 @@
 
     private void onFillRequestFailureOrTimeout(int requestId, boolean timedOut,
             @Nullable CharSequence message) {
+        boolean showMessage = !TextUtils.isEmpty(message);
         synchronized (mLock) {
             if (mDestroyed) {
                 Slog.w(TAG, "Call to Session#onFillRequestFailureOrTimeout(req=" + requestId
                         + ") rejected - session: " + id + " destroyed");
                 return;
             }
+            if (sDebug) {
+                Slog.d(TAG, "finishing session due to service "
+                        + (timedOut ? "timeout" : "failure"));
+            }
             mService.resetLastResponse();
             final LogMaker requestLog = mRequestLogs.get(requestId);
             if (requestLog == null) {
@@ -757,8 +764,21 @@
             } else {
                 requestLog.setType(timedOut ? MetricsEvent.TYPE_CLOSE : MetricsEvent.TYPE_FAILURE);
             }
+            if (showMessage) {
+                final int targetSdk = mService.getTargedSdkLocked();
+                if (targetSdk >= Build.VERSION_CODES.Q) {
+                    showMessage = false;
+                    Slog.w(TAG, "onFillRequestFailureOrTimeout(): not showing '" + message
+                            + "' because service's targetting API " + targetSdk);
+                }
+                if (message != null) {
+                    requestLog.addTaggedData(MetricsEvent.FIELD_AUTOFILL_TEXT_LEN,
+                            message.length());
+                }
+            }
         }
-        if (message != null) {
+        notifyUnavailableToClient(AutofillManager.STATE_UNKNOWN_FAILED);
+        if (showMessage) {
             getUiForShowing().showError(message, this);
         }
         removeSelf();
@@ -793,6 +813,7 @@
     @Override
     public void onSaveRequestFailure(@Nullable CharSequence message,
             @NonNull String servicePackageName) {
+        boolean showMessage = !TextUtils.isEmpty(message);
         synchronized (mLock) {
             mIsSaving = false;
 
@@ -801,12 +822,26 @@
                         + id + " destroyed");
                 return;
             }
+            if (showMessage) {
+                final int targetSdk = mService.getTargedSdkLocked();
+                if (targetSdk >= Build.VERSION_CODES.Q) {
+                    showMessage = false;
+                    Slog.w(TAG, "onSaveRequestFailure(): not showing '" + message
+                            + "' because service's targetting API " + targetSdk);
+                }
+            }
         }
-        LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_DATA_SAVE_REQUEST, servicePackageName)
+        final LogMaker log =
+                newLogMaker(MetricsEvent.AUTOFILL_DATA_SAVE_REQUEST, servicePackageName)
                 .setType(MetricsEvent.TYPE_FAILURE);
+        if (message != null) {
+            log.addTaggedData(MetricsEvent.FIELD_AUTOFILL_TEXT_LEN, message.length());
+        }
         mMetricsLogger.write(log);
 
-        getUiForShowing().showError(message, this);
+        if (showMessage) {
+            getUiForShowing().showError(message, this);
+        }
         removeSelf();
     }
 
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index 5962406..fe86ab3 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -43,6 +43,8 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.server.LocalServices;
+import com.android.server.UiModeManagerInternal;
 import com.android.server.UiThread;
 import com.android.server.autofill.Helper;
 
@@ -69,6 +71,7 @@
     private final MetricsLogger mMetricsLogger = new MetricsLogger();
 
     private final @NonNull OverlayControl mOverlayControl;
+    private final @NonNull UiModeManagerInternal mUiModeMgr;
 
     public interface AutoFillUiCallback {
         void authenticate(int requestId, int datasetIndex, @NonNull IntentSender intent,
@@ -86,6 +89,7 @@
     public AutoFillUI(@NonNull Context context) {
         mContext = context;
         mOverlayControl = new OverlayControl(context);
+        mUiModeMgr = LocalServices.getService(UiModeManagerInternal.class);
     }
 
     public void setCallback(@NonNull AutoFillUiCallback callback) {
@@ -193,7 +197,9 @@
             }
             hideAllUiThread(callback);
             mFillUi = new FillUi(mContext, response, focusedId,
-                    filterText, mOverlayControl, serviceLabel, serviceIcon, new FillUi.Callback() {
+                    filterText, mOverlayControl, serviceLabel, serviceIcon,
+                    mUiModeMgr.isNightMode(),
+                    new FillUi.Callback() {
                 @Override
                 public void onResponsePicked(FillResponse response) {
                     log.setType(MetricsEvent.TYPE_DETAIL);
@@ -332,7 +338,7 @@
                     }
                     mMetricsLogger.write(log);
                 }
-            }, isUpdate, compatMode);
+            }, mUiModeMgr.isNightMode(), isUpdate, compatMode);
         });
     }
 
@@ -368,6 +374,7 @@
         pw.println("Autofill UI");
         final String prefix = "  ";
         final String prefix2 = "    ";
+        pw.print(prefix); pw.print("Night mode: "); pw.println(mUiModeMgr.isNightMode());
         if (mFillUi != null) {
             pw.print(prefix); pw.println("showsFillUi: true");
             mFillUi.dump(pw, prefix2);
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 68a495f..742d494 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -73,7 +73,10 @@
 final class FillUi {
     private static final String TAG = "FillUi";
 
-    private static final int THEME_ID = com.android.internal.R.style.Theme_DeviceDefault_Autofill;
+    private static final int THEME_ID_LIGHT =
+            com.android.internal.R.style.Theme_DeviceDefault_Light_Autofill;
+    private static final int THEME_ID_DARK =
+            com.android.internal.R.style.Theme_DeviceDefault_Autofill;
 
     private static final TypedValue sTempTypedValue = new TypedValue();
 
@@ -117,6 +120,8 @@
 
     private boolean mDestroyed;
 
+    private final int mThemeId;
+
     public static boolean isFullScreen(Context context) {
         if (sFullScreenMode != null) {
             if (sVerbose) Slog.v(TAG, "forcing full-screen mode to " + sFullScreenMode);
@@ -128,10 +133,13 @@
     FillUi(@NonNull Context context, @NonNull FillResponse response,
            @NonNull AutofillId focusedViewId, @NonNull @Nullable String filterText,
            @NonNull OverlayControl overlayControl, @NonNull CharSequence serviceLabel,
-           @NonNull Drawable serviceIcon, @NonNull Callback callback) {
+           @NonNull Drawable serviceIcon, boolean nightMode, @NonNull Callback callback) {
+        if (sVerbose) Slog.v(TAG, "nightMode: " + nightMode);
+        mThemeId = nightMode ? THEME_ID_DARK : THEME_ID_LIGHT;
         mCallback = callback;
         mFullScreen = isFullScreen(context);
-        mContext = new ContextThemeWrapper(context, THEME_ID);
+        mContext = new ContextThemeWrapper(context, mThemeId);
+
         final LayoutInflater inflater = LayoutInflater.from(mContext);
 
         final RemoteViews headerPresentation = response.getHeader();
@@ -216,7 +224,7 @@
             ViewGroup container = decor.findViewById(R.id.autofill_dataset_picker);
             final View content;
             try {
-                response.getPresentation().setApplyTheme(THEME_ID);
+                response.getPresentation().setApplyTheme(mThemeId);
                 content = response.getPresentation().apply(mContext, decor, interceptionHandler);
                 container.addView(content);
             } catch (RuntimeException e) {
@@ -257,7 +265,7 @@
             RemoteViews.OnClickHandler clickBlocker = null;
             if (headerPresentation != null) {
                 clickBlocker = newClickBlocker();
-                headerPresentation.setApplyTheme(THEME_ID);
+                headerPresentation.setApplyTheme(mThemeId);
                 mHeader = headerPresentation.apply(mContext, null, clickBlocker);
                 final LinearLayout headerContainer =
                         decor.findViewById(R.id.autofill_dataset_header);
@@ -275,7 +283,7 @@
                     if (clickBlocker == null) { // already set for header
                         clickBlocker = newClickBlocker();
                     }
-                    footerPresentation.setApplyTheme(THEME_ID);
+                    footerPresentation.setApplyTheme(mThemeId);
                     mFooter = footerPresentation.apply(mContext, null, clickBlocker);
                     // Footer not supported on some platform e.g. TV
                     if (sVerbose) Slog.v(TAG, "adding footer");
@@ -302,7 +310,7 @@
                     final View view;
                     try {
                         if (sVerbose) Slog.v(TAG, "setting remote view for " + focusedViewId);
-                        presentation.setApplyTheme(THEME_ID);
+                        presentation.setApplyTheme(mThemeId);
                         view = presentation.apply(mContext, null, interceptionHandler);
                     } catch (RuntimeException e) {
                         Slog.e(TAG, "Error inflating remote views", e);
@@ -732,6 +740,18 @@
         pw.print(prefix); pw.print("mContentWidth: "); pw.println(mContentWidth);
         pw.print(prefix); pw.print("mContentHeight: "); pw.println(mContentHeight);
         pw.print(prefix); pw.print("mDestroyed: "); pw.println(mDestroyed);
+        pw.print(prefix); pw.print("theme id: "); pw.print(mThemeId);
+        switch (mThemeId) {
+            case THEME_ID_DARK:
+                pw.println(" (dark)");
+                break;
+            case THEME_ID_LIGHT:
+                pw.println(" (light)");
+                break;
+            default:
+                pw.println("(UNKNOWN_MODE)");
+                break;
+        }
         if (mWindow != null) {
             pw.print(prefix); pw.print("mWindow: ");
             final String prefix2 = prefix + "  ";
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 9d3d3cb..89b442e 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -72,9 +72,11 @@
  */
 final class SaveUi {
 
-    private static final String TAG = "AutofillSaveUi";
+    private static final String TAG = "SaveUi";
 
-    private static final int THEME_ID =
+    private static final int THEME_ID_LIGHT =
+            com.android.internal.R.style.Theme_DeviceDefault_Light_Autofill_Save;
+    private static final int THEME_ID_DARK =
             com.android.internal.R.style.Theme_DeviceDefault_Autofill_Save;
 
     public interface OnSaveListener {
@@ -144,6 +146,7 @@
     private final String mServicePackageName;
     private final ComponentName mComponentName;
     private final boolean mCompatMode;
+    private final int mThemeId;
 
     private boolean mDestroyed;
 
@@ -152,7 +155,9 @@
            @Nullable String servicePackageName, @NonNull ComponentName componentName,
            @NonNull SaveInfo info, @NonNull ValueFinder valueFinder,
            @NonNull OverlayControl overlayControl, @NonNull OnSaveListener listener,
-           boolean isUpdate, boolean compatMode) {
+           boolean nightMode, boolean isUpdate, boolean compatMode) {
+        if (sVerbose) Slog.v(TAG, "nightMode: " + nightMode);
+        mThemeId = nightMode ? THEME_ID_DARK : THEME_ID_LIGHT;
         mPendingUi= pendingUi;
         mListener = new OneActionThenDestroyListener(listener);
         mOverlayControl = overlayControl;
@@ -160,7 +165,7 @@
         mComponentName = componentName;
         mCompatMode = compatMode;
 
-        context = new ContextThemeWrapper(context, THEME_ID);
+        context = new ContextThemeWrapper(context, mThemeId);
         final LayoutInflater inflater = LayoutInflater.from(context);
         final View view = inflater.inflate(R.layout.autofill_save, null);
 
@@ -250,7 +255,7 @@
         }
         yesButton.setOnClickListener((v) -> mListener.onSave());
 
-        mDialog = new Dialog(context, THEME_ID);
+        mDialog = new Dialog(context, mThemeId);
         mDialog.setContentView(view);
 
         // Dialog can be dismissed when touched outside, but the negative listener should not be
@@ -337,7 +342,7 @@
 
         try {
             // Create the remote view peer.
-            template.setApplyTheme(THEME_ID);
+            template.setApplyTheme(mThemeId);
             final View customSubtitleView = template.apply(context, null, handler);
 
             // Apply batch updates (if any).
@@ -556,7 +561,18 @@
         pw.print(prefix); pw.print("service: "); pw.println(mServicePackageName);
         pw.print(prefix); pw.print("app: "); pw.println(mComponentName.toShortString());
         pw.print(prefix); pw.print("compat mode: "); pw.println(mCompatMode);
-
+        pw.print(prefix); pw.print("theme id: "); pw.print(mThemeId);
+        switch (mThemeId) {
+            case THEME_ID_DARK:
+                pw.println(" (dark)");
+                break;
+            case THEME_ID_LIGHT:
+                pw.println(" (light)");
+                break;
+            default:
+                pw.println("(UNKNOWN_MODE)");
+                break;
+        }
         final View view = mDialog.getWindow().getDecorView();
         final int[] loc = view.getLocationOnScreen();
         pw.print(prefix); pw.print("coordinates: ");
diff --git a/services/backup/java/com/android/server/backup/encryption/chunk/Chunk.java b/services/backup/java/com/android/server/backup/encryption/chunk/Chunk.java
new file mode 100644
index 0000000..5bec1a9
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/encryption/chunk/Chunk.java
@@ -0,0 +1,54 @@
+package com.android.server.backup.encryption.chunk;
+
+import android.util.proto.ProtoInputStream;
+
+import java.io.IOException;
+
+/**
+ * Information about a chunk entry in a protobuf. Only used for reading from a {@link
+ * ProtoInputStream}.
+ */
+public class Chunk {
+    /**
+     * Reads a Chunk from a {@link ProtoInputStream}. Expects the message to be of format {@link
+     * ChunksMetadataProto.Chunk}.
+     *
+     * @param inputStream currently at a {@link ChunksMetadataProto.Chunk} message.
+     * @throws IOException when the message is not structured as expected or a field can not be
+     *     read.
+     */
+    static Chunk readFromProto(ProtoInputStream inputStream) throws IOException {
+        Chunk result = new Chunk();
+
+        while (inputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+            switch (inputStream.getFieldNumber()) {
+                case (int) ChunksMetadataProto.Chunk.HASH:
+                    result.mHash = inputStream.readBytes(ChunksMetadataProto.Chunk.HASH);
+                    break;
+                case (int) ChunksMetadataProto.Chunk.LENGTH:
+                    result.mLength = inputStream.readInt(ChunksMetadataProto.Chunk.LENGTH);
+                    break;
+            }
+        }
+
+        return result;
+    }
+
+    private int mLength;
+    private byte[] mHash;
+
+    /** Private constructor. This class should only be instantiated by calling readFromProto. */
+    private Chunk() {
+        // Set default values for fields in case they are not available in the proto.
+        mHash = new byte[]{};
+        mLength = 0;
+    }
+
+    public int getLength() {
+        return mLength;
+    }
+
+    public byte[] getHash() {
+        return mHash;
+    }
+}
\ No newline at end of file
diff --git a/services/backup/java/com/android/server/backup/encryption/chunk/ChunkListing.java b/services/backup/java/com/android/server/backup/encryption/chunk/ChunkListing.java
new file mode 100644
index 0000000..2d2e88a
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/encryption/chunk/ChunkListing.java
@@ -0,0 +1,108 @@
+/*
+ * 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.chunk;
+
+import android.annotation.Nullable;
+import android.util.proto.ProtoInputStream;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Chunk listing in a format optimized for quick look-up of chunks via their hash keys. This is
+ * useful when building an incremental backup. After a chunk has been produced, the algorithm can
+ * quickly look up whether the chunk existed in the previous backup by checking this chunk listing.
+ * It can then tell the server to use that chunk, through telling it the position and length of the
+ * chunk in the previous backup's blob.
+ */
+public class ChunkListing {
+    /**
+     * Reads a ChunkListing from a {@link ProtoInputStream}. Expects the message to be of format
+     * {@link ChunksMetadataProto.ChunkListing}.
+     *
+     * @param inputStream Currently at a {@link ChunksMetadataProto.ChunkListing} message.
+     * @throws IOException when the message is not structured as expected or a field can not be
+     *     read.
+     */
+    public static ChunkListing readFromProto(ProtoInputStream inputStream) throws IOException {
+        Map<ChunkHash, Entry> entries = new HashMap();
+
+        long start = 0;
+
+        while (inputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+            if (inputStream.getFieldNumber() == (int) ChunksMetadataProto.ChunkListing.CHUNKS) {
+                long chunkToken = inputStream.start(ChunksMetadataProto.ChunkListing.CHUNKS);
+                Chunk chunk = Chunk.readFromProto(inputStream);
+                entries.put(new ChunkHash(chunk.getHash()), new Entry(start, chunk.getLength()));
+                start += chunk.getLength();
+                inputStream.end(chunkToken);
+            }
+        }
+
+        return new ChunkListing(entries);
+    }
+
+    private final Map<ChunkHash, Entry> mChunksByHash;
+
+    private ChunkListing(Map<ChunkHash, Entry> chunksByHash) {
+        mChunksByHash = Collections.unmodifiableMap(new HashMap<>(chunksByHash));
+    }
+
+    /** Returns {@code true} if there is a chunk with the given SHA-256 MAC key in the listing. */
+    public boolean hasChunk(ChunkHash hash) {
+        return mChunksByHash.containsKey(hash);
+    }
+
+    /**
+     * Returns the entry for the chunk with the given hash.
+     *
+     * @param hash The SHA-256 MAC of the plaintext of the chunk.
+     * @return The entry, containing position and length of the chunk in the backup blob, or null if
+     *     it does not exist.
+     */
+    @Nullable
+    public Entry getChunkEntry(ChunkHash hash) {
+        return mChunksByHash.get(hash);
+    }
+
+    /** Returns the number of chunks in this listing. */
+    public int getChunkCount() {
+        return mChunksByHash.size();
+    }
+
+    /** Information about a chunk entry in a backup blob - i.e., its position and length. */
+    public static final class Entry {
+        private final int mLength;
+        private final long mStart;
+
+        private Entry(long start, int length) {
+            mStart = start;
+            mLength = length;
+        }
+
+        /** Returns the length of the chunk in bytes. */
+        public int getLength() {
+            return mLength;
+        }
+
+        /** Returns the start position of the chunk in the backup blob, in bytes. */
+        public long getStart() {
+            return mStart;
+        }
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/encryption/chunk/EncryptedChunkOrdering.java b/services/backup/java/com/android/server/backup/encryption/chunk/EncryptedChunkOrdering.java
new file mode 100644
index 0000000..3a6d1f6
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/encryption/chunk/EncryptedChunkOrdering.java
@@ -0,0 +1,67 @@
+/*
+ * 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.chunk;
+
+import java.util.Arrays;
+
+/**
+ * Holds the bytes of an encrypted {@link ChunksMetadataProto.ChunkOrdering}.
+ *
+ * <p>TODO(b/116575321): After all code is ported, remove the factory method and rename
+ * encryptedChunkOrdering() to getBytes().
+ */
+public class EncryptedChunkOrdering {
+    /**
+     * Constructs a new object holding the given bytes of an encrypted {@link
+     * ChunksMetadataProto.ChunkOrdering}.
+     *
+     * <p>Note that this just holds an ordering which is already encrypted, it does not encrypt the
+     * ordering.
+     */
+    public static EncryptedChunkOrdering create(byte[] encryptedChunkOrdering) {
+        return new EncryptedChunkOrdering(encryptedChunkOrdering);
+    }
+
+    private final byte[] mEncryptedChunkOrdering;
+
+    public byte[] encryptedChunkOrdering() {
+        return mEncryptedChunkOrdering;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof EncryptedChunkOrdering)) {
+            return false;
+        }
+
+        EncryptedChunkOrdering encryptedChunkOrdering = (EncryptedChunkOrdering) o;
+        return Arrays.equals(
+                mEncryptedChunkOrdering, encryptedChunkOrdering.mEncryptedChunkOrdering);
+    }
+
+    @Override
+    public int hashCode() {
+        return Arrays.hashCode(mEncryptedChunkOrdering);
+    }
+
+    private EncryptedChunkOrdering(byte[] encryptedChunkOrdering) {
+        mEncryptedChunkOrdering = encryptedChunkOrdering;
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/keyvalue/AgentException.java b/services/backup/java/com/android/server/backup/keyvalue/AgentException.java
new file mode 100644
index 0000000..e2ca351
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/keyvalue/AgentException.java
@@ -0,0 +1,63 @@
+/*
+ * 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.keyvalue;
+
+/**
+ * This represents something wrong with a specific package. For example:
+ * <ul>
+ *     <li>Package unknown.
+ *     <li>Package is not eligible for backup anymore.
+ *     <li>Backup agent timed out.
+ *     <li>Backup agent wrote protected keys.
+ *     <li>...
+ * </ul>
+ *
+ * @see KeyValueBackupTask
+ * @see TaskException
+ */
+class AgentException extends BackupException {
+    static AgentException transitory() {
+        return new AgentException(/* transitory */ true);
+    }
+
+    static AgentException transitory(Exception cause) {
+        return new AgentException(/* transitory */ true, cause);
+    }
+
+    static AgentException permanent() {
+        return new AgentException(/* transitory */ false);
+    }
+
+    static AgentException permanent(Exception cause) {
+        return new AgentException(/* transitory */ false, cause);
+    }
+
+    private final boolean mTransitory;
+
+    private AgentException(boolean transitory) {
+        mTransitory = transitory;
+    }
+
+    private AgentException(boolean transitory, Exception cause) {
+        super(cause);
+        mTransitory = transitory;
+    }
+
+    boolean isTransitory() {
+        return mTransitory;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/events/StartedDragingEvent.java b/services/backup/java/com/android/server/backup/keyvalue/BackupException.java
similarity index 60%
copy from packages/SystemUI/src/com/android/systemui/stackdivider/events/StartedDragingEvent.java
copy to services/backup/java/com/android/server/backup/keyvalue/BackupException.java
index 5d19851..27b2d35 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/events/StartedDragingEvent.java
+++ b/services/backup/java/com/android/server/backup/keyvalue/BackupException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 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.
@@ -14,12 +14,20 @@
  * limitations under the License
  */
 
-package com.android.systemui.stackdivider.events;
+package com.android.server.backup.keyvalue;
 
-import com.android.systemui.recents.events.EventBus;
+import android.util.AndroidException;
 
 /**
- * Sent when the divider is being draged either manually or by an animation.
+ * Key-value backup task exception.
+ *
+ * @see AgentException
+ * @see TaskException
  */
-public class StartedDragingEvent extends EventBus.Event {
+class BackupException extends AndroidException {
+    BackupException() {}
+
+    BackupException(Exception cause) {
+        super(cause);
+    }
 }
diff --git a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupReporter.java b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupReporter.java
index 54e6b1d..bb8a1d1 100644
--- a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupReporter.java
+++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupReporter.java
@@ -54,7 +54,7 @@
 public class KeyValueBackupReporter {
     @VisibleForTesting static final String TAG = "KeyValueBackupTask";
     private static final boolean DEBUG = BackupManagerService.DEBUG;
-    @VisibleForTesting static final boolean MORE_DEBUG = BackupManagerService.MORE_DEBUG || true;
+    @VisibleForTesting static final boolean MORE_DEBUG = BackupManagerService.MORE_DEBUG || false;
 
     static void onNewThread(String threadName) {
         if (DEBUG) {
@@ -153,16 +153,18 @@
                 mObserver, packageName, BackupManager.ERROR_BACKUP_NOT_ALLOWED);
     }
 
-    void onBindAgentError(SecurityException e) {
-        Slog.d(TAG, "Error in bind/backup", e);
-    }
-
     void onAgentUnknown(String packageName) {
         Slog.d(TAG, "Package does not exist, skipping");
         BackupObserverUtils.sendBackupOnPackageResult(
                 mObserver, packageName, BackupManager.ERROR_PACKAGE_NOT_FOUND);
     }
 
+    void onBindAgentError(String packageName, SecurityException e) {
+        Slog.d(TAG, "Error in bind/backup", e);
+        BackupObserverUtils.sendBackupOnPackageResult(
+                mObserver, packageName, BackupManager.ERROR_AGENT_FAILURE);
+    }
+
     void onAgentError(String packageName) {
         if (MORE_DEBUG) {
             Slog.i(TAG, "Agent failure for " + packageName + ", re-staging");
@@ -190,6 +192,8 @@
     void onCallAgentDoBackupError(String packageName, boolean callingAgent, Exception e) {
         if (callingAgent) {
             Slog.e(TAG, "Error invoking agent on " + packageName + ": " + e);
+            BackupObserverUtils.sendBackupOnPackageResult(
+                    mObserver, packageName, BackupManager.ERROR_AGENT_FAILURE);
         } else {
             Slog.e(TAG, "Error before invoking agent on " + packageName + ": " + e);
         }
@@ -220,12 +224,8 @@
         }
     }
 
-    void onReadAgentDataError(String packageName, IOException e) {
-        Slog.w(TAG, "Unable read backup data for " + packageName + ": " + e);
-    }
-
-    void onWriteWidgetDataError(String packageName, IOException e) {
-        Slog.w(TAG, "Unable to save widget data for " + packageName + ": " + e);
+    void onAgentDataError(String packageName, IOException e) {
+        Slog.w(TAG, "Unable to read/write agent data for " + packageName + ": " + e);
     }
 
     void onDigestError(NoSuchAlgorithmException e) {
@@ -243,16 +243,12 @@
         }
     }
 
-    void onSendDataToTransport(String packageName) {
+    void onTransportPerformBackup(String packageName) {
         if (MORE_DEBUG) {
             Slog.v(TAG, "Sending non-empty data to transport for " + packageName);
         }
     }
 
-    void onNonIncrementalAndNonIncrementalRequired() {
-        Slog.e(TAG, "Transport requested non-incremental but already the case");
-    }
-
     void onEmptyData(PackageInfo packageInfo) {
         if (MORE_DEBUG) {
             Slog.i(TAG, "No backup data written, not calling transport");
@@ -302,13 +298,20 @@
                 /* extras */ null);
     }
 
+    void onPackageBackupNonIncrementalAndNonIncrementalRequired(String packageName) {
+        Slog.e(TAG, "Transport requested non-incremental but already the case");
+        BackupObserverUtils.sendBackupOnPackageResult(
+                mObserver, packageName, BackupManager.ERROR_TRANSPORT_ABORTED);
+        EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_FAILURE, packageName);
+    }
+
     void onPackageBackupTransportFailure(String packageName) {
         BackupObserverUtils.sendBackupOnPackageResult(
                 mObserver, packageName, BackupManager.ERROR_TRANSPORT_ABORTED);
         EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_FAILURE, packageName);
     }
 
-    void onPackageBackupError(String packageName, Exception e) {
+    void onPackageBackupTransportError(String packageName, Exception e) {
         Slog.e(TAG, "Transport error backing up " + packageName, e);
         BackupObserverUtils.sendBackupOnPackageResult(
                 mObserver, packageName, BackupManager.ERROR_TRANSPORT_ABORTED);
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 e915ce1..6904b3f 100644
--- a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
+++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
@@ -16,6 +16,7 @@
 
 package com.android.server.backup.keyvalue;
 
+import static android.app.ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL;
 import static android.os.ParcelFileDescriptor.MODE_CREATE;
 import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
 import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
@@ -25,8 +26,8 @@
 import static com.android.server.backup.BackupManagerService.OP_PENDING;
 import static com.android.server.backup.BackupManagerService.OP_TYPE_BACKUP;
 
+import android.annotation.IntDef;
 import android.annotation.Nullable;
-import android.app.ApplicationThreadConstants;
 import android.app.IBackupAgent;
 import android.app.backup.BackupAgent;
 import android.app.backup.BackupDataInput;
@@ -47,7 +48,6 @@
 import android.os.SELinux;
 import android.os.UserHandle;
 import android.os.WorkSource;
-import android.util.Pair;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
@@ -77,6 +77,8 @@
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
@@ -173,10 +175,8 @@
     private static final AtomicInteger THREAD_COUNT = new AtomicInteger();
     private static final String BLANK_STATE_FILE_NAME = "blank_state";
     private static final String PM_PACKAGE = BackupManagerService.PACKAGE_MANAGER_SENTINEL;
-    @VisibleForTesting
-    public static final String STAGING_FILE_SUFFIX = ".data";
-    @VisibleForTesting
-    public static final String NEW_STATE_FILE_SUFFIX = ".new";
+    @VisibleForTesting public static final String STAGING_FILE_SUFFIX = ".data";
+    @VisibleForTesting public static final String NEW_STATE_FILE_SUFFIX = ".new";
 
     /**
      * Creates a new {@link KeyValueBackupTask} for key-value backup operation, spins up a new
@@ -244,13 +244,13 @@
     private final int mCurrentOpToken;
     private final File mStateDirectory;
     private final File mDataDirectory;
+    private final File mBlankStateFile;
     private final List<String> mOriginalQueue;
     private final List<String> mQueue;
     private final List<String> mPendingFullBackups;
     private final Object mQueueLock;
     @Nullable private final DataChangedJournal mJournal;
 
-    private int mStatus;
     @Nullable private PerformFullTransportBackupTask mFullBackupTask;
     @Nullable private IBackupAgent mAgent;
     @Nullable private PackageInfo mCurrentPackage;
@@ -316,6 +316,7 @@
         mDataDirectory = mBackupManagerService.getDataDir();
         mCurrentOpToken = backupManagerService.generateRandomIntegerToken();
         mQueueLock = mBackupManagerService.getQueueLock();
+        mBlankStateFile = new File(mStateDirectory, BLANK_STATE_FILE_NAME);
     }
 
     private void registerTask() {
@@ -331,45 +332,43 @@
     public void run() {
         Process.setThreadPriority(THREAD_PRIORITY);
 
-        boolean processQueue = startTask();
-        while (processQueue && !mQueue.isEmpty() && !mCancelled) {
-            String packageName = mQueue.remove(0);
-            if (PM_PACKAGE.equals(packageName)) {
-                processQueue = backupPm();
-            } else {
-                processQueue = backupPackage(packageName);
+        int status = BackupTransport.TRANSPORT_OK;
+        try {
+            startTask();
+            while (!mQueue.isEmpty() && !mCancelled) {
+                String packageName = mQueue.remove(0);
+                try {
+                    if (PM_PACKAGE.equals(packageName)) {
+                        backupPm();
+                    } else {
+                        backupPackage(packageName);
+                    }
+                } catch (AgentException e) {
+                    if (e.isTransitory()) {
+                        // We try again this package in the next backup pass.
+                        mBackupManagerService.dataChangedImpl(packageName);
+                    }
+                }
             }
+        } catch (TaskException e) {
+            if (e.isStateCompromised()) {
+                mBackupManagerService.resetBackupState(mStateDirectory);
+            }
+            revertTask();
+            status = e.getStatus();
         }
-        finishTask();
+        finishTask(status);
     }
 
-    /** Returns whether to consume next queue package. */
-    private boolean handleAgentResult(@Nullable PackageInfo packageInfo, RemoteResult result) {
-        if (result == RemoteResult.FAILED_THREAD_INTERRUPTED) {
-            // Not an explicit cancel, we need to flag it.
-            mCancelled = true;
-            mReporter.onAgentCancelled(packageInfo);
-            cleanUpAgentForAgentError();
-            return false;
+    /** Returns transport status. */
+    private int sendDataToTransport(@Nullable PackageInfo packageInfo)
+            throws AgentException, TaskException {
+        try {
+            return sendDataToTransport();
+        } catch (IOException e) {
+            mReporter.onAgentDataError(packageInfo.packageName, e);
+            throw TaskException.causedBy(e);
         }
-        if (result == RemoteResult.FAILED_CANCELLED) {
-            mReporter.onAgentCancelled(packageInfo);
-            cleanUpAgentForAgentError();
-            return false;
-        }
-        if (result == RemoteResult.FAILED_TIMED_OUT) {
-            mReporter.onAgentTimedOut(packageInfo);
-            cleanUpAgentForAgentError();
-            return true;
-        }
-        Preconditions.checkState(result.isPresent());
-        long agentResult = result.get();
-        if (agentResult == BackupAgent.RESULT_ERROR) {
-            mReporter.onAgentResultError(packageInfo);
-            cleanUpAgentForAgentError();
-            return true;
-        }
-        return sendDataToTransport();
     }
 
     @Override
@@ -378,11 +377,10 @@
     @Override
     public void operationComplete(long unusedResult) {}
 
-    /** Returns whether to consume next queue package. */
-    private boolean startTask() {
+    private void startTask() throws TaskException {
         if (mBackupManagerService.isBackupOperationInProgress()) {
             mReporter.onSkipBackup();
-            return false;
+            throw TaskException.create();
         }
 
         // Unfortunately full backup task constructor registers the task with BMS, so we have to
@@ -390,11 +388,9 @@
         mFullBackupTask = createFullBackupTask(mPendingFullBackups);
         registerTask();
 
-        mStatus = BackupTransport.TRANSPORT_OK;
-
         if (mQueue.isEmpty() && mPendingFullBackups.isEmpty()) {
             mReporter.onEmptyQueueAtStart();
-            return false;
+            return;
         }
         // We only backup PM if it was explicitly in the queue or if it's incremental.
         boolean backupPm = mQueue.remove(PM_PACKAGE) || !mNonIncremental;
@@ -415,20 +411,18 @@
             if (pmState.length() <= 0) {
                 mReporter.onInitializeTransport(transportName);
                 mBackupManagerService.resetBackupState(mStateDirectory);
-                mStatus = transport.initializeDevice();
-                mReporter.onTransportInitialized(mStatus);
+                int status = transport.initializeDevice();
+                mReporter.onTransportInitialized(status);
+                if (status != BackupTransport.TRANSPORT_OK) {
+                    throw TaskException.stateCompromised();
+                }
             }
+        } catch (TaskException e) {
+            throw e;
         } catch (Exception e) {
             mReporter.onInitializeTransportError(e);
-            mStatus = BackupTransport.TRANSPORT_ERROR;
+            throw TaskException.stateCompromised();
         }
-
-        if (mStatus != BackupTransport.TRANSPORT_OK) {
-            mBackupManagerService.resetBackupState(mStateDirectory);
-            return false;
-        }
-
-        return true;
     }
 
     private PerformFullTransportBackupTask createFullBackupTask(List<String> packages) {
@@ -446,120 +440,82 @@
                 mUserInitiated);
     }
 
-    /** Returns whether to consume next queue package. */
-    private boolean backupPm() {
-        RemoteResult agentResult = null;
+    private void backupPm() throws TaskException {
+        mReporter.onStartPackageBackup(PM_PACKAGE);
+        mCurrentPackage = new PackageInfo();
+        mCurrentPackage.packageName = PM_PACKAGE;
+
         try {
-            mCurrentPackage = new PackageInfo();
-            mCurrentPackage.packageName = PM_PACKAGE;
-
-            // Since PM is running in the system process we can set up its agent directly.
-            BackupAgent pmAgent = mBackupManagerService.makeMetadataAgent();
-            mAgent = IBackupAgent.Stub.asInterface(pmAgent.onBind());
-
-            Pair<Integer, RemoteResult> statusAndResult = extractAgentData(PM_PACKAGE, mAgent);
-            mStatus = statusAndResult.first;
-            agentResult = statusAndResult.second;
-        } catch (Exception e) {
+            extractPmAgentData(mCurrentPackage);
+            int status = sendDataToTransport(mCurrentPackage);
+            cleanUpAgentForTransportStatus(status);
+        } catch (AgentException | TaskException e) {
             mReporter.onExtractPmAgentDataError(e);
-            mStatus = BackupTransport.TRANSPORT_ERROR;
+            cleanUpAgentForError(e);
+            // PM agent failure is task failure.
+            throw TaskException.stateCompromised(e);
         }
-
-        if (mStatus != BackupTransport.TRANSPORT_OK) {
-            // In this case either extractAgentData() already made the agent clean-up or we haven't
-            // prepared the state for calling the agent, in either case we don't need to clean-up.
-            mBackupManagerService.resetBackupState(mStateDirectory);
-            return false;
-        }
-
-        Preconditions.checkNotNull(agentResult);
-        return handleAgentResult(mCurrentPackage, agentResult);
     }
 
-    /** Returns whether to consume next queue package. */
-    private boolean backupPackage(String packageName) {
+    private void backupPackage(String packageName) throws AgentException, TaskException {
         mReporter.onStartPackageBackup(packageName);
-        mStatus = BackupTransport.TRANSPORT_OK;
+        mCurrentPackage = getPackageForBackup(packageName);
 
-        // Verify that the requested app is eligible for key-value backup.
-        RemoteResult agentResult = null;
         try {
-            mCurrentPackage = mPackageManager.getPackageInfo(
-                    packageName, PackageManager.GET_SIGNING_CERTIFICATES);
-            ApplicationInfo applicationInfo = mCurrentPackage.applicationInfo;
-            if (!AppBackupUtils.appIsEligibleForBackup(applicationInfo, mPackageManager)) {
-                // The manifest has changed. This won't happen again because the app won't be
-                // requesting further backups.
-                mReporter.onPackageNotEligibleForBackup(packageName);
-                return true;
-            }
-
-            if (AppBackupUtils.appGetsFullBackup(mCurrentPackage)) {
-                // Initially enqueued for key-value backup, but only supports full-backup now.
-                mReporter.onPackageEligibleForFullBackup(packageName);
-                return true;
-            }
-
-            if (AppBackupUtils.appIsStopped(applicationInfo)) {
-                // Just as it won't receive broadcasts, we won't run it for backup.
-                mReporter.onPackageStopped(packageName);
-                return true;
-            }
-
-            try {
-                mBackupManagerService.setWorkSource(new WorkSource(applicationInfo.uid));
-                IBackupAgent agent =
-                        mBackupManagerService.bindToAgentSynchronous(
-                                applicationInfo,
-                                ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL);
-                if (agent != null) {
-                    mAgent = agent;
-                    Pair<Integer, RemoteResult> statusAndResult =
-                            extractAgentData(packageName, agent);
-                    mStatus = statusAndResult.first;
-                    agentResult = statusAndResult.second;
-                } else {
-                    // Timeout waiting for the agent to bind.
-                    mStatus = BackupTransport.AGENT_ERROR;
-                }
-            } catch (SecurityException e) {
-                mReporter.onBindAgentError(e);
-                mStatus = BackupTransport.AGENT_ERROR;
-            }
-        } catch (PackageManager.NameNotFoundException e) {
-            mStatus = BackupTransport.AGENT_UNKNOWN;
-        } finally {
-            mBackupManagerService.setWorkSource(null);
+            extractAgentData(mCurrentPackage);
+            int status = sendDataToTransport(mCurrentPackage);
+            cleanUpAgentForTransportStatus(status);
+        } catch (AgentException | TaskException e) {
+            cleanUpAgentForError(e);
+            throw e;
         }
-
-        if (mStatus != BackupTransport.TRANSPORT_OK) {
-            // In this case either extractAgentData() already made the agent clean-up or we haven't
-            // prepared the state for calling the agent, in either case we don't need to clean-up.
-            Preconditions.checkState(mAgent == null);
-
-            if (mStatus == BackupTransport.AGENT_ERROR) {
-                mReporter.onAgentError(packageName);
-                mBackupManagerService.dataChangedImpl(packageName);
-                mStatus = BackupTransport.TRANSPORT_OK;
-                return true;
-            }
-
-            if (mStatus == BackupTransport.AGENT_UNKNOWN) {
-                mReporter.onAgentUnknown(packageName);
-                mStatus = BackupTransport.TRANSPORT_OK;
-                return true;
-            }
-
-            // Transport-level failure, re-enqueue everything.
-            revertTask();
-            return false;
-        }
-
-        Preconditions.checkNotNull(agentResult);
-        return handleAgentResult(mCurrentPackage, agentResult);
     }
 
-    private void finishTask() {
+    private PackageInfo getPackageForBackup(String packageName) throws AgentException {
+        final PackageInfo packageInfo;
+        try {
+            packageInfo =
+                    mPackageManager.getPackageInfo(
+                            packageName, PackageManager.GET_SIGNING_CERTIFICATES);
+        } catch (PackageManager.NameNotFoundException e) {
+            mReporter.onAgentUnknown(packageName);
+            throw AgentException.permanent(e);
+        }
+        ApplicationInfo applicationInfo = packageInfo.applicationInfo;
+        if (!AppBackupUtils.appIsEligibleForBackup(applicationInfo, mPackageManager)) {
+            mReporter.onPackageNotEligibleForBackup(packageName);
+            throw AgentException.permanent();
+        }
+        if (AppBackupUtils.appGetsFullBackup(packageInfo)) {
+            mReporter.onPackageEligibleForFullBackup(packageName);
+            throw AgentException.permanent();
+        }
+        if (AppBackupUtils.appIsStopped(applicationInfo)) {
+            mReporter.onPackageStopped(packageName);
+            throw AgentException.permanent();
+        }
+        return packageInfo;
+    }
+
+    private IBackupAgent bindAgent(PackageInfo packageInfo) throws AgentException {
+        String packageName = packageInfo.packageName;
+        final IBackupAgent agent;
+        try {
+            agent =
+                    mBackupManagerService.bindToAgentSynchronous(
+                            packageInfo.applicationInfo, BACKUP_MODE_INCREMENTAL);
+            if (agent == null) {
+                mReporter.onAgentError(packageName);
+                throw AgentException.transitory();
+            }
+        } catch (SecurityException e) {
+            mReporter.onBindAgentError(packageName, e);
+            throw AgentException.transitory(e);
+        }
+        return agent;
+    }
+
+    private void finishTask(int status) {
         // Mark packages that we couldn't backup as pending backup.
         for (String packageName : mQueue) {
             mBackupManagerService.dataChangedImpl(packageName);
@@ -576,7 +532,7 @@
         // If 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 ((mStatus == BackupTransport.TRANSPORT_OK) && (currentToken == 0)) {
+        if ((status == BackupTransport.TRANSPORT_OK) && (currentToken == 0)) {
             try {
                 IBackupTransport transport = mTransportClient.connectOrThrow(callerLogString);
                 mBackupManagerService.setCurrentToken(transport.getCurrentRestoreSet());
@@ -589,9 +545,14 @@
 
         synchronized (mQueueLock) {
             mBackupManagerService.setBackupRunning(false);
-            if (mStatus == BackupTransport.TRANSPORT_NOT_INITIALIZED) {
+            if (status == BackupTransport.TRANSPORT_NOT_INITIALIZED) {
                 mReporter.onTransportNotInitialized();
-                triggerTransportInitializationLocked();
+                try {
+                    triggerTransportInitializationLocked();
+                } catch (Exception e) {
+                    mReporter.onPendingInitializeTransportError(e);
+                    status = BackupTransport.TRANSPORT_ERROR;
+                }
             }
         }
 
@@ -605,7 +566,7 @@
         }
 
         if (!mCancelled
-                && mStatus == BackupTransport.TRANSPORT_OK
+                && status == BackupTransport.TRANSPORT_OK
                 && mFullBackupTask != null
                 && !mPendingFullBackups.isEmpty()) {
             mReporter.onStartFullBackup(mPendingFullBackups);
@@ -621,7 +582,7 @@
             mFullBackupTask.unregisterTask();
         }
         mTaskFinishedListener.onFinished(callerLogString);
-        mReporter.onBackupFinished(getBackupFinishedStatus(mCancelled, mStatus));
+        mReporter.onBackupFinished(getBackupFinishedStatus(mCancelled, status));
         mBackupManagerService.getWakelock().release();
     }
 
@@ -642,17 +603,12 @@
     }
 
     @GuardedBy("mQueueLock")
-    private void triggerTransportInitializationLocked() {
-        try {
-            IBackupTransport transport =
-                    mTransportClient.connectOrThrow("KVBT.triggerTransportInitializationLocked");
-            mBackupManagerService.getPendingInits().add(transport.name());
-            deletePmStateFile();
-            mBackupManagerService.backupNow();
-        } catch (Exception e) {
-            mReporter.onPendingInitializeTransportError(e);
-            mStatus = BackupTransport.TRANSPORT_ERROR;
-        }
+    private void triggerTransportInitializationLocked() throws Exception {
+        IBackupTransport transport =
+                mTransportClient.connectOrThrow("KVBT.triggerTransportInitializationLocked");
+        mBackupManagerService.getPendingInits().add(transport.name());
+        deletePmStateFile();
+        mBackupManagerService.backupNow();
     }
 
     /** Removes PM state, triggering initialization in the next key-value task. */
@@ -660,35 +616,69 @@
         new File(mStateDirectory, PM_PACKAGE).delete();
     }
 
+    /** Same as {@link #extractAgentData(PackageInfo)}, but only for PM package. */
+    private void extractPmAgentData(PackageInfo packageInfo) throws AgentException, TaskException {
+        Preconditions.checkArgument(packageInfo.packageName.equals(PM_PACKAGE));
+        BackupAgent pmAgent = mBackupManagerService.makeMetadataAgent();
+        mAgent = IBackupAgent.Stub.asInterface(pmAgent.onBind());
+        extractAgentData(packageInfo, mAgent);
+    }
+
     /**
-     * Returns a {@link Pair}. The first of the pair contains the status. In case the status is
-     * {@link BackupTransport#TRANSPORT_OK}, the second of the pair contains the agent result,
-     * otherwise {@code null}.
+     * Binds to the agent and extracts its backup data. If this method returns, the data in {@code
+     * mBackupData} is ready to be sent to the transport, otherwise it will throw.
+     *
+     * <p>This method leaves agent resources (agent binder, files and file-descriptors) opened that
+     * need to be cleaned up after terminating, either successfully or exceptionally. This clean-up
+     * can be done with methods {@link #cleanUpAgentForTransportStatus(int)} and {@link
+     * #cleanUpAgentForError(BackupException)}, depending on whether data was successfully sent to
+     * the transport or not. It's the caller responsibility to do the clean-up or delegate it.
      */
-    private Pair<Integer, RemoteResult> extractAgentData(String packageName, IBackupAgent agent) {
+    private void extractAgentData(PackageInfo packageInfo) throws AgentException, TaskException {
+        mBackupManagerService.setWorkSource(new WorkSource(packageInfo.applicationInfo.uid));
+        try {
+            mAgent = bindAgent(packageInfo);
+            extractAgentData(packageInfo, mAgent);
+        } finally {
+            mBackupManagerService.setWorkSource(null);
+        }
+    }
+
+    /**
+     * Calls agent {@link IBackupAgent#doBackup(ParcelFileDescriptor, ParcelFileDescriptor,
+     * ParcelFileDescriptor, long, IBackupCallback, int)} and waits for the result. If this method
+     * returns, the data in {@code mBackupData} is ready to be sent to the transport, otherwise it
+     * will throw.
+     *
+     * <p>This method creates files and file-descriptors for the agent that need to be deleted and
+     * closed after terminating, either successfully or exceptionally. This clean-up can be done
+     * with methods {@link #cleanUpAgentForTransportStatus(int)} and {@link
+     * #cleanUpAgentForError(BackupException)}, depending on whether data was successfully sent to
+     * the transport or not. It's the caller responsibility to do the clean-up or delegate it.
+     */
+    private void extractAgentData(PackageInfo packageInfo, IBackupAgent agent)
+            throws AgentException, TaskException {
+        String packageName = packageInfo.packageName;
         mReporter.onExtractAgentData(packageName);
 
-        File blankStateFile = new File(mStateDirectory, BLANK_STATE_FILE_NAME);
         mSavedStateFile = new File(mStateDirectory, packageName);
         mBackupDataFile = new File(mDataDirectory, packageName + STAGING_FILE_SUFFIX);
         mNewStateFile = new File(mStateDirectory, packageName + NEW_STATE_FILE_SUFFIX);
         mReporter.onAgentFilesReady(mBackupDataFile);
 
-        mSavedState = null;
-        mBackupData = null;
-        mNewState = null;
-
         boolean callingAgent = false;
         final RemoteResult agentResult;
         try {
-            File savedStateFileForAgent = (mNonIncremental) ? blankStateFile : mSavedStateFile;
+            File savedStateFileForAgent = (mNonIncremental) ? mBlankStateFile : mSavedStateFile;
             // MODE_CREATE to make an empty file if necessary
-            mSavedState = ParcelFileDescriptor.open(
-                    savedStateFileForAgent, MODE_READ_ONLY | MODE_CREATE);
-            mBackupData = ParcelFileDescriptor.open(
-                    mBackupDataFile, MODE_READ_WRITE | MODE_CREATE | MODE_TRUNCATE);
-            mNewState = ParcelFileDescriptor.open(
-                    mNewStateFile, MODE_READ_WRITE | MODE_CREATE | MODE_TRUNCATE);
+            mSavedState =
+                    ParcelFileDescriptor.open(savedStateFileForAgent, MODE_READ_ONLY | MODE_CREATE);
+            mBackupData =
+                    ParcelFileDescriptor.open(
+                            mBackupDataFile, MODE_READ_WRITE | MODE_CREATE | MODE_TRUNCATE);
+            mNewState =
+                    ParcelFileDescriptor.open(
+                            mNewStateFile, MODE_READ_WRITE | MODE_CREATE | MODE_TRUNCATE);
 
             if (!SELinux.restorecon(mBackupDataFile)) {
                 mReporter.onRestoreconFailed(mBackupDataFile);
@@ -713,15 +703,40 @@
                             "doBackup()");
         } catch (Exception e) {
             mReporter.onCallAgentDoBackupError(packageName, callingAgent, e);
-            cleanUpAgentForAgentError();
-            // TODO: Remove the check on callingAgent when RemoteCall supports local agent calls.
-            int status =
-                    callingAgent ? BackupTransport.AGENT_ERROR : BackupTransport.TRANSPORT_ERROR;
-            return Pair.create(status, null);
+            if (callingAgent) {
+                throw AgentException.transitory(e);
+            } else {
+                throw TaskException.create();
+            }
+        } finally {
+            mBlankStateFile.delete();
         }
-        blankStateFile.delete();
+        checkAgentResult(packageInfo, agentResult);
+    }
 
-        return Pair.create(BackupTransport.TRANSPORT_OK, agentResult);
+    private void checkAgentResult(PackageInfo packageInfo, RemoteResult result)
+            throws AgentException, TaskException {
+        if (result == RemoteResult.FAILED_THREAD_INTERRUPTED) {
+            // Not an explicit cancel, we need to flag it.
+            mCancelled = true;
+            mReporter.onAgentCancelled(packageInfo);
+            throw TaskException.create();
+        }
+        if (result == RemoteResult.FAILED_CANCELLED) {
+            mReporter.onAgentCancelled(packageInfo);
+            throw TaskException.create();
+        }
+        if (result == RemoteResult.FAILED_TIMED_OUT) {
+            mReporter.onAgentTimedOut(packageInfo);
+            throw AgentException.transitory();
+        }
+        Preconditions.checkState(result.isPresent());
+        long resultCode = result.get();
+        if (resultCode == BackupAgent.RESULT_ERROR) {
+            mReporter.onAgentResultError(packageInfo);
+            throw AgentException.transitory();
+        }
+        Preconditions.checkState(resultCode == BackupAgent.RESULT_SUCCESS);
     }
 
     private void agentFail(IBackupAgent agent, String message) {
@@ -801,94 +816,79 @@
         }
     }
 
-    /** Returns whether to consume next queue package. */
-    private boolean sendDataToTransport() {
+    /** Returns transport status. */
+    private int sendDataToTransport() throws AgentException, TaskException, IOException {
         Preconditions.checkState(mBackupData != null);
+        checkBackupData(mCurrentPackage.applicationInfo, mBackupDataFile);
 
         String packageName = mCurrentPackage.packageName;
-        ApplicationInfo applicationInfo = mCurrentPackage.applicationInfo;
-
-        boolean writingWidgetData = false;
-        try {
-            if (!validateBackupData(applicationInfo, mBackupDataFile)) {
-                cleanUpAgentForAgentError();
-                return true;
-            }
-            writingWidgetData = true;
-            writeWidgetPayloadIfAppropriate(mBackupData.getFileDescriptor(), packageName);
-        } catch (IOException e) {
-            if (writingWidgetData) {
-                mReporter.onWriteWidgetDataError(packageName, e);
-            } else {
-                mReporter.onReadAgentDataError(packageName, e);
-            }
-            cleanUpAgentForAgentError();
-            revertTask();
-            return false;
-        }
+        writeWidgetPayloadIfAppropriate(mBackupData.getFileDescriptor(), packageName);
 
         boolean nonIncremental = mSavedStateFile.length() == 0;
-        long size = mBackupDataFile.length();
-        if (size > 0) {
-            try (ParcelFileDescriptor backupData =
-                         ParcelFileDescriptor.open(mBackupDataFile, MODE_READ_ONLY)) {
-                IBackupTransport transport =
-                        mTransportClient.connectOrThrow("KVBT.sendDataToTransport()");
-                mReporter.onSendDataToTransport(packageName);
-                int flags = getPerformBackupFlags(mUserInitiated, nonIncremental);
-
-                mStatus = transport.performBackup(mCurrentPackage, backupData, flags);
-                if (mStatus == BackupTransport.TRANSPORT_OK) {
-                    mStatus = transport.finishBackup();
-                }
-            } catch (Exception e) {
-                mReporter.onPackageBackupError(packageName, e);
-                mStatus = BackupTransport.TRANSPORT_ERROR;
-            }
-        } else {
-            mReporter.onEmptyData(mCurrentPackage);
-            mStatus = BackupTransport.TRANSPORT_OK;
-        }
-
-        if (nonIncremental
-                && mStatus == BackupTransport.TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED) {
-            mReporter.onNonIncrementalAndNonIncrementalRequired();
-            mStatus = BackupTransport.TRANSPORT_ERROR;
-        }
-
-
-        boolean processQueue = handleTransportStatus(mStatus, packageName, size);
-        // We might report quota exceeded to the agent in handleTransportStatus() above, so we
-        // only clean-up after it.
-        cleanUpAgentForTransportStatus(mStatus);
-        return processQueue;
+        int status = transportPerformBackup(mCurrentPackage, mBackupDataFile, nonIncremental);
+        handleTransportStatus(status, packageName, mBackupDataFile.length());
+        return status;
     }
 
-    /** Returns whether to consume next queue package. */
-    private boolean handleTransportStatus(int status, String packageName, long size) {
+    private int transportPerformBackup(
+            PackageInfo packageInfo, File backupDataFile, boolean nonIncremental)
+            throws TaskException {
+        String packageName = packageInfo.packageName;
+        long size = backupDataFile.length();
+        if (size <= 0) {
+            mReporter.onEmptyData(packageInfo);
+            return BackupTransport.TRANSPORT_OK;
+        }
+
+        int status;
+        try (ParcelFileDescriptor backupData =
+                ParcelFileDescriptor.open(backupDataFile, MODE_READ_ONLY)) {
+            IBackupTransport transport =
+                    mTransportClient.connectOrThrow("KVBT.transportPerformBackup()");
+            mReporter.onTransportPerformBackup(packageName);
+            int flags = getPerformBackupFlags(mUserInitiated, nonIncremental);
+
+            status = transport.performBackup(packageInfo, backupData, flags);
+            if (status == BackupTransport.TRANSPORT_OK) {
+                status = transport.finishBackup();
+            }
+        } catch (Exception e) {
+            mReporter.onPackageBackupTransportError(packageName, e);
+            throw TaskException.causedBy(e);
+        }
+
+        if (nonIncremental && status == BackupTransport.TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED) {
+            mReporter.onPackageBackupNonIncrementalAndNonIncrementalRequired(packageName);
+            throw TaskException.create();
+        }
+
+        return status;
+    }
+
+    private void handleTransportStatus(int status, String packageName, long size)
+            throws TaskException, AgentException {
         if (status == BackupTransport.TRANSPORT_OK) {
             mReporter.onPackageBackupComplete(packageName, size);
-            return true;
-        }
-        if (status == BackupTransport.TRANSPORT_PACKAGE_REJECTED) {
-            mReporter.onPackageBackupRejected(packageName);
-            return true;
+            return;
         }
         if (status == BackupTransport.TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED) {
             mReporter.onPackageBackupNonIncrementalRequired(mCurrentPackage);
             // Immediately retry the current package.
             mQueue.add(0, packageName);
-            return true;
+            return;
+        }
+        if (status == BackupTransport.TRANSPORT_PACKAGE_REJECTED) {
+            mReporter.onPackageBackupRejected(packageName);
+            throw AgentException.permanent();
         }
         if (status == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) {
             mReporter.onPackageBackupQuotaExceeded(packageName);
             agentDoQuotaExceeded(mAgent, packageName, size);
-            return true;
+            throw AgentException.permanent();
         }
         // Any other error here indicates a transport-level failure.
         mReporter.onPackageBackupTransportFailure(packageName);
-        revertTask();
-        return false;
+        throw TaskException.forStatus(status);
     }
 
     private void agentDoQuotaExceeded(@Nullable IBackupAgent agent, String packageName, long size) {
@@ -908,19 +908,17 @@
     }
 
     /**
-     * For system apps and pseudo-apps always return {@code true}. For regular apps returns whether
-     * {@code backupDataFile} doesn't have any protected keys.
-     *
-     * <p>If the app has attempted to write any protected keys we also crash them.
+     * For system apps and pseudo-apps never throws. For regular apps throws {@link AgentException}
+     * if {@code backupDataFile} has any protected keys, also crashing the app.
      */
-    private boolean validateBackupData(
-            @Nullable ApplicationInfo applicationInfo, File backupDataFile) throws IOException {
+    private void checkBackupData(@Nullable ApplicationInfo applicationInfo, File backupDataFile)
+            throws IOException, AgentException {
         if (applicationInfo == null || (applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
             // System apps and pseudo-apps can write what they want.
-            return true;
+            return;
         }
         try (ParcelFileDescriptor backupData =
-                     ParcelFileDescriptor.open(backupDataFile, MODE_READ_ONLY)) {
+                ParcelFileDescriptor.open(backupDataFile, MODE_READ_ONLY)) {
             BackupDataInput backupDataInput = new BackupDataInput(backupData.getFileDescriptor());
             while (backupDataInput.readNextHeader()) {
                 String key = backupDataInput.getKey();
@@ -928,12 +926,11 @@
                     mReporter.onAgentIllegalKey(mCurrentPackage, key);
                     // Crash them if they wrote any protected keys.
                     agentFail(mAgent, "Illegal backup key: " + key);
-                    return false;
+                    throw AgentException.permanent();
                 }
                 backupDataInput.skipEntityData();
             }
         }
-        return true;
     }
 
     private int getPerformBackupFlags(boolean userInitiated, boolean nonIncremental) {
@@ -1009,44 +1006,39 @@
         }
     }
 
-    /** Cleans-up after having called the agent. */
+    /**
+     * Cleans up agent resources opened by {@link #extractAgentData(PackageInfo)} for exceptional
+     * case.
+     *
+     * <p>Note: Declaring exception parameter so that the caller only calls this when an exception
+     * is thrown.
+     */
+    private void cleanUpAgentForError(BackupException exception) {
+        cleanUpAgent(StateTransaction.DISCARD_NEW);
+    }
+
+    /**
+     * Cleans up agent resources opened by {@link #extractAgentData(PackageInfo)} according to
+     * transport status returned in {@link #sendDataToTransport(PackageInfo)}.
+     */
     private void cleanUpAgentForTransportStatus(int status) {
-        updateFiles(status);
-        cleanUpAgent();
-    }
-
-    /** Cleans-up if we failed to call the agent. */
-    private void cleanUpAgentForAgentError() {
-        mBackupDataFile.delete();
-        mNewStateFile.delete();
-        cleanUpAgent();
-    }
-
-    private void updateFiles(int status) {
         switch (status) {
             case BackupTransport.TRANSPORT_OK:
-                mBackupDataFile.delete();
-                mNewStateFile.renameTo(mSavedStateFile);
+                cleanUpAgent(StateTransaction.COMMIT_NEW);
                 break;
             case BackupTransport.TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED:
-                mSavedStateFile.delete();
-                mBackupDataFile.delete();
-                mNewStateFile.delete();
+                cleanUpAgent(StateTransaction.DISCARD_ALL);
                 break;
             default:
-                // Includes:
-                // * BackupTransport.TRANSPORT_PACKAGE_REJECTED
-                // * BackupTransport.TRANSPORT_QUOTA_EXCEEDED
-                // * BackupTransport.TRANSPORT_ERROR
-                mBackupDataFile.delete();
-                mNewStateFile.delete();
-                break;
+                // All other transport statuses are properly converted to agent or task exceptions.
+                throw new AssertionError();
         }
     }
 
-    /** Cleans-up file-descriptors and unbinds agent. */
-    private void cleanUpAgent() {
-        mAgent = null;
+    private void cleanUpAgent(@StateTransaction int stateTransaction) {
+        applyStateTransaction(stateTransaction);
+        mBackupDataFile.delete();
+        mBlankStateFile.delete();
         tryCloseFileDescriptor(mSavedState, "old state");
         tryCloseFileDescriptor(mBackupData, "backup data");
         tryCloseFileDescriptor(mNewState, "new state");
@@ -1058,6 +1050,24 @@
         if (mCurrentPackage.applicationInfo != null) {
             mBackupManagerService.unbindAgent(mCurrentPackage.applicationInfo);
         }
+        mAgent = null;
+    }
+
+    private void applyStateTransaction(@StateTransaction int stateTransaction) {
+        switch (stateTransaction) {
+            case StateTransaction.COMMIT_NEW:
+                mNewStateFile.renameTo(mSavedStateFile);
+                break;
+            case StateTransaction.DISCARD_NEW:
+                mNewStateFile.delete();
+                break;
+            case StateTransaction.DISCARD_ALL:
+                mSavedStateFile.delete();
+                mNewStateFile.delete();
+                break;
+            default:
+                throw new IllegalArgumentException("Unknown state transaction " + stateTransaction);
+        }
     }
 
     private void tryCloseFileDescriptor(@Nullable Closeable closeable, String logName) {
@@ -1079,4 +1089,16 @@
         mPendingCall = null;
         return result;
     }
+
+    @IntDef({
+        StateTransaction.COMMIT_NEW,
+        StateTransaction.DISCARD_NEW,
+        StateTransaction.DISCARD_ALL,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface StateTransaction {
+        int COMMIT_NEW = 0;
+        int DISCARD_NEW = 1;
+        int DISCARD_ALL = 2;
+    }
 }
diff --git a/services/backup/java/com/android/server/backup/keyvalue/TaskException.java b/services/backup/java/com/android/server/backup/keyvalue/TaskException.java
new file mode 100644
index 0000000..08d2895
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/keyvalue/TaskException.java
@@ -0,0 +1,83 @@
+/*
+ * 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.keyvalue;
+
+import android.app.backup.BackupTransport;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * The key-value backup task has failed, no more packages will be processed and we shouldn't attempt
+ * any more backups now. These can be caused by transport failures (as opposed to agent failures).
+ *
+ * @see KeyValueBackupTask
+ * @see AgentException
+ */
+class TaskException extends BackupException {
+    private static final int DEFAULT_STATUS = BackupTransport.TRANSPORT_ERROR;
+
+    static TaskException stateCompromised() {
+        return new TaskException(/* stateCompromised */ true, DEFAULT_STATUS);
+    }
+
+    static TaskException stateCompromised(Exception cause) {
+        if (cause instanceof TaskException) {
+            TaskException exception = (TaskException) cause;
+            return new TaskException(cause, /* stateCompromised */ true, exception.getStatus());
+        }
+        return new TaskException(cause, /* stateCompromised */ true, DEFAULT_STATUS);
+    }
+
+    static TaskException forStatus(int status) {
+        Preconditions.checkArgument(
+                status != BackupTransport.TRANSPORT_OK, "Exception based on TRANSPORT_OK");
+        return new TaskException(/* stateCompromised */ false, status);
+    }
+
+    static TaskException causedBy(Exception cause) {
+        if (cause instanceof TaskException) {
+            return (TaskException) cause;
+        }
+        return new TaskException(cause, /* stateCompromised */ false, DEFAULT_STATUS);
+    }
+
+    static TaskException create() {
+        return new TaskException(/* stateCompromised */ false, DEFAULT_STATUS);
+    }
+
+    private final boolean mStateCompromised;
+    private final int mStatus;
+
+    private TaskException(Exception cause, boolean stateCompromised, int status) {
+        super(cause);
+        mStateCompromised = stateCompromised;
+        mStatus = status;
+    }
+
+    private TaskException(boolean stateCompromised, int status) {
+        mStateCompromised = stateCompromised;
+        mStatus = status;
+    }
+
+    boolean isStateCompromised() {
+        return mStateCompromised;
+    }
+
+    int getStatus() {
+        return mStatus;
+    }
+}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index e41a09e..a1989e5 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -57,6 +57,7 @@
 import android.net.ConnectivityManager.PacketKeepalive;
 import android.net.IConnectivityManager;
 import android.net.IIpConnectivityMetrics;
+import android.net.INetd;
 import android.net.INetdEventCallback;
 import android.net.INetworkManagementEventObserver;
 import android.net.INetworkPolicyListener;
@@ -88,6 +89,7 @@
 import android.net.metrics.NetworkEvent;
 import android.net.netlink.InetDiagMessage;
 import android.net.util.MultinetworkPolicyTracker;
+import android.net.util.NetdService;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
@@ -259,7 +261,8 @@
     // 0 is full bad, 100 is full good
     private int mDefaultInetConditionPublished = 0;
 
-    private INetworkManagementService mNetd;
+    private INetworkManagementService mNMS;
+    private INetd mNetd;
     private INetworkStatsService mStatsService;
     private INetworkPolicyManager mPolicyManager;
     private NetworkPolicyManagerInternal mPolicyManagerInternal;
@@ -759,7 +762,7 @@
         mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS);
 
         mContext = checkNotNull(context, "missing Context");
-        mNetd = checkNotNull(netManager, "missing INetworkManagementService");
+        mNMS = checkNotNull(netManager, "missing INetworkManagementService");
         mStatsService = checkNotNull(statsService, "missing INetworkStatsService");
         mPolicyManager = checkNotNull(policyManager, "missing INetworkPolicyManager");
         mPolicyManagerInternal = checkNotNull(
@@ -767,6 +770,7 @@
                 "missing NetworkPolicyManagerInternal");
         mProxyTracker = new ProxyTracker(context, mHandler, EVENT_PROXY_HAS_CHANGED);
 
+        mNetd = NetdService.getInstance();
         mKeyStore = KeyStore.getInstance();
         mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
 
@@ -849,7 +853,7 @@
 
         mTethering = makeTethering();
 
-        mPermissionMonitor = new PermissionMonitor(mContext, mNetd);
+        mPermissionMonitor = new PermissionMonitor(mContext, mNMS);
 
         //set up the listener for user state for creating user VPNs
         IntentFilter intentFilter = new IntentFilter();
@@ -864,8 +868,8 @@
                 new IntentFilter(Intent.ACTION_USER_PRESENT), null, null);
 
         try {
-            mNetd.registerObserver(mTethering);
-            mNetd.registerObserver(mDataActivityObserver);
+            mNMS.registerObserver(mTethering);
+            mNMS.registerObserver(mDataActivityObserver);
         } catch (RemoteException e) {
             loge("Error registering observer :" + e);
         }
@@ -896,7 +900,7 @@
 
         mMultipathPolicyTracker = new MultipathPolicyTracker(mContext, mHandler);
 
-        mDnsManager = new DnsManager(mContext, mNetd, mSystemProperties);
+        mDnsManager = new DnsManager(mContext, mNMS, mSystemProperties);
         registerPrivateDnsSettingsCallbacks();
     }
 
@@ -912,7 +916,7 @@
                 return mDefaultRequest;
             }
         };
-        return new Tethering(mContext, mNetd, mStatsService, mPolicyManager,
+        return new Tethering(mContext, mNMS, mStatsService, mPolicyManager,
                 IoThread.get().getLooper(), new MockableSystemProperties(),
                 deps);
     }
@@ -1476,6 +1480,20 @@
     };
 
     /**
+     * Ensures that the system cannot call a particular method.
+     */
+    private boolean disallowedBecauseSystemCaller() {
+        // TODO: start throwing a SecurityException when GnssLocationProvider stops calling
+        // requestRouteToHost.
+        if (isSystem(Binder.getCallingUid())) {
+            log("This method exists only for app backwards compatibility"
+                    + " and must not be called by system services.");
+            return true;
+        }
+        return false;
+    }
+
+    /**
      * Ensure that a network route exists to deliver traffic to the specified
      * host via the specified network interface.
      * @param networkType the type of the network over which traffic to the
@@ -1486,6 +1504,9 @@
      */
     @Override
     public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress) {
+        if (disallowedBecauseSystemCaller()) {
+            return false;
+        }
         enforceChangePermission();
         if (mProtectedNetworks.contains(networkType)) {
             enforceConnectivityInternalPermission();
@@ -1563,7 +1584,7 @@
         if (DBG) log("Adding legacy route " + bestRoute +
                 " for UID/PID " + uid + "/" + Binder.getCallingPid());
         try {
-            mNetd.addLegacyRouteForNetId(netId, bestRoute, uid);
+            mNMS.addLegacyRouteForNetId(netId, bestRoute, uid);
         } catch (Exception e) {
             // never crash - catch them all
             if (DBG) loge("Exception trying to add a route: " + e);
@@ -1853,7 +1874,7 @@
 
         if (timeout > 0 && iface != null && type != ConnectivityManager.TYPE_NONE) {
             try {
-                mNetd.addIdleTimer(iface, timeout, type);
+                mNMS.addIdleTimer(iface, timeout, type);
             } catch (Exception e) {
                 // You shall not crash!
                 loge("Exception in setupDataActivityTracking " + e);
@@ -1872,7 +1893,7 @@
                               caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))) {
             try {
                 // the call fails silently if no idle timer setup for this interface
-                mNetd.removeIdleTimer(iface);
+                mNMS.removeIdleTimer(iface);
             } catch (Exception e) {
                 loge("Exception in removeDataActivityTracking " + e);
             }
@@ -1880,6 +1901,18 @@
     }
 
     /**
+     * Update data activity tracking when network state is updated.
+     */
+    private void updateDataActivityTracking(NetworkAgentInfo newNetwork,
+            NetworkAgentInfo oldNetwork) {
+        if (newNetwork != null) {
+            setupDataActivityTracking(newNetwork);
+        }
+        if (oldNetwork != null) {
+            removeDataActivityTracking(oldNetwork);
+        }
+    }
+    /**
      * Reads the network specific MTU size from resources.
      * and set it on it's iface.
      */
@@ -1907,7 +1940,7 @@
 
         try {
             if (VDBG) log("Setting MTU size: " + iface + ", " + mtu);
-            mNetd.setMtu(iface, mtu);
+            mNMS.setMtu(iface, mtu);
         } catch (Exception e) {
             Slog.e(TAG, "exception in setMtu()" + e);
         }
@@ -2561,7 +2594,7 @@
         }
         nai.clearLingerState();
         if (nai.isSatisfyingRequest(mDefaultRequest.requestId)) {
-            removeDataActivityTracking(nai);
+            updateDataActivityTracking(null /* newNetwork */, nai);
             notifyLockdownVpn(nai);
             ensureNetworkTransitionWakelock(nai.name());
         }
@@ -2581,7 +2614,7 @@
             // NetworkFactories, so network traffic isn't interrupted for an unnecessarily
             // long time.
             try {
-                mNetd.removeNetwork(nai.network.netId);
+                mNMS.removeNetwork(nai.network.netId);
             } catch (Exception e) {
                 loge("Exception removing network: " + e);
             }
@@ -2779,20 +2812,6 @@
                 }
             }
 
-            // TODO: remove this code once we know that the Slog.wtf is never hit.
-            //
-            // Find all networks that are satisfying this request and remove the request
-            // from their request lists.
-            // TODO - it's my understanding that for a request there is only a single
-            // network satisfying it, so this loop is wasteful
-            for (NetworkAgentInfo otherNai : mNetworkAgentInfos.values()) {
-                if (otherNai.isSatisfyingRequest(nri.request.requestId) && otherNai != nai) {
-                    Slog.wtf(TAG, "Request " + nri.request + " satisfied by " +
-                            otherNai.name() + ", but mNetworkAgentInfos says " +
-                            (nai != null ? nai.name() : "null"));
-                }
-            }
-
             // Maintain the illusion.  When this request arrived, we might have pretended
             // that a network connected to serve it, even though the network was already
             // connected.  Now that this request has gone away, we might have to pretend
@@ -3760,7 +3779,7 @@
                     Slog.w(TAG, "VPN for user " + user + " not ready yet. Skipping lockdown");
                     return false;
                 }
-                setLockdownTracker(new LockdownVpnTracker(mContext, mNetd, this, vpn, profile));
+                setLockdownTracker(new LockdownVpnTracker(mContext, mNMS, this, vpn, profile));
             } else {
                 setLockdownTracker(null);
             }
@@ -4015,7 +4034,7 @@
                 loge("Starting user already has a VPN");
                 return;
             }
-            userVpn = new Vpn(mHandler.getLooper(), mContext, mNetd, userId);
+            userVpn = new Vpn(mHandler.getLooper(), mContext, mNMS, userId);
             mVpns.put(userId, userVpn);
             if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
                 updateLockdownVpn();
@@ -4632,7 +4651,7 @@
         mDnsManager.updatePrivateDnsStatus(netId, newLp);
 
         // Start or stop clat accordingly to network state.
-        networkAgent.updateClat(mNetd);
+        networkAgent.updateClat(mNMS);
         if (isDefaultNetwork(networkAgent)) {
             handleApplyDefaultProxy(newLp.getHttpProxy());
         } else {
@@ -4671,9 +4690,9 @@
         final String prefix = "iface:" + iface;
         try {
             if (add) {
-                mNetd.getNetdService().wakeupAddInterface(iface, prefix, mark, mask);
+                mNetd.wakeupAddInterface(iface, prefix, mark, mask);
             } else {
-                mNetd.getNetdService().wakeupDelInterface(iface, prefix, mark, mask);
+                mNetd.wakeupDelInterface(iface, prefix, mark, mask);
             }
         } catch (Exception e) {
             loge("Exception modifying wakeup packet monitoring: " + e);
@@ -4689,7 +4708,7 @@
         for (String iface : interfaceDiff.added) {
             try {
                 if (DBG) log("Adding iface " + iface + " to network " + netId);
-                mNetd.addInterfaceToNetwork(iface, netId);
+                mNMS.addInterfaceToNetwork(iface, netId);
                 wakeupModifyInterface(iface, caps, true);
             } catch (Exception e) {
                 loge("Exception adding interface: " + e);
@@ -4699,7 +4718,7 @@
             try {
                 if (DBG) log("Removing iface " + iface + " from network " + netId);
                 wakeupModifyInterface(iface, caps, false);
-                mNetd.removeInterfaceFromNetwork(iface, netId);
+                mNMS.removeInterfaceFromNetwork(iface, netId);
             } catch (Exception e) {
                 loge("Exception removing interface: " + e);
             }
@@ -4723,7 +4742,7 @@
             if (route.hasGateway()) continue;
             if (VDBG) log("Adding Route [" + route + "] to network " + netId);
             try {
-                mNetd.addRoute(netId, route);
+                mNMS.addRoute(netId, route);
             } catch (Exception e) {
                 if ((route.getDestination().getAddress() instanceof Inet4Address) || VDBG) {
                     loge("Exception in addRoute for non-gateway: " + e);
@@ -4734,7 +4753,7 @@
             if (route.hasGateway() == false) continue;
             if (VDBG) log("Adding Route [" + route + "] to network " + netId);
             try {
-                mNetd.addRoute(netId, route);
+                mNMS.addRoute(netId, route);
             } catch (Exception e) {
                 if ((route.getGateway() instanceof Inet4Address) || VDBG) {
                     loge("Exception in addRoute for gateway: " + e);
@@ -4745,7 +4764,7 @@
         for (RouteInfo route : routeDiff.removed) {
             if (VDBG) log("Removing Route [" + route + "] from network " + netId);
             try {
-                mNetd.removeRoute(netId, route);
+                mNMS.removeRoute(netId, route);
             } catch (Exception e) {
                 loge("Exception in removeRoute: " + e);
             }
@@ -4857,7 +4876,7 @@
         final String newPermission = getNetworkPermission(newNc);
         if (!Objects.equals(oldPermission, newPermission) && nai.created && !nai.isVPN()) {
             try {
-                mNetd.setNetworkPermission(nai.network.netId, newPermission);
+                mNMS.setNetworkPermission(nai.network.netId, newPermission);
             } catch (RemoteException e) {
                 loge("Exception in setNetworkPermission: " + e);
             }
@@ -4917,12 +4936,12 @@
             if (!newRanges.isEmpty()) {
                 final UidRange[] addedRangesArray = new UidRange[newRanges.size()];
                 newRanges.toArray(addedRangesArray);
-                mNetd.addVpnUidRanges(nai.network.netId, addedRangesArray);
+                mNMS.addVpnUidRanges(nai.network.netId, addedRangesArray);
             }
             if (!prevRanges.isEmpty()) {
                 final UidRange[] removedRangesArray = new UidRange[prevRanges.size()];
                 prevRanges.toArray(removedRangesArray);
-                mNetd.removeVpnUidRanges(nai.network.netId, removedRangesArray);
+                mNMS.removeVpnUidRanges(nai.network.netId, removedRangesArray);
             }
         } catch (Exception e) {
             // Never crash!
@@ -5091,9 +5110,9 @@
 
     private void makeDefault(NetworkAgentInfo newNetwork) {
         if (DBG) log("Switching to new default network: " + newNetwork);
-        setupDataActivityTracking(newNetwork);
+
         try {
-            mNetd.setDefaultNetId(newNetwork.network.netId);
+            mNMS.setDefaultNetId(newNetwork.network.netId);
         } catch (Exception e) {
             loge("Exception setting default network :" + e);
         }
@@ -5266,6 +5285,7 @@
             }
         }
         if (isNewDefault) {
+            updateDataActivityTracking(newNetwork, oldDefaultNetwork);
             // Notify system services that this network is up.
             makeDefault(newNetwork);
             // Log 0 -> X and Y -> X default network transitions, where X is the new default.
@@ -5488,12 +5508,12 @@
             try {
                 // This should never fail.  Specifying an already in use NetID will cause failure.
                 if (networkAgent.isVPN()) {
-                    mNetd.createVirtualNetwork(networkAgent.network.netId,
+                    mNMS.createVirtualNetwork(networkAgent.network.netId,
                             !networkAgent.linkProperties.getDnsServers().isEmpty(),
                             (networkAgent.networkMisc == null ||
                                 !networkAgent.networkMisc.allowBypass));
                 } else {
-                    mNetd.createPhysicalNetwork(networkAgent.network.netId,
+                    mNMS.createPhysicalNetwork(networkAgent.network.netId,
                             getNetworkPermission(networkAgent.networkCapabilities));
                 }
             } catch (Exception e) {
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 1d163ee..de930f7 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -161,6 +161,8 @@
 
     private static final int MAX_UID_RANGES_PER_COMMAND = 10;
 
+    private static final  String[] EMPTY_STRING_ARRAY = new String[0];
+
     /**
      * Name representing {@link #setGlobalAlert(long)} limit when delivered to
      * {@link INetworkManagementEventObserver#limitReached(String, String)}.
@@ -1234,18 +1236,12 @@
     @Override
     public void startTethering(String[] dhcpRange) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-        // cmd is "tether start first_start first_stop second_start second_stop ..."
         // an odd number of addrs will fail
 
-        final Command cmd = new Command("tether", "start");
-        for (String d : dhcpRange) {
-            cmd.appendArg(d);
-        }
-
         try {
-            mConnector.execute(cmd);
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
+            mNetdService.tetherStart(dhcpRange);
+        } catch (RemoteException | ServiceSpecificException e) {
+            throw new IllegalStateException(e);
         }
     }
 
@@ -1253,9 +1249,9 @@
     public void stopTethering() {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
         try {
-            mConnector.execute("tether", "stop");
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
+            mNetdService.tetherStop();
+        } catch (RemoteException | ServiceSpecificException e) {
+            throw new IllegalStateException(e);
         }
     }
 
@@ -1263,25 +1259,21 @@
     public boolean isTetheringStarted() {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
 
-        final NativeDaemonEvent event;
         try {
-            event = mConnector.execute("tether", "status");
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
+            final boolean isEnabled = mNetdService.tetherIsEnabled();
+            return isEnabled;
+        } catch (RemoteException | ServiceSpecificException e) {
+            throw new IllegalStateException(e);
         }
-
-        // 210 Tethering services started
-        event.checkCode(TetherStatusResult);
-        return event.getMessage().endsWith("started");
     }
 
     @Override
     public void tetherInterface(String iface) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
         try {
-            mConnector.execute("tether", "interface", "add", iface);
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
+            mNetdService.tetherInterfaceAdd(iface);
+        } catch (RemoteException | ServiceSpecificException e) {
+            throw new IllegalStateException(e);
         }
         List<RouteInfo> routes = new ArrayList<>();
         // The RouteInfo constructor truncates the LinkAddress to a network prefix, thus making it
@@ -1294,9 +1286,9 @@
     public void untetherInterface(String iface) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
         try {
-            mConnector.execute("tether", "interface", "remove", iface);
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
+            mNetdService.tetherInterfaceRemove(iface);
+        } catch (RemoteException | ServiceSpecificException e) {
+            throw new IllegalStateException(e);
         } finally {
             removeInterfaceFromLocalNetwork(iface);
         }
@@ -1306,11 +1298,10 @@
     public String[] listTetheredInterfaces() {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
         try {
-            return NativeDaemonEvent.filterMessageList(
-                    mConnector.executeForList("tether", "interface", "list"),
-                    TetherInterfaceListResult);
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
+            final List<String> result = mNetdService.tetherInterfaceList();
+            return result.toArray(EMPTY_STRING_ARRAY);
+        } catch (RemoteException | ServiceSpecificException e) {
+            throw new IllegalStateException(e);
         }
     }
 
@@ -1319,16 +1310,11 @@
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
 
         int netId = (network != null) ? network.netId : ConnectivityManager.NETID_UNSET;
-        final Command cmd = new Command("tether", "dns", "set", netId);
-
-        for (String s : dns) {
-            cmd.appendArg(NetworkUtils.numericToInetAddress(s).getHostAddress());
-        }
 
         try {
-            mConnector.execute(cmd);
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
+            mNetdService.tetherDnsSet(netId, dns);
+        } catch (RemoteException | ServiceSpecificException e) {
+            throw new IllegalStateException(e);
         }
     }
 
@@ -1336,10 +1322,10 @@
     public String[] getDnsForwarders() {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
         try {
-            return NativeDaemonEvent.filterMessageList(
-                    mConnector.executeForList("tether", "dns", "list"), TetherDnsFwdTgtListResult);
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
+            final List<String> result = mNetdService.tetherDnsList();
+            return result.toArray(EMPTY_STRING_ARRAY);
+        } catch (RemoteException | ServiceSpecificException e) {
+            throw new IllegalStateException(e);
         }
     }
 
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index d505a77..21f54dd 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -329,6 +329,12 @@
     @GuardedBy("mPackagesLock")
     private final SparseArray<String> mSandboxIds = new SparseArray<>();
 
+    /**
+     * List of volumes visible to any user.
+     * TODO: may be have a map of userId -> volumes?
+     */
+    private final CopyOnWriteArrayList<VolumeInfo> mVisibleVols = new CopyOnWriteArrayList<>();
+
     private volatile int mCurrentUserId = UserHandle.USER_SYSTEM;
 
     /** Holding lock for AppFuse business */
@@ -623,16 +629,12 @@
                         Slog.i(TAG, "Ignoring mount " + vol.getId() + " due to policy");
                         break;
                     }
-                    try {
-                        mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
-                    } catch (Exception e) {
-                        Slog.wtf(TAG, e);
-                    }
+                    mount(vol);
                     break;
                 }
                 case H_VOLUME_UNMOUNT: {
                     final VolumeInfo vol = (VolumeInfo) msg.obj;
-                    unmount(vol.getId());
+                    unmount(vol);
                     break;
                 }
                 case H_VOLUME_BROADCAST: {
@@ -869,6 +871,8 @@
                 addInternalVolumeLocked();
             }
 
+            mVisibleVols.clear();
+
             try {
                 mVold.reset();
 
@@ -1466,7 +1470,7 @@
                     = mContext.getPackageManager().getInstalledApplicationsAsUser(
                             PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
             synchronized (mPackagesLock) {
-                final ArraySet<String> userPackages = getPackagesForUserPL(userId);
+                final ArraySet<String> userPackages = getAvailablePackagesForUserPL(userId);
                 for (int i = appInfos.size() - 1; i >= 0; --i) {
                     if (appInfos.get(i).isInstantApp()) {
                         continue;
@@ -1523,7 +1527,7 @@
     }
 
     @GuardedBy("mPackagesLock")
-    private ArraySet<String> getPackagesForUserPL(int userId) {
+    private ArraySet<String> getAvailablePackagesForUserPL(int userId) {
         ArraySet<String> userPackages = mPackages.get(userId);
         if (userPackages == null) {
             userPackages = new ArraySet<>();
@@ -1535,8 +1539,24 @@
     private String[] getPackagesArrayForUser(int userId) {
         if (!ENABLE_ISOLATED_STORAGE) return EmptyArray.STRING;
 
+        final ArraySet<String> userPackages;
         synchronized (mPackagesLock) {
-            return getPackagesForUserPL(userId).toArray(new String[0]);
+            userPackages = getAvailablePackagesForUserPL(userId);
+            if (!userPackages.isEmpty()) {
+                return userPackages.toArray(new String[0]);
+            }
+        }
+        final List<ApplicationInfo> appInfos =
+                mContext.getPackageManager().getInstalledApplicationsAsUser(
+                        PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
+        synchronized (mPackagesLock) {
+            for (int i = appInfos.size() - 1; i >= 0; --i) {
+                if (appInfos.get(i).isInstantApp()) {
+                    continue;
+                }
+                userPackages.add(appInfos.get(i).packageName);
+            }
+            return userPackages.toArray(new String[0]);
         }
     }
 
@@ -1747,8 +1767,15 @@
         if (isMountDisallowed(vol)) {
             throw new SecurityException("Mounting " + volId + " restricted by policy");
         }
+        mount(vol);
+    }
+
+    private void mount(VolumeInfo vol) {
         try {
             mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
+            if ((vol.mountFlags & VolumeInfo.MOUNT_FLAG_VISIBLE) != 0) {
+                mVisibleVols.add(vol);
+            }
         } catch (Exception e) {
             Slog.wtf(TAG, e);
         }
@@ -1759,8 +1786,15 @@
         enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
 
         final VolumeInfo vol = findVolumeByIdOrThrow(volId);
+        unmount(vol);
+    }
+
+    private void unmount(VolumeInfo vol) {
         try {
             mVold.unmount(vol.id);
+            if ((vol.mountFlags & VolumeInfo.MOUNT_FLAG_VISIBLE) != 0) {
+                mVisibleVols.remove(vol);
+            }
         } catch (Exception e) {
             Slog.wtf(TAG, e);
         }
@@ -3596,6 +3630,14 @@
             pw.decreaseIndent();
 
             pw.println();
+            pw.println("mVisibleVols:");
+            pw.increaseIndent();
+            for (int i = 0; i < mVisibleVols.size(); i++) {
+                mVisibleVols.get(i).dump(pw);
+            }
+            pw.decreaseIndent();
+
+            pw.println();
             pw.println("Primary storage UUID: " + mPrimaryStorageUuid);
             final Pair<String, Long> pair = StorageManager.getPrimaryStoragePathAndSize();
             if (pair == null) {
@@ -3716,7 +3758,7 @@
                 int userId) {
             final String sandboxId;
             synchronized (mPackagesLock) {
-                final ArraySet<String> userPackages = getPackagesForUserPL(userId);
+                final ArraySet<String> userPackages = getAvailablePackagesForUserPL(userId);
                 // If userPackages is empty, it means the user is not started yet, so no need to
                 // do anything now.
                 if (userPackages.isEmpty() || userPackages.contains(packageName)) {
@@ -3734,5 +3776,29 @@
                 Slog.wtf(TAG, e);
             }
         }
+
+        @Override
+        public String[] getVisibleVolumesForUser(int userId) {
+            final ArrayList<String> visibleVolsForUser = new ArrayList<>();
+            for (int i = mVisibleVols.size() - 1; i >= 0; --i) {
+                final VolumeInfo vol = mVisibleVols.get(i);
+                if (vol.isVisibleForUser(userId)) {
+                    visibleVolsForUser.add(getVolumeLabel(vol));
+                }
+            }
+            return visibleVolsForUser.toArray(new String[visibleVolsForUser.size()]);
+        }
+
+        private String getVolumeLabel(VolumeInfo vol) {
+            // STOPSHIP: Label needs to part of VolumeInfo and need to be passed on from vold
+            switch (vol.getType()) {
+                case VolumeInfo.TYPE_EMULATED:
+                    return "emulated";
+                case VolumeInfo.TYPE_PUBLIC:
+                    return vol.fsUuid == null ? vol.id : vol.fsUuid;
+                default:
+                    return null;
+            }
+        }
     }
 }
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 98b88cb..fb8894b 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -213,6 +213,8 @@
 
     private PhoneCapability mPhoneCapability = null;
 
+    private int mPreferredDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
     private final LocalLog mLocalLog = new LocalLog(100);
 
     private PreciseDataConnectionState mPreciseDataConnectionState =
@@ -752,6 +754,13 @@
                             remove(r.binder);
                         }
                     }
+                    if ((events & PhoneStateListener.LISTEN_PREFERRED_DATA_SUBID_CHANGE) != 0) {
+                        try {
+                            r.callback.onPreferredDataSubIdChanged(mPreferredDataSubId);
+                        } catch (RemoteException ex) {
+                            remove(r.binder);
+                        }
+                    }
                 }
             }
         } else {
@@ -1573,6 +1582,31 @@
         }
     }
 
+    public void notifyPreferredDataSubIdChanged(int preferredSubId) {
+        if (!checkNotifyPermission("notifyPreferredDataSubIdChanged()")) {
+            return;
+        }
+
+        if (VDBG) {
+            log("notifyPreferredDataSubIdChanged: preferredSubId=" + preferredSubId);
+        }
+
+        synchronized (mRecords) {
+            mPreferredDataSubId = preferredSubId;
+
+            for (Record r : mRecords) {
+                if (r.matchPhoneStateListenerEvent(
+                        PhoneStateListener.LISTEN_PREFERRED_DATA_SUBID_CHANGE)) {
+                    try {
+                        r.callback.onPreferredDataSubIdChanged(preferredSubId);
+                    } catch (RemoteException ex) {
+                        mRemoveList.add(r.binder);
+                    }
+                }
+            }
+            handleRemoveListLocked();
+        }
+    }
 
     @Override
     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
@@ -1610,6 +1644,7 @@
             pw.println("mBackgroundCallState=" + mBackgroundCallState);
             pw.println("mVoLteServiceState=" + mVoLteServiceState);
             pw.println("mPhoneCapability=" + mPhoneCapability);
+            pw.println("mPreferredDataSubId=" + mPreferredDataSubId);
 
             pw.decreaseIndent();
 
@@ -1647,6 +1682,7 @@
         intent.putExtras(data);
         // Pass the subscription along with the intent.
         intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
+        intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
         intent.putExtra(PhoneConstants.SLOT_KEY, phoneId);
         mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
@@ -1701,6 +1737,7 @@
         if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
             intent.setAction(PhoneConstants.ACTION_SUBSCRIPTION_PHONE_STATE_CHANGED);
             intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
+            intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
         }
         // If the phoneId is invalid, the broadcast is for overall call state.
         if (phoneId != SubscriptionManager.INVALID_PHONE_INDEX) {
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/events/StoppedDragingEvent.java b/services/core/java/com/android/server/UiModeManagerInternal.java
similarity index 63%
copy from packages/SystemUI/src/com/android/systemui/stackdivider/events/StoppedDragingEvent.java
copy to services/core/java/com/android/server/UiModeManagerInternal.java
index c50d6d6..ef29069 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/events/StoppedDragingEvent.java
+++ b/services/core/java/com/android/server/UiModeManagerInternal.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 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.
@@ -11,15 +11,17 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
  */
 
-package com.android.systemui.stackdivider.events;
-
-import com.android.systemui.recents.events.EventBus;
+package com.android.server;
 
 /**
- * Sent when the divider isn't draging anymore.
+ * UiModeManager local system service interface.
+ *
+ * @hide Only for use within the system server.
  */
-public class StoppedDragingEvent extends EventBus.Event {
+public abstract class UiModeManagerInternal {
+
+    public abstract boolean isNightMode();
 }
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index f436286..5538e72 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -108,6 +108,8 @@
 
     private PowerManager.WakeLock mWakeLock;
 
+    private final LocalService mLocalService = new LocalService();
+
     public UiModeManagerService(Context context) {
         super(context);
     }
@@ -242,6 +244,7 @@
 
         }, TAG + ".onStart");
         publishBinderService(Context.UI_MODE_SERVICE, mService);
+        publishLocalService(UiModeManagerInternal.class, mLocalService);
     }
 
     private final IUiModeManager.Stub mService = new IUiModeManager.Stub() {
@@ -367,7 +370,8 @@
             pw.println("Current UI Mode Service state:");
             pw.print("  mDockState="); pw.print(mDockState);
                     pw.print(" mLastBroadcastState="); pw.println(mLastBroadcastState);
-            pw.print("  mNightMode="); pw.print(mNightMode);
+            pw.print("  mNightMode="); pw.print(mNightMode); pw.print(" (");
+                    pw.print(Shell.nightModeToStr(mNightMode)); pw.print(") ");
                     pw.print(" mNightModeLocked="); pw.print(mNightModeLocked);
                     pw.print(" mCarModeEnabled="); pw.print(mCarModeEnabled);
                     pw.print(" mComputedNightMode="); pw.print(mComputedNightMode);
@@ -839,4 +843,22 @@
             }
         }
     }
+
+    public final class LocalService extends UiModeManagerInternal {
+
+        @Override
+        public boolean isNightMode() {
+            synchronized (mLock) {
+                final boolean isIt = (mConfiguration.uiMode & Configuration.UI_MODE_NIGHT_YES) != 0;
+                if (LOG) {
+                    Slog.d(TAG,
+                        "LocalService.isNightMode(): mNightMode=" + mNightMode
+                        + "; mComputedNightMode=" + mComputedNightMode
+                        + "; uiMode=" + mConfiguration.uiMode
+                        + "; isIt=" + isIt);
+                }
+                return isIt;
+            }
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 6d69fcd..0b836f0 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -94,7 +94,7 @@
         "media.metrics", // system/bin/mediametrics
         "media.codec", // vendor/bin/hw/android.hardware.media.omx@1.0-service
         "com.android.bluetooth",  // Bluetooth service
-        "statsd",  // Stats daemon
+        "/system/bin/statsd",  // Stats daemon
     };
 
     public static final List<String> HAL_INTERFACES_OF_INTEREST = Arrays.asList(
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 510d333..461d39d 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -629,7 +629,7 @@
                 return false;
             }
 
-            IIntentSender target = mAm.getIntentSenderLocked(
+            IIntentSender target = mAm.mPendingIntentController.getIntentSender(
                     ActivityManager.INTENT_SENDER_SERVICE, callingPackage,
                     callingUid, userId, null, null, 0, new Intent[]{service},
                     new String[]{service.resolveType(mAm.mContext.getContentResolver())},
diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java
index 01421c7..fab967c 100644
--- a/services/core/java/com/android/server/am/ActivityDisplay.java
+++ b/services/core/java/com/android/server/am/ActivityDisplay.java
@@ -890,6 +890,8 @@
         mRemoved = true;
 
         releaseSelfIfNeeded();
+
+        mSupervisor.getKeyguardController().onDisplayRemoved(mDisplayId);
     }
 
     private void releaseSelfIfNeeded() {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 8c7fc84..f49c50a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -134,7 +134,6 @@
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SERVICE;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SWITCH;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_UID_OBSERVERS;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_URI_PERMISSION;
 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.ActivityStackSupervisor.PRESERVE_WINDOWS;
@@ -369,7 +368,6 @@
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.io.UnsupportedEncodingException;
-import java.lang.ref.WeakReference;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
@@ -417,7 +415,6 @@
     private static final String TAG_SERVICE = TAG + POSTFIX_SERVICE;
     private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
     private static final String TAG_UID_OBSERVERS = TAG + POSTFIX_UID_OBSERVERS;
-    private static final String TAG_URI_PERMISSION = TAG + POSTFIX_URI_PERMISSION;
 
     // Mock "pretend we're idle now" broadcast action to the job scheduler; declared
     // here so that while the job scheduler can depend on AMS, the other way around
@@ -563,6 +560,7 @@
     String mDeviceOwnerName;
 
     final UserController mUserController;
+    final PendingIntentController mPendingIntentController;
 
     final AppErrors mAppErrors;
 
@@ -821,12 +819,6 @@
     final SparseArray<UidRecord> mValidateUids = new SparseArray<>();
 
     /**
-     * Set of IntentSenderRecord objects that are currently active.
-     */
-    final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
-            = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
-
-    /**
      * Fingerprints (hashCode()) of stack traces that we've
      * already logged DropBox entries for.  Guarded by itself.  If
      * something (rogue user app) forces this over
@@ -1426,7 +1418,6 @@
     static final int UPDATE_TIME_ZONE = 13;
     static final int PROC_START_TIMEOUT_MSG = 20;
     static final int KILL_APPLICATION_MSG = 22;
-    static final int FINALIZE_PENDING_INTENT_MSG = 23;
     static final int SHOW_STRICT_MODE_VIOLATION_UI_MSG = 26;
     static final int CHECK_EXCESSIVE_POWER_USE_MSG = 27;
     static final int CLEAR_DNS_CACHE_MSG = 28;
@@ -1445,7 +1436,6 @@
     static final int IDLE_UIDS_MSG = 58;
     static final int HANDLE_TRUST_STORAGE_UPDATE_MSG = 63;
     static final int SERVICE_FOREGROUND_TIMEOUT_MSG = 66;
-    static final int DISPATCH_PENDING_INTENT_CANCEL_MSG = 67;
     static final int PUSH_TEMP_WHITELIST_UI_MSG = 68;
     static final int SERVICE_FOREGROUND_CRASH_MSG = 69;
     static final int DISPATCH_OOM_ADJ_OBSERVER_MSG = 70;
@@ -1644,21 +1634,6 @@
                 mServices.serviceForegroundCrash(
                     (ProcessRecord) msg.obj, msg.getData().getCharSequence(SERVICE_RECORD_KEY));
             } break;
-            case DISPATCH_PENDING_INTENT_CANCEL_MSG: {
-                RemoteCallbackList<IResultReceiver> callbacks
-                        = (RemoteCallbackList<IResultReceiver>)msg.obj;
-                int N = callbacks.beginBroadcast();
-                for (int i = 0; i < N; i++) {
-                    try {
-                        callbacks.getBroadcastItem(i).send(Activity.RESULT_CANCELED, null);
-                    } catch (RemoteException e) {
-                    }
-                }
-                callbacks.finishBroadcast();
-                // We have to clean up the RemoteCallbackList here, because otherwise it will
-                // needlessly hold the enclosed callbacks until the remote process dies.
-                callbacks.kill();
-            } break;
             case UPDATE_TIME_ZONE: {
                 synchronized (ActivityManagerService.this) {
                     for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
@@ -1738,9 +1713,6 @@
                             false, userId, reason);
                 }
             } break;
-            case FINALIZE_PENDING_INTENT_MSG: {
-                ((PendingIntentRecord)msg.obj).completeFinalize();
-            } break;
             case CHECK_EXCESSIVE_POWER_USE_MSG: {
                 synchronized (ActivityManagerService.this) {
                     checkExcessivePowerUsageLocked();
@@ -2354,6 +2326,7 @@
         mSystemThread = null;
         mUiHandler = injector.getUiHandler(null);
         mUserController = null;
+        mPendingIntentController = null;
         mProcStartHandlerThread = null;
         mProcStartHandler = null;
         mHiddenApiBlacklist = null;
@@ -2407,7 +2380,8 @@
         final File systemDir = SystemServiceManager.ensureSystemDir();
 
         // TODO: Move creation of battery stats service outside of activity manager service.
-        mBatteryStatsService = new BatteryStatsService(systemContext, systemDir, mHandler);
+        mBatteryStatsService = new BatteryStatsService(systemContext, systemDir,
+                BackgroundThread.get().getHandler());
         mBatteryStatsService.getActiveStatistics().readLocked();
         mBatteryStatsService.scheduleWriteToDisk();
         mOnBattery = DEBUG_POWER ? true
@@ -2423,6 +2397,9 @@
 
         mUserController = new UserController(this);
 
+        mPendingIntentController = new PendingIntentController(
+                mHandlerThread.getLooper(), mUserController);
+
         GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
             ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
 
@@ -2508,6 +2485,7 @@
         LocalServices.addService(ActivityManagerInternal.class, new LocalService());
         mActivityTaskManager.onActivityManagerInternalAdded();
         mUgmInternal.onActivityManagerInternalAdded();
+        mPendingIntentController.onActivityManagerInternalAdded();
         // Wait for the synchronized block started in mProcessCpuThread,
         // so that any other access to mProcessCpuTracker from main thread
         // will be blocked during mProcessCpuTracker initialization.
@@ -3559,6 +3537,9 @@
             String seInfo, String requiredAbi, String instructionSet, String invokeWith,
             long startTime) {
         try {
+            final String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
+            final String[] visibleVolIds = LocalServices.getService(StorageManagerInternal.class)
+                    .getVisibleVolumesForUser(UserHandle.getUserId(uid));
             Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                     app.processName);
             checkTime(startTime, "startProcess: asking zygote to start proc");
@@ -3568,12 +3549,14 @@
                         app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                         app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                         app.info.dataDir, null, app.info.packageName,
+                        packageNames, visibleVolIds,
                         new String[] {PROC_START_SEQ_IDENT + app.startSeq});
             } else {
                 startResult = Process.start(entryPoint,
                         app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                         app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                         app.info.dataDir, invokeWith, app.info.packageName,
+                        packageNames, visibleVolIds,
                         new String[] {PROC_START_SEQ_IDENT + app.startSeq});
             }
             checkTime(startTime, "startProcess: returned from zygote!");
@@ -5511,55 +5494,8 @@
         }
 
         if (packageName == null || uninstalling) {
-            // Remove pending intents.  For now we only do this when force
-            // stopping users, because we have some problems when doing this
-            // for packages -- app widgets are not currently cleaned up for
-            // such packages, so they can be left with bad pending intents.
-            if (mIntentSenderRecords.size() > 0) {
-                Iterator<WeakReference<PendingIntentRecord>> it
-                        = mIntentSenderRecords.values().iterator();
-                while (it.hasNext()) {
-                    WeakReference<PendingIntentRecord> wpir = it.next();
-                    if (wpir == null) {
-                        it.remove();
-                        continue;
-                    }
-                    PendingIntentRecord pir = wpir.get();
-                    if (pir == null) {
-                        it.remove();
-                        continue;
-                    }
-                    if (packageName == null) {
-                        // Stopping user, remove all objects for the user.
-                        if (pir.key.userId != userId) {
-                            // Not the same user, skip it.
-                            continue;
-                        }
-                    } else {
-                        if (UserHandle.getAppId(pir.uid) != appId) {
-                            // Different app id, skip it.
-                            continue;
-                        }
-                        if (userId != UserHandle.USER_ALL && pir.key.userId != userId) {
-                            // Different user, skip it.
-                            continue;
-                        }
-                        if (!pir.key.packageName.equals(packageName)) {
-                            // Different package, skip it.
-                            continue;
-                        }
-                    }
-                    if (!doit) {
-                        return true;
-                    }
-                    didSomething = true;
-                    it.remove();
-                    makeIntentSenderCanceledLocked(pir);
-                    if (pir.key.activity != null && pir.key.activity.pendingResults != null) {
-                        pir.key.activity.pendingResults.remove(pir.ref);
-                    }
-                }
-            }
+            didSomething |= mPendingIntentController.removePendingIntentsForPackage(
+                    packageName, userId, appId, doit);
         }
 
         if (doit) {
@@ -6342,90 +6278,19 @@
                     }
                 }
 
-                return getIntentSenderLocked(type, packageName, callingUid, userId,
-                        token, resultWho, requestCode, intents, resolvedTypes, flags, bOptions);
-
+                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);
             }
         }
     }
 
-    IIntentSender getIntentSenderLocked(int type, String packageName,
-            int callingUid, int userId, IBinder token, String resultWho,
-            int requestCode, Intent[] intents, String[] resolvedTypes, int flags,
-            Bundle bOptions) {
-        if (DEBUG_MU) Slog.v(TAG_MU, "getIntentSenderLocked(): uid=" + callingUid);
-        ActivityRecord activity = null;
-        if (type == ActivityManager.INTENT_SENDER_ACTIVITY_RESULT) {
-            activity = ActivityRecord.isInStackLocked(token);
-            if (activity == null) {
-                Slog.w(TAG, "Failed createPendingResult: activity " + token + " not in any stack");
-                return null;
-            }
-            if (activity.finishing) {
-                Slog.w(TAG, "Failed createPendingResult: activity " + activity + " is finishing");
-                return null;
-            }
-        }
-
-        // We're going to be splicing together extras before sending, so we're
-        // okay poking into any contained extras.
-        if (intents != null) {
-            for (int i = 0; i < intents.length; i++) {
-                intents[i].setDefusable(true);
-            }
-        }
-        Bundle.setDefusable(bOptions, true);
-
-        final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
-        final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
-        final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
-        flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
-                |PendingIntent.FLAG_UPDATE_CURRENT);
-
-        PendingIntentRecord.Key key = new PendingIntentRecord.Key(type, packageName, activity,
-                resultWho, requestCode, intents, resolvedTypes, flags,
-                SafeActivityOptions.fromBundle(bOptions), userId);
-        WeakReference<PendingIntentRecord> ref;
-        ref = mIntentSenderRecords.get(key);
-        PendingIntentRecord rec = ref != null ? ref.get() : null;
-        if (rec != null) {
-            if (!cancelCurrent) {
-                if (updateCurrent) {
-                    if (rec.key.requestIntent != null) {
-                        rec.key.requestIntent.replaceExtras(intents != null ?
-                                intents[intents.length - 1] : null);
-                    }
-                    if (intents != null) {
-                        intents[intents.length-1] = rec.key.requestIntent;
-                        rec.key.allIntents = intents;
-                        rec.key.allResolvedTypes = resolvedTypes;
-                    } else {
-                        rec.key.allIntents = null;
-                        rec.key.allResolvedTypes = null;
-                    }
-                }
-                return rec;
-            }
-            makeIntentSenderCanceledLocked(rec);
-            mIntentSenderRecords.remove(key);
-        }
-        if (noCreate) {
-            return rec;
-        }
-        rec = new PendingIntentRecord(this, key, callingUid);
-        mIntentSenderRecords.put(key, rec.ref);
-        if (type == ActivityManager.INTENT_SENDER_ACTIVITY_RESULT) {
-            if (activity.pendingResults == null) {
-                activity.pendingResults
-                        = new HashSet<WeakReference<PendingIntentRecord>>();
-            }
-            activity.pendingResults.add(rec.ref);
-        }
-        return rec;
-    }
-
     @Override
     public int sendIntentSender(IIntentSender target, IBinder whitelistToken, int code,
             Intent intent, String resolvedType,
@@ -6465,44 +6330,7 @@
 
     @Override
     public void cancelIntentSender(IIntentSender sender) {
-        if (!(sender instanceof PendingIntentRecord)) {
-            return;
-        }
-        synchronized(this) {
-            PendingIntentRecord rec = (PendingIntentRecord)sender;
-            try {
-                final int uid = AppGlobals.getPackageManager().getPackageUid(rec.key.packageName,
-                        MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getCallingUserId());
-                if (!UserHandle.isSameApp(uid, Binder.getCallingUid())) {
-                    String msg = "Permission Denial: cancelIntentSender() from pid="
-                        + Binder.getCallingPid()
-                        + ", uid=" + Binder.getCallingUid()
-                        + " is not allowed to cancel package "
-                        + rec.key.packageName;
-                    Slog.w(TAG, msg);
-                    throw new SecurityException(msg);
-                }
-            } catch (RemoteException e) {
-                throw new SecurityException(e);
-            }
-            cancelIntentSenderLocked(rec, true);
-        }
-    }
-
-    void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
-        makeIntentSenderCanceledLocked(rec);
-        mIntentSenderRecords.remove(rec.key);
-        if (cleanActivity && rec.key.activity != null) {
-            rec.key.activity.pendingResults.remove(rec.ref);
-        }
-    }
-
-    void makeIntentSenderCanceledLocked(PendingIntentRecord rec) {
-        rec.canceled = true;
-        RemoteCallbackList<IResultReceiver> callbacks = rec.detachCancelListenersLocked();
-        if (callbacks != null) {
-            mHandler.obtainMessage(DISPATCH_PENDING_INTENT_CANCEL_MSG, callbacks).sendToTarget();
-        }
+        mPendingIntentController.cancelIntentSender(sender);
     }
 
     @Override
@@ -7813,7 +7641,23 @@
                 }
             }
 
-            boolean providerRunning = cpr != null && cpr.proc != null && !cpr.proc.killed;
+            boolean providerRunning = false;
+
+            if (cpr != null && cpr.proc != null) {
+                providerRunning = !cpr.proc.killed;
+
+                // Note if killedByAm is also set, this means the provider process has just been
+                // killed by AM (in ProcessRecord.kill()), but appDiedLocked() hasn't been called
+                // yet. So we need to call appDiedLocked() here and let it clean up.
+                // (See the commit message on I2c4ba1e87c2d47f2013befff10c49b3dc337a9a7 to see
+                // how to test this case.)
+                if (cpr.proc.killed && cpr.proc.killedByAm) {
+                    checkTime(startTime, "getContentProviderImpl: before appDied (killedByAm)");
+                    appDiedLocked(cpr.proc);
+                    checkTime(startTime, "getContentProviderImpl: after appDied (killedByAm)");
+                }
+            }
+
             if (providerRunning) {
                 cpi = cpr.info;
                 String msg;
@@ -9607,9 +9451,10 @@
 
         mBatteryStatsService.noteWakupAlarm(sourcePkg, sourceUid, workSource, tag);
         if (workSource != null) {
-            StatsLog.write(StatsLog.WAKEUP_ALARM_OCCURRED, workSource, tag);
+            StatsLog.write(StatsLog.WAKEUP_ALARM_OCCURRED, workSource, tag, sourcePkg);
         } else {
-            StatsLog.write_non_chained(StatsLog.WAKEUP_ALARM_OCCURRED, sourceUid, null, tag);
+            StatsLog.write_non_chained(StatsLog.WAKEUP_ALARM_OCCURRED, sourceUid, null, tag,
+                    sourcePkg);
         }
     }
 
@@ -10866,7 +10711,7 @@
                 pw.println("-------------------------------------------------------------------------------");
 
             }
-            dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
+            mPendingIntentController.dumpPendingIntents(pw, dumpAll, dumpPackage);
             pw.println();
             if (dumpAll) {
                 pw.println("-------------------------------------------------------------------------------");
@@ -11159,7 +11004,7 @@
                     opti++;
                 }
                 synchronized (this) {
-                    dumpPendingIntentsLocked(fd, pw, args, opti, true, dumpPackage);
+                    mPendingIntentController.dumpPendingIntents(pw, true, dumpPackage);
                 }
             } else if ("processes".equals(cmd) || "p".equals(cmd)) {
                 if (opti < args.length) {
@@ -12857,61 +12702,6 @@
         mUgmInternal.dump(pw, dumpAll, dumpPackage);
     }
 
-    void dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
-            int opti, boolean dumpAll, String dumpPackage) {
-        boolean printed = false;
-
-        pw.println("ACTIVITY MANAGER PENDING INTENTS (dumpsys activity intents)");
-
-        if (mIntentSenderRecords.size() > 0) {
-            // Organize these by package name, so they are easier to read.
-            final ArrayMap<String, ArrayList<PendingIntentRecord>> byPackage = new ArrayMap<>();
-            final ArrayList<WeakReference<PendingIntentRecord>> weakRefs = new ArrayList<>();
-            final Iterator<WeakReference<PendingIntentRecord>> it
-                    = mIntentSenderRecords.values().iterator();
-            while (it.hasNext()) {
-                WeakReference<PendingIntentRecord> ref = it.next();
-                PendingIntentRecord rec = ref != null ? ref.get() : null;
-                if (rec == null) {
-                    weakRefs.add(ref);
-                    continue;
-                }
-                if (dumpPackage != null && !dumpPackage.equals(rec.key.packageName)) {
-                    continue;
-                }
-                ArrayList<PendingIntentRecord> list = byPackage.get(rec.key.packageName);
-                if (list == null) {
-                    list = new ArrayList<>();
-                    byPackage.put(rec.key.packageName, list);
-                }
-                list.add(rec);
-            }
-            for (int i = 0; i < byPackage.size(); i++) {
-                ArrayList<PendingIntentRecord> intents = byPackage.valueAt(i);
-                printed = true;
-                pw.print("  * "); pw.print(byPackage.keyAt(i));
-                pw.print(": "); pw.print(intents.size()); pw.println(" items");
-                for (int j = 0; j < intents.size(); j++) {
-                    pw.print("    #"); pw.print(j); pw.print(": "); pw.println(intents.get(j));
-                    if (dumpAll) {
-                        intents.get(j).dump(pw, "      ");
-                    }
-                }
-            }
-            if (weakRefs.size() > 0) {
-                printed = true;
-                pw.println("  * WEAK REFS:");
-                for (int i = 0; i < weakRefs.size(); i++) {
-                    pw.print("    #"); pw.print(i); pw.print(": "); pw.println(weakRefs.get(i));
-                }
-            }
-        }
-
-        if (!printed) {
-            pw.println("  (nothing)");
-        }
-    }
-
     private static final int dumpProcessList(PrintWriter pw,
             ActivityManagerService service, List list,
             String prefix, String normalLabel, String persistentLabel,
@@ -15186,24 +14976,6 @@
         }
     }
 
-    ComponentName startServiceInPackage(int uid, Intent service, String resolvedType,
-            boolean fgRequired, String callingPackage, int userId)
-            throws TransactionTooLargeException {
-        synchronized(this) {
-            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
-                    "startServiceInPackage: " + service + " type=" + resolvedType);
-            final long origId = Binder.clearCallingIdentity();
-            ComponentName res;
-            try {
-                res = mServices.startServiceLocked(null, service,
-                        resolvedType, -1, uid, fgRequired, callingPackage, userId);
-            } finally {
-                Binder.restoreCallingIdentity(origId);
-            }
-            return res;
-        }
-    }
-
     @Override
     public int stopService(IApplicationThread caller, Intent service,
             String resolvedType, int userId) {
@@ -20892,7 +20664,8 @@
                                     memoryStat.pgmajfault,
                                     memoryStat.rssInBytes,
                                     memoryStat.cacheInBytes,
-                                    memoryStat.swapInBytes);
+                                    memoryStat.swapInBytes,
+                                    memoryStat.rssHighWatermarkInBytes);
                     processMemoryStates.add(processMemoryState);
                 }
             }
@@ -21091,6 +20864,46 @@
         public void finishBooting() {
             ActivityManagerService.this.finishBooting();
         }
+
+        @Override
+        public void tempWhitelistForPendingIntent(int callerPid, int callerUid, int targetUid,
+                long duration, String tag) {
+            synchronized (ActivityManagerService.this) {
+                ActivityManagerService.this.tempWhitelistForPendingIntentLocked(
+                        callerPid, callerUid, targetUid, duration, tag);
+            }
+        }
+
+        @Override
+        public int broadcastIntentInPackage(String packageName, int uid, Intent intent,
+                String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData,
+                Bundle resultExtras, String requiredPermission, Bundle bOptions, boolean serialized,
+                boolean sticky, int userId) {
+            synchronized (ActivityManagerService.this) {
+                return ActivityManagerService.this.broadcastIntentInPackage(packageName, uid,
+                        intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
+                        requiredPermission, bOptions, serialized, sticky, userId);
+            }
+        }
+
+        @Override
+        public ComponentName startServiceInPackage(int uid, Intent service, String resolvedType,
+                boolean fgRequired, String callingPackage, int userId)
+                throws TransactionTooLargeException {
+            synchronized(ActivityManagerService.this) {
+                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
+                        "startServiceInPackage: " + service + " type=" + resolvedType);
+                final long origId = Binder.clearCallingIdentity();
+                ComponentName res;
+                try {
+                    res = mServices.startServiceLocked(null, service,
+                            resolvedType, -1, uid, fgRequired, callingPackage, userId);
+                } finally {
+                    Binder.restoreCallingIdentity(origId);
+                }
+                return res;
+            }
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
index 263c34f..78b42f2 100644
--- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
@@ -3,13 +3,13 @@
 import static android.app.ActivityManager.START_SUCCESS;
 import static android.app.ActivityManager.START_TASK_TO_FRONT;
 import static android.app.ActivityManager.processStateAmToProto;
-import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_TIMEOUT;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 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.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_ACTIVITY_START;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_BIND_APPLICATION_DELAY_MS;
@@ -28,9 +28,9 @@
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_IS_NO_DISPLAY;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_IS_VISIBLE;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_IS_VISIBLE_IGNORING_KEYGUARD;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_LAUNCH_MODE;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_LAUNCH;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_VISIBLE;
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_LAUNCH_MODE;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_PROCESS_NAME;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_REAL_ACTIVITY;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_RESULT_TO_PKG_NAME;
@@ -57,16 +57,16 @@
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_PENDING_UI_CLEAN;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_PROCESS_NAME;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_REAL_CALLING_UID;
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_REAL_CALLING_UID_PROC_STATE;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_REAL_CALLING_UID_HAS_ANY_VISIBLE_WINDOW;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_REAL_CALLING_UID_PROC_STATE;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_PACKAGE_NAME;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_SHORT_COMPONENT_NAME;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_UID;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_UID_HAS_ANY_VISIBLE_WINDOW;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_UID_PROC_STATE;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_WHITELIST_TAG;
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PACKAGE_OPTIMIZATION_COMPILATION_REASON;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PACKAGE_OPTIMIZATION_COMPILATION_FILTER;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PACKAGE_OPTIMIZATION_COMPILATION_REASON;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_COLD_LAUNCH;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_HOT_LAUNCH;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE;
@@ -77,6 +77,7 @@
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.am.MemoryStatUtil.MemoryStat;
 import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
+import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_TIMEOUT;
 
 import android.content.Context;
 import android.content.Intent;
@@ -98,8 +99,6 @@
 import com.android.internal.os.SomeArgs;
 import com.android.server.LocalServices;
 
-import java.util.ArrayList;
-
 /**
  * Handles logging into Tron.
  */
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 35a1eb8..9f59bd8 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -2450,13 +2450,24 @@
         if (shouldSleepOrShutDownActivities()
                 && mLastPausedActivity == next
                 && mStackSupervisor.allPausedActivitiesComplete()) {
-            // Make sure we have executed any pending transitions, since there
-            // should be nothing left to do at this point.
-            executeAppTransition(options);
-            if (DEBUG_STATES) Slog.d(TAG_STATES,
-                    "resumeTopActivityLocked: Going to sleep and all paused");
-            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
-            return false;
+            // If the current top activity may be able to occlude keyguard but the occluded state
+            // has not been set, update visibility and check again if we should continue to resume.
+            boolean nothingToResume = true;
+            if (!mService.mShuttingDown && !mTopActivityOccludesKeyguard
+                    && next.canShowWhenLocked()) {
+                ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */,
+                        !PRESERVE_WINDOWS);
+                nothingToResume = shouldSleepActivities();
+            }
+            if (nothingToResume) {
+                // Make sure we have executed any pending transitions, since there
+                // should be nothing left to do at this point.
+                executeAppTransition(options);
+                if (DEBUG_STATES) Slog.d(TAG_STATES,
+                        "resumeTopActivityLocked: Going to sleep and all paused");
+                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
+                return false;
+            }
         }
 
         // Make sure that the user who owns this activity is started.  If not,
@@ -4144,7 +4155,7 @@
             for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
                 PendingIntentRecord rec = apr.get();
                 if (rec != null) {
-                    mService.mAm.cancelIntentSenderLocked(rec, false);
+                    mService.mPendingIntentController.cancelIntentSender(rec, false);
                 }
             }
             r.pendingResults = null;
diff --git a/services/core/java/com/android/server/am/ActivityStartInterceptor.java b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
index 177e2f5..1fb8f87 100644
--- a/services/core/java/com/android/server/am/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
@@ -126,7 +126,7 @@
 
     private IntentSender createIntentSenderForOriginalIntent(int callingUid, int flags) {
         Bundle activityOptions = deferCrossProfileAppsAnimationIfNecessary();
-        final IIntentSender target = mService.mAm.getIntentSenderLocked(
+        final IIntentSender target = mService.getIntentSenderLocked(
                 INTENT_SENDER_ACTIVITY, mCallingPackage, callingUid, mUserId, null /*token*/,
                 null /*resultCode*/, 0 /*requestCode*/,
                 new Intent[] { mIntent }, new String[] { mResolvedType },
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 7da0519..890aafe 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -783,7 +783,7 @@
         if (aInfo != null) {
             if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
                     aInfo.packageName, userId)) {
-                IIntentSender target = mService.mAm.getIntentSenderLocked(
+                IIntentSender target = mService.getIntentSenderLocked(
                         ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
                         callingUid, userId, null, null, 0, new Intent[]{intent},
                         new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
@@ -1096,7 +1096,7 @@
                             }
                         }
 
-                        IIntentSender target = mService.mAm.getIntentSenderLocked(
+                        IIntentSender target = mService.getIntentSenderLocked(
                                 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
                                 appCallingUid, userId, null, null, 0, new Intent[] { intent },
                                 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerService.java b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
index 4dc2851..36261b5 100644
--- a/services/core/java/com/android/server/am/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
@@ -239,7 +239,9 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
 
@@ -276,6 +278,7 @@
     UriGrantsManagerInternal mUgmInternal;
     private PackageManagerInternal mPmInternal;
     private ActivityTaskManagerInternal mInternal;
+    PendingIntentController mPendingIntentController;
     /* Global service lock used by the package the owns this service. */
     Object mGlobalLock;
     ActivityStackSupervisor mStackSupervisor;
@@ -628,6 +631,7 @@
         final File systemDir = SystemServiceManager.ensureSystemDir();
         mAppWarnings = new AppWarnings(this, mUiContext, mH, mUiHandler, systemDir);
         mCompatModePackages = new CompatModePackages(this, systemDir, mH);
+        mPendingIntentController = mAm.mPendingIntentController;
 
         mTempConfig.setToDefaults();
         mTempConfig.setLocales(LocaleList.getDefault());
@@ -1956,10 +1960,12 @@
             final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
             if (task == null) {
                 Slog.d(TAG, "Could not find task for id: "+ taskId);
+                SafeActivityOptions.abort(options);
                 return;
             }
             if (getLockTaskController().isLockTaskModeViolation(task)) {
                 Slog.e(TAG, "moveTaskToFront: Attempt to violate Lock Task Mode");
+                SafeActivityOptions.abort(options);
                 return;
             }
             ActivityOptions realOptions = options != null
@@ -1979,7 +1985,6 @@
         } finally {
             Binder.restoreCallingIdentity(origId);
         }
-        SafeActivityOptions.abort(options);
     }
 
     boolean checkAppSwitchAllowedLocked(int sourcePid, int sourceUid,
@@ -5019,6 +5024,39 @@
 
     }
 
+    IIntentSender getIntentSenderLocked(int type, String packageName, int callingUid, int userId,
+            IBinder token, String resultWho, int requestCode, Intent[] intents,
+            String[] resolvedTypes, int flags, Bundle bOptions) {
+
+        ActivityRecord activity = null;
+        if (type == ActivityManager.INTENT_SENDER_ACTIVITY_RESULT) {
+            activity = ActivityRecord.isInStackLocked(token);
+            if (activity == null) {
+                Slog.w(TAG, "Failed createPendingResult: activity " + token + " not in any stack");
+                return null;
+            }
+            if (activity.finishing) {
+                Slog.w(TAG, "Failed createPendingResult: activity " + activity + " is finishing");
+                return null;
+            }
+        }
+
+        final PendingIntentRecord rec = mPendingIntentController.getIntentSender(type, packageName,
+                callingUid, userId, token, resultWho, requestCode, intents, resolvedTypes, flags,
+                bOptions);
+        final boolean noCreate = (flags & PendingIntent.FLAG_NO_CREATE) != 0;
+        if (noCreate) {
+            return rec;
+        }
+        if (type == ActivityManager.INTENT_SENDER_ACTIVITY_RESULT) {
+            if (activity.pendingResults == null) {
+                activity.pendingResults = new HashSet<>();
+            }
+            activity.pendingResults.add(rec.ref);
+        }
+        return rec;
+    }
+
     // TODO(b/111541062): Update app time tracking to make it aware of multiple resumed activities
     private void startTimeTrackingFocusedActivityLocked() {
         final ActivityRecord resumedActivity = mStackSupervisor.getTopResumedActivity();
@@ -5310,6 +5348,31 @@
         }
 
         @Override
+        public int startActivitiesInPackage(int uid, String callingPackage, Intent[] intents,
+                String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId,
+                boolean validateIncomingUser, PendingIntentRecord originatingPendingIntent) {
+            synchronized (mGlobalLock) {
+                return getActivityStartController().startActivitiesInPackage(uid, callingPackage,
+                        intents, resolvedTypes, resultTo, options, userId, validateIncomingUser,
+                        originatingPendingIntent);
+            }
+        }
+
+        @Override
+        public int startActivityInPackage(int uid, int realCallingPid, int realCallingUid,
+                String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
+                String resultWho, int requestCode, int startFlags, SafeActivityOptions options,
+                int userId, TaskRecord inTask, String reason, boolean validateIncomingUser,
+                PendingIntentRecord originatingPendingIntent) {
+            synchronized (mGlobalLock) {
+                return getActivityStartController().startActivityInPackage(uid, realCallingPid,
+                        realCallingUid, callingPackage, intent, resolvedType, resultTo, resultWho,
+                        requestCode, startFlags, options, userId, inTask, reason,
+                        validateIncomingUser, originatingPendingIntent);
+            }
+        }
+
+        @Override
         public int startActivityAsUser(IApplicationThread caller, String callerPacakge,
                 Intent intent, Bundle options, int userId) {
             return ActivityTaskManagerService.this.startActivityAsUser(
@@ -5684,5 +5747,39 @@
                 }
             });
         }
+
+        @Override
+        public void sendActivityResult(int callingUid, IBinder activityToken, String resultWho,
+                int requestCode, int resultCode, Intent data) {
+            synchronized (mGlobalLock) {
+                final ActivityRecord r = ActivityRecord.isInStackLocked(activityToken);
+                if (r != null && r.getStack() != null) {
+                    r.getStack().sendActivityResultLocked(callingUid, r, resultWho, requestCode,
+                            resultCode, data);
+                }
+            }
+        }
+
+        @Override
+        public void clearPendingResultForActivity(IBinder activityToken,
+                WeakReference<PendingIntentRecord> pir) {
+            synchronized (mGlobalLock) {
+                final ActivityRecord r = ActivityRecord.isInStackLocked(activityToken);
+                if (r != null && r.pendingResults != null) {
+                    r.pendingResults.remove(pir);
+                }
+            }
+        }
+
+        @Override
+        public IIntentSender getIntentSender(int type, String packageName,
+                int callingUid, int userId, IBinder token, String resultWho,
+                int requestCode, Intent[] intents, String[] resolvedTypes, int flags,
+                Bundle bOptions) {
+            synchronized (mGlobalLock) {
+                return getIntentSenderLocked(type, packageName, callingUid, userId, token,
+                        resultWho, requestCode, intents, resolvedTypes, flags, bOptions);
+            }
+        }
     }
 }
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 1387f45..e2035f6 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -741,7 +741,7 @@
 
         // Show a permission review UI only for explicit broadcast from a foreground app
         if (callerForeground && receiverRecord.intent.getComponent() != null) {
-            IIntentSender target = mService.getIntentSenderLocked(
+            IIntentSender target = mService.mPendingIntentController.getIntentSender(
                     ActivityManager.INTENT_SENDER_BROADCAST, receiverRecord.callerPackage,
                     receiverRecord.callingUid, receiverRecord.userId, null, null, 0,
                     new Intent[]{receiverRecord.intent},
@@ -1668,7 +1668,7 @@
 
     final boolean dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args,
             int opti, boolean dumpAll, String dumpPackage, boolean needSep) {
-        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
         if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
                 || mPendingBroadcast != null) {
             boolean printed = false;
diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java
index ee4e36f..cfe2829 100644
--- a/services/core/java/com/android/server/am/KeyguardController.java
+++ b/services/core/java/com/android/server/am/KeyguardController.java
@@ -29,16 +29,20 @@
 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
 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.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
-import static com.android.server.am.KeyguardControllerProto.KEYGUARD_OCCLUDED;
+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 android.os.IBinder;
 import android.os.RemoteException;
 import android.os.Trace;
 import android.util.Slog;
+import android.util.SparseArray;
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.policy.IKeyguardDismissCallback;
@@ -58,19 +62,18 @@
 
     private static final String TAG = TAG_WITH_CLASS_NAME ? "KeyguardController" : TAG_AM;
 
-    private final ActivityTaskManagerService mService;
     private final ActivityStackSupervisor mStackSupervisor;
     private WindowManagerService mWindowManager;
     private boolean mKeyguardShowing;
     private boolean mAodShowing;
     private boolean mKeyguardGoingAway;
-    private boolean mOccluded;
     private boolean mDismissalRequested;
-    private ActivityRecord mDismissingKeyguardActivity;
     private int mBeforeUnoccludeTransit;
     private int mVisibilityTransactionDepth;
-    private SleepToken mSleepToken;
+    // TODO(b/111955725): Support multiple external displays
     private int mSecondaryDisplayShowing = INVALID_DISPLAY;
+    private final SparseArray<KeyguardDisplayState> mDisplayStates = new SparseArray<>();
+    private final ActivityTaskManagerService mService;
 
     KeyguardController(ActivityTaskManagerService service,
             ActivityStackSupervisor stackSupervisor) {
@@ -87,8 +90,8 @@
      *         on the given display, false otherwise
      */
     boolean isKeyguardOrAodShowing(int displayId) {
-        return (mKeyguardShowing || mAodShowing) && !mKeyguardGoingAway &&
-                (displayId == DEFAULT_DISPLAY ? !mOccluded : displayId == mSecondaryDisplayShowing);
+        return (mKeyguardShowing || mAodShowing) && !mKeyguardGoingAway
+                && !isDisplayOccluded(displayId);
     }
 
     /**
@@ -96,8 +99,7 @@
      *         display, false otherwise
      */
     boolean isKeyguardShowing(int displayId) {
-        return mKeyguardShowing && !mKeyguardGoingAway &&
-                (displayId == DEFAULT_DISPLAY ? !mOccluded : displayId == mSecondaryDisplayShowing);
+        return mKeyguardShowing && !mKeyguardGoingAway && !isDisplayOccluded(displayId);
     }
 
     /**
@@ -133,6 +135,7 @@
         if (showingChanged) {
             dismissDockedStackIfNeeded();
             setKeyguardGoingAway(false);
+            // TODO(b/113840485): Check usage for non-default display
             mWindowManager.setKeyguardOrAodShowingOnDefaultDisplay(
                     isKeyguardOrAodShowing(DEFAULT_DISPLAY));
             if (keyguardShowing) {
@@ -248,7 +251,8 @@
         // already the dismissing activity, in which case we don't allow it to repeatedly dismiss
         // Keyguard.
         return dismissKeyguard && canDismissKeyguard() && !mAodShowing
-                && (mDismissalRequested || r != mDismissingKeyguardActivity);
+                && (mDismissalRequested
+                || getDisplay(r.getDisplayId()).mDismissingKeyguardActivity != r);
     }
 
     /**
@@ -259,44 +263,16 @@
     }
 
     private void visibilitiesUpdated() {
-        final boolean lastOccluded = mOccluded;
-        final ActivityRecord lastDismissingKeyguardActivity = mDismissingKeyguardActivity;
-        mOccluded = false;
-        mDismissingKeyguardActivity = null;
-
+        boolean requestDismissKeyguard = false;
         for (int displayNdx = mStackSupervisor.getChildCount() - 1; displayNdx >= 0; displayNdx--) {
             final ActivityDisplay display = mStackSupervisor.getChildAt(displayNdx);
-            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getChildAt(stackNdx);
-
-                // Only the top activity of the focused stack on the default display may control
-                // occluded state.
-                if (display.mDisplayId == DEFAULT_DISPLAY
-                        && mStackSupervisor.isTopDisplayFocusedStack(stack)) {
-
-                    // A dismissing activity occludes Keyguard in the insecure case for legacy
-                    // reasons.
-                    final ActivityRecord topDismissing = stack.getTopDismissingKeyguardActivity();
-                    mOccluded =
-                            stack.topActivityOccludesKeyguard()
-                                    || (topDismissing != null
-                                            && stack.topRunningActivityLocked() == topDismissing
-                                            && canShowWhileOccluded(
-                                                    true /* dismissKeyguard */,
-                                                    false /* showWhenLocked */));
-                }
-
-                if (mDismissingKeyguardActivity == null
-                        && stack.getTopDismissingKeyguardActivity() != null) {
-                    mDismissingKeyguardActivity = stack.getTopDismissingKeyguardActivity();
-                }
-            }
+            final KeyguardDisplayState state = getDisplay(display.mDisplayId);
+            state.visibilitiesUpdated(this, display);
+            requestDismissKeyguard |= state.mRequestDismissKeyguard;
         }
-        mOccluded |= mWindowManager.isShowingDream();
-        if (mOccluded != lastOccluded) {
-            handleOccludedChanged();
-        }
-        if (mDismissingKeyguardActivity != lastDismissingKeyguardActivity) {
+
+        // Dismissing Keyguard happens globally using the information from all displays.
+        if (requestDismissKeyguard) {
             handleDismissKeyguard();
         }
     }
@@ -305,7 +281,7 @@
      * Called when occluded state changed.
      */
     private void handleOccludedChanged() {
-        mWindowManager.onKeyguardOccludedChanged(mOccluded);
+        mWindowManager.onKeyguardOccludedChanged(isDisplayOccluded(DEFAULT_DISPLAY));
         if (isKeyguardLocked()) {
             mWindowManager.deferSurfaceLayout();
             try {
@@ -322,14 +298,13 @@
     }
 
     /**
-     * Called when somebody might want to dismiss the Keyguard.
+     * Called when somebody wants to dismiss the Keyguard via the flag.
      */
     private void handleDismissKeyguard() {
         // We only allow dismissing Keyguard via the flag when Keyguard is secure for legacy
         // reasons, because that's how apps used to dismiss Keyguard in the secure case. In the
         // insecure case, we actually show it on top of the lockscreen. See #canShowWhileOccluded.
-        if (!mOccluded && mDismissingKeyguardActivity != null
-                && mWindowManager.isKeyguardSecure()) {
+        if (mWindowManager.isKeyguardSecure()) {
             mWindowManager.dismissKeyguard(null /* callback */, null /* message */);
             mDismissalRequested = true;
 
@@ -345,6 +320,10 @@
         }
     }
 
+    private boolean isDisplayOccluded(int displayId) {
+        return getDisplay(displayId).mOccluded;
+    }
+
     /**
      * @return true if Keyguard can be currently dismissed without entering credentials.
      */
@@ -355,12 +334,14 @@
     private int resolveOccludeTransit() {
         if (mBeforeUnoccludeTransit != TRANSIT_UNSET
                 && mWindowManager.getPendingAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE
-                && mOccluded) {
+                // TODO(b/113840485): Handle app transition for individual display.
+                && isDisplayOccluded(DEFAULT_DISPLAY)) {
 
             // Reuse old transit in case we are occluding Keyguard again, meaning that we never
             // actually occclude/unocclude Keyguard, but just run a normal transition.
             return mBeforeUnoccludeTransit;
-        } else if (!mOccluded) {
+            // TODO(b/113840485): Handle app transition for individual display.
+        } else if (!isDisplayOccluded(DEFAULT_DISPLAY)) {
 
             // Save transit in case we dismiss/occlude Keyguard shortly after.
             mBeforeUnoccludeTransit = mWindowManager.getPendingAppTransition();
@@ -371,7 +352,8 @@
     }
 
     private void dismissDockedStackIfNeeded() {
-        if (mKeyguardShowing && mOccluded) {
+        // TODO(b/113840485): Handle docked stack for individual display.
+        if (mKeyguardShowing && isDisplayOccluded(DEFAULT_DISPLAY)) {
             // The lock screen is currently showing, but is occluded by a window that can
             // show on top of the lock screen. In this can we want to dismiss the docked
             // stack since it will be complicated/risky to try to put the activity on top
@@ -386,11 +368,116 @@
     }
 
     private void updateKeyguardSleepToken() {
-        if (mSleepToken == null && isKeyguardOrAodShowing(DEFAULT_DISPLAY)) {
-            mSleepToken = mService.acquireSleepToken("Keyguard", DEFAULT_DISPLAY);
-        } else if (mSleepToken != null && !isKeyguardOrAodShowing(DEFAULT_DISPLAY)) {
-            mSleepToken.release();
-            mSleepToken = null;
+        for (int displayNdx = mStackSupervisor.getChildCount() - 1; displayNdx >= 0; displayNdx--) {
+            final ActivityDisplay display = mStackSupervisor.getChildAt(displayNdx);
+            final KeyguardDisplayState state = getDisplay(display.mDisplayId);
+            if (isKeyguardOrAodShowing(display.mDisplayId) && state.mSleepToken == null) {
+                state.acquiredSleepToken();
+            } else if (!isKeyguardOrAodShowing(display.mDisplayId) && state.mSleepToken != null) {
+                state.releaseSleepToken();
+            }
+        }
+    }
+
+    private KeyguardDisplayState getDisplay(int displayId) {
+        if (mDisplayStates.get(displayId) == null) {
+            mDisplayStates.append(displayId,
+                    new KeyguardDisplayState(mService, displayId));
+        }
+        return mDisplayStates.get(displayId);
+    }
+
+    void onDisplayRemoved(int displayId) {
+        if (mDisplayStates.get(displayId) != null) {
+            mDisplayStates.get(displayId).onRemoved();
+            mDisplayStates.remove(displayId);
+        }
+    }
+
+    /** Represents Keyguard state per individual display. */
+    private static class KeyguardDisplayState {
+        private final int mDisplayId;
+        private boolean mOccluded;
+        private ActivityRecord mDismissingKeyguardActivity;
+        private boolean mRequestDismissKeyguard;
+        private final ActivityTaskManagerService mService;
+        private SleepToken mSleepToken;
+
+        KeyguardDisplayState(ActivityTaskManagerService service, int displayId) {
+            mService = service;
+            mDisplayId = displayId;
+        }
+
+        void onRemoved() {
+            mDismissingKeyguardActivity = null;
+            releaseSleepToken();
+        }
+
+        void acquiredSleepToken() {
+            if (mSleepToken == null) {
+                mSleepToken = mService.acquireSleepToken("keyguard", mDisplayId);
+            }
+        }
+
+        void releaseSleepToken() {
+            if (mSleepToken != null) {
+                mSleepToken.release();
+                mSleepToken = null;
+            }
+        }
+
+        void visibilitiesUpdated(KeyguardController controller, ActivityDisplay display) {
+            final boolean lastOccluded = mOccluded;
+            final ActivityRecord lastDismissActivity = mDismissingKeyguardActivity;
+            mRequestDismissKeyguard = false;
+            mOccluded = false;
+            mDismissingKeyguardActivity = null;
+
+            // Only the top activity of the focused stack on each display may control it's
+            // occluded state.
+            final ActivityStack focusedStack = display.getFocusedStack();
+            if (focusedStack != null) {
+                final ActivityRecord topDismissing =
+                        focusedStack.getTopDismissingKeyguardActivity();
+                mOccluded = focusedStack.topActivityOccludesKeyguard() || (topDismissing != null
+                                && focusedStack.topRunningActivityLocked() == topDismissing
+                                && controller.canShowWhileOccluded(
+                                true /* dismissKeyguard */,
+                                false /* showWhenLocked */));
+                if (focusedStack.getTopDismissingKeyguardActivity() != null) {
+                    mDismissingKeyguardActivity = focusedStack.getTopDismissingKeyguardActivity();
+                }
+                mOccluded |= controller.mWindowManager.isShowingDream();
+            }
+
+            // TODO(b/113840485): Handle app transition for individual display.
+            // For now, only default display can change occluded.
+            if (lastOccluded != mOccluded && mDisplayId == DEFAULT_DISPLAY) {
+                controller.handleOccludedChanged();
+            }
+            if (lastDismissActivity != mDismissingKeyguardActivity && !mOccluded
+                    && mDismissingKeyguardActivity != null
+                    && controller.mWindowManager.isKeyguardSecure()) {
+                mRequestDismissKeyguard = true;
+            }
+        }
+
+        void dumpStatus(PrintWriter pw, String prefix) {
+            final StringBuilder sb = new StringBuilder();
+            sb.append(prefix);
+            sb.append("  Occluded=").append(mOccluded)
+                    .append(" DismissingKeyguardActivity=")
+                    .append(mDismissingKeyguardActivity)
+                    .append(" at display=")
+                    .append(mDisplayId);
+            pw.println(sb.toString());
+        }
+
+        void writeToProto(ProtoOutputStream proto, long fieldId) {
+            final long token = proto.start(fieldId);
+            proto.write(DISPLAY_ID, mDisplayId);
+            proto.write(KEYGUARD_OCCLUDED, mOccluded);
+            proto.end(token);
         }
     }
 
@@ -399,8 +486,7 @@
         pw.println(prefix + "  mKeyguardShowing=" + mKeyguardShowing);
         pw.println(prefix + "  mAodShowing=" + mAodShowing);
         pw.println(prefix + "  mKeyguardGoingAway=" + mKeyguardGoingAway);
-        pw.println(prefix + "  mOccluded=" + mOccluded);
-        pw.println(prefix + "  mDismissingKeyguardActivity=" + mDismissingKeyguardActivity);
+        dumpDisplayStates(pw, prefix);
         pw.println(prefix + "  mDismissalRequested=" + mDismissalRequested);
         pw.println(prefix + "  mVisibilityTransactionDepth=" + mVisibilityTransactionDepth);
     }
@@ -408,7 +494,19 @@
     void writeToProto(ProtoOutputStream proto, long fieldId) {
         final long token = proto.start(fieldId);
         proto.write(KEYGUARD_SHOWING, mKeyguardShowing);
-        proto.write(KEYGUARD_OCCLUDED, mOccluded);
+        writeDisplayStatesToProto(proto, KEYGUARD_OCCLUDED_STATES);
         proto.end(token);
     }
+
+    private void dumpDisplayStates(PrintWriter pw, String prefix) {
+        for (int i = 0; i < mDisplayStates.size(); i++) {
+            mDisplayStates.valueAt(i).dumpStatus(pw, prefix);
+        }
+    }
+
+    private void writeDisplayStatesToProto(ProtoOutputStream proto, long fieldId) {
+        for (int i = 0; i < mDisplayStates.size(); i++) {
+            mDisplayStates.valueAt(i).writeToProto(proto, fieldId);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/MemoryStatUtil.java b/services/core/java/com/android/server/am/MemoryStatUtil.java
index aad890b..a8e1ccc 100644
--- a/services/core/java/com/android/server/am/MemoryStatUtil.java
+++ b/services/core/java/com/android/server/am/MemoryStatUtil.java
@@ -37,18 +37,26 @@
  * Static utility methods related to {@link MemoryStat}.
  */
 final class MemoryStatUtil {
+    static final int BYTES_IN_KILOBYTE = 1024;
+    static final int PAGE_SIZE = 4096;
+
     private static final String TAG = TAG_WITH_CLASS_NAME ? "MemoryStatUtil" : TAG_AM;
 
     /** True if device has per-app memcg */
-    private static final Boolean DEVICE_HAS_PER_APP_MEMCG =
+    private static final boolean DEVICE_HAS_PER_APP_MEMCG =
             SystemProperties.getBoolean("ro.config.per_app_memcg", false);
 
     /** Path to check if device has memcg */
     private static final String MEMCG_TEST_PATH = "/dev/memcg/apps/memory.stat";
     /** Path to memory stat file for logging app start memory state */
     private static final String MEMORY_STAT_FILE_FMT = "/dev/memcg/apps/uid_%d/pid_%d/memory.stat";
+    /** Path to memory max usage file for logging app memory state */
+    private static final String MEMORY_MAX_USAGE_FILE_FMT =
+            "/dev/memcg/apps/uid_%d/pid_%d/memory.max_usage_in_bytes";
     /** Path to procfs stat file for logging app start memory state */
     private static final String PROC_STAT_FILE_FMT = "/proc/%d/stat";
+    /** Path to procfs status file for logging app memory state */
+    private static final String PROC_STATUS_FILE_FMT = "/proc/%d/status";
 
     private static final Pattern PGFAULT = Pattern.compile("total_pgfault (\\d+)");
     private static final Pattern PGMAJFAULT = Pattern.compile("total_pgmajfault (\\d+)");
@@ -56,9 +64,12 @@
     private static final Pattern CACHE_IN_BYTES = Pattern.compile("total_cache (\\d+)");
     private static final Pattern SWAP_IN_BYTES = Pattern.compile("total_swap (\\d+)");
 
+    private static final Pattern RSS_HIGH_WATERMARK_IN_BYTES =
+            Pattern.compile("VmHWM:\\s*(\\d+)\\s*kB");
+
     private static final int PGFAULT_INDEX = 9;
     private static final int PGMAJFAULT_INDEX = 11;
-    private static final int RSS_IN_BYTES_INDEX = 23;
+    private static final int RSS_IN_PAGES_INDEX = 23;
 
     private MemoryStatUtil() {}
 
@@ -80,8 +91,15 @@
      */
     @Nullable
     static MemoryStat readMemoryStatFromMemcg(int uid, int pid) {
-        final String path = String.format(Locale.US, MEMORY_STAT_FILE_FMT, uid, pid);
-        return parseMemoryStatFromMemcg(readFileContents(path));
+        final String statPath = String.format(Locale.US, MEMORY_STAT_FILE_FMT, uid, pid);
+        MemoryStat stat = parseMemoryStatFromMemcg(readFileContents(statPath));
+        if (stat == null) {
+            return null;
+        }
+        String maxUsagePath = String.format(Locale.US, MEMORY_MAX_USAGE_FILE_FMT, uid, pid);
+        stat.rssHighWatermarkInBytes = parseMemoryMaxUsageFromMemCg(
+                readFileContents(maxUsagePath));
+        return stat;
     }
 
     /**
@@ -91,8 +109,14 @@
      */
     @Nullable
     static MemoryStat readMemoryStatFromProcfs(int pid) {
-        final String path = String.format(Locale.US, PROC_STAT_FILE_FMT, pid);
-        return parseMemoryStatFromProcfs(readFileContents(path));
+        final String statPath = String.format(Locale.US, PROC_STAT_FILE_FMT, pid);
+        MemoryStat stat = parseMemoryStatFromProcfs(readFileContents(statPath));
+        if (stat == null) {
+            return null;
+        }
+        final String statusPath = String.format(Locale.US, PROC_STATUS_FILE_FMT, pid);
+        stat.rssHighWatermarkInBytes = parseVmHWMFromProcfs(readFileContents(statusPath));
+        return stat;
     }
 
     private static String readFileContents(String path) {
@@ -113,7 +137,7 @@
     /**
      * Parses relevant statistics out from the contents of a memory.stat file in memcg.
      */
-    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    @VisibleForTesting
     @Nullable
     static MemoryStat parseMemoryStatFromMemcg(String memoryStatContents) {
         if (memoryStatContents == null || memoryStatContents.isEmpty()) {
@@ -123,22 +147,35 @@
         final MemoryStat memoryStat = new MemoryStat();
         Matcher m;
         m = PGFAULT.matcher(memoryStatContents);
-        memoryStat.pgfault = m.find() ? Long.valueOf(m.group(1)) : 0;
+        memoryStat.pgfault = m.find() ? Long.parseLong(m.group(1)) : 0;
         m = PGMAJFAULT.matcher(memoryStatContents);
-        memoryStat.pgmajfault = m.find() ? Long.valueOf(m.group(1)) : 0;
+        memoryStat.pgmajfault = m.find() ? Long.parseLong(m.group(1)) : 0;
         m = RSS_IN_BYTES.matcher(memoryStatContents);
-        memoryStat.rssInBytes = m.find() ? Long.valueOf(m.group(1)) : 0;
+        memoryStat.rssInBytes = m.find() ? Long.parseLong(m.group(1)) : 0;
         m = CACHE_IN_BYTES.matcher(memoryStatContents);
-        memoryStat.cacheInBytes = m.find() ? Long.valueOf(m.group(1)) : 0;
+        memoryStat.cacheInBytes = m.find() ? Long.parseLong(m.group(1)) : 0;
         m = SWAP_IN_BYTES.matcher(memoryStatContents);
-        memoryStat.swapInBytes = m.find() ? Long.valueOf(m.group(1)) : 0;
+        memoryStat.swapInBytes = m.find() ? Long.parseLong(m.group(1)) : 0;
         return memoryStat;
     }
 
+    @VisibleForTesting
+    static long parseMemoryMaxUsageFromMemCg(String memoryMaxUsageContents) {
+        if (memoryMaxUsageContents == null || memoryMaxUsageContents.isEmpty()) {
+            return 0;
+        }
+        try {
+            return Long.parseLong(memoryMaxUsageContents);
+        } catch (NumberFormatException e) {
+            Slog.e(TAG, "Failed to parse value", e);
+            return 0;
+        }
+    }
+
     /**
-     * Parses relevant statistics out from the contents of a /proc/pid/stat file in procfs.
+     * Parses relevant statistics out from the contents of the /proc/pid/stat file in procfs.
      */
-    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    @VisibleForTesting
     @Nullable
     static MemoryStat parseMemoryStatFromProcfs(String procStatContents) {
         if (procStatContents == null || procStatContents.isEmpty()) {
@@ -150,11 +187,30 @@
             return null;
         }
 
-        final MemoryStat memoryStat = new MemoryStat();
-        memoryStat.pgfault = Long.valueOf(splits[PGFAULT_INDEX]);
-        memoryStat.pgmajfault = Long.valueOf(splits[PGMAJFAULT_INDEX]);
-        memoryStat.rssInBytes = Long.valueOf(splits[RSS_IN_BYTES_INDEX]);
-        return memoryStat;
+        try {
+            final MemoryStat memoryStat = new MemoryStat();
+            memoryStat.pgfault = Long.parseLong(splits[PGFAULT_INDEX]);
+            memoryStat.pgmajfault = Long.parseLong(splits[PGMAJFAULT_INDEX]);
+            memoryStat.rssInBytes = Long.parseLong(splits[RSS_IN_PAGES_INDEX]) * PAGE_SIZE;
+            return memoryStat;
+        } catch (NumberFormatException e) {
+            Slog.e(TAG, "Failed to parse value", e);
+            return null;
+        }
+    }
+
+    /**
+     * Parses RSS high watermark out from the contents of the /proc/pid/status file in procfs. The
+     * returned value is in bytes.
+     */
+    @VisibleForTesting
+    static long parseVmHWMFromProcfs(String procStatusContents) {
+        if (procStatusContents == null || procStatusContents.isEmpty()) {
+            return 0;
+        }
+        Matcher m = RSS_HIGH_WATERMARK_IN_BYTES.matcher(procStatusContents);
+        // Convert value read from /proc/pid/status from kilobytes to bytes.
+        return m.find() ? Long.parseLong(m.group(1)) * BYTES_IN_KILOBYTE : 0;
     }
 
     /**
@@ -175,5 +231,7 @@
         long cacheInBytes;
         /** Number of bytes of swap usage */
         long swapInBytes;
+        /** Number of bytes of peak anonymous and swap cache memory */
+        long rssHighWatermarkInBytes;
     }
 }
diff --git a/services/core/java/com/android/server/am/PendingIntentController.java b/services/core/java/com/android/server/am/PendingIntentController.java
new file mode 100644
index 0000000..a9c00a7
--- /dev/null
+++ b/services/core/java/com/android/server/am/PendingIntentController.java
@@ -0,0 +1,329 @@
+/*
+ * 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 android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_MU;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+
+import android.app.Activity;
+import android.app.ActivityManagerInternal;
+import android.app.AppGlobals;
+import android.app.PendingIntent;
+import android.content.IIntentSender;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.ArrayMap;
+import android.util.Slog;
+import com.android.internal.os.IResultReceiver;
+import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.server.LocalServices;
+import com.android.server.wm.ActivityTaskManagerInternal;
+
+import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * Helper class for {@link ActivityManagerService} responsible for managing pending intents.
+ *
+ * <p>This class uses {@link #mLock} to synchronize access to internal state and doesn't make use of
+ * {@link ActivityManagerService} lock since there can be direct calls into this class from outside
+ * AM. This helps avoid deadlocks.
+ */
+public class PendingIntentController {
+    private static final String TAG = TAG_WITH_CLASS_NAME ? "PendingIntentController" : TAG_AM;
+    private static final String TAG_MU = TAG + POSTFIX_MU;
+
+    /** Lock for internal state. */
+    final Object mLock = new Object();
+    final Handler mH;
+    ActivityManagerInternal mAmInternal;
+    final UserController mUserController;
+    final ActivityTaskManagerInternal mAtmInternal;
+
+    /** Set of IntentSenderRecord objects that are currently active. */
+    final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
+            = new HashMap<>();
+
+    PendingIntentController(Looper looper, UserController userController) {
+        mH = new Handler(looper);
+        mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
+        mUserController = userController;
+    }
+
+    void onActivityManagerInternalAdded() {
+        synchronized (mLock) {
+            mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
+        }
+    }
+
+    PendingIntentRecord getIntentSender(int type, String packageName, int callingUid, int userId,
+            IBinder token, String resultWho, int requestCode, Intent[] intents,
+            String[] resolvedTypes, int flags, Bundle bOptions) {
+        synchronized (mLock) {
+            if (DEBUG_MU) Slog.v(TAG_MU, "getIntentSender(): uid=" + callingUid);
+
+            // We're going to be splicing together extras before sending, so we're
+            // okay poking into any contained extras.
+            if (intents != null) {
+                for (int i = 0; i < intents.length; i++) {
+                    intents[i].setDefusable(true);
+                }
+            }
+            Bundle.setDefusable(bOptions, true);
+
+            final boolean noCreate = (flags & PendingIntent.FLAG_NO_CREATE) != 0;
+            final boolean cancelCurrent = (flags & PendingIntent.FLAG_CANCEL_CURRENT) != 0;
+            final boolean updateCurrent = (flags & PendingIntent.FLAG_UPDATE_CURRENT) != 0;
+            flags &= ~(PendingIntent.FLAG_NO_CREATE | PendingIntent.FLAG_CANCEL_CURRENT
+                    | PendingIntent.FLAG_UPDATE_CURRENT);
+
+            PendingIntentRecord.Key key = new PendingIntentRecord.Key(type, packageName, token,
+                    resultWho, requestCode, intents, resolvedTypes, flags,
+                    SafeActivityOptions.fromBundle(bOptions), userId);
+            WeakReference<PendingIntentRecord> ref;
+            ref = mIntentSenderRecords.get(key);
+            PendingIntentRecord rec = ref != null ? ref.get() : null;
+            if (rec != null) {
+                if (!cancelCurrent) {
+                    if (updateCurrent) {
+                        if (rec.key.requestIntent != null) {
+                            rec.key.requestIntent.replaceExtras(intents != null ?
+                                    intents[intents.length - 1] : null);
+                        }
+                        if (intents != null) {
+                            intents[intents.length - 1] = rec.key.requestIntent;
+                            rec.key.allIntents = intents;
+                            rec.key.allResolvedTypes = resolvedTypes;
+                        } else {
+                            rec.key.allIntents = null;
+                            rec.key.allResolvedTypes = null;
+                        }
+                    }
+                    return rec;
+                }
+                makeIntentSenderCanceled(rec);
+                mIntentSenderRecords.remove(key);
+            }
+            if (noCreate) {
+                return rec;
+            }
+            rec = new PendingIntentRecord(this, key, callingUid);
+            mIntentSenderRecords.put(key, rec.ref);
+            return rec;
+        }
+    }
+
+    boolean removePendingIntentsForPackage(String packageName, int userId, int appId,
+            boolean doIt) {
+
+        boolean didSomething = false;
+        synchronized (mLock) {
+
+            // Remove pending intents.  For now we only do this when force stopping users, because
+            // we have some problems when doing this for packages -- app widgets are not currently
+            // cleaned up for such packages, so they can be left with bad pending intents.
+            if (mIntentSenderRecords.size() <= 0) {
+                return false;
+            }
+
+            Iterator<WeakReference<PendingIntentRecord>> it
+                    = mIntentSenderRecords.values().iterator();
+            while (it.hasNext()) {
+                WeakReference<PendingIntentRecord> wpir = it.next();
+                if (wpir == null) {
+                    it.remove();
+                    continue;
+                }
+                PendingIntentRecord pir = wpir.get();
+                if (pir == null) {
+                    it.remove();
+                    continue;
+                }
+                if (packageName == null) {
+                    // Stopping user, remove all objects for the user.
+                    if (pir.key.userId != userId) {
+                        // Not the same user, skip it.
+                        continue;
+                    }
+                } else {
+                    if (UserHandle.getAppId(pir.uid) != appId) {
+                        // Different app id, skip it.
+                        continue;
+                    }
+                    if (userId != UserHandle.USER_ALL && pir.key.userId != userId) {
+                        // Different user, skip it.
+                        continue;
+                    }
+                    if (!pir.key.packageName.equals(packageName)) {
+                        // Different package, skip it.
+                        continue;
+                    }
+                }
+                if (!doIt) {
+                    return true;
+                }
+                didSomething = true;
+                it.remove();
+                makeIntentSenderCanceled(pir);
+                if (pir.key.activity != null) {
+                    final Message m = PooledLambda.obtainMessage(
+                            PendingIntentController::clearPendingResultForActivity, this,
+                            pir.key.activity, pir.ref);
+                    mH.sendMessage(m);
+                }
+            }
+        }
+
+        return didSomething;
+    }
+
+    public void cancelIntentSender(IIntentSender sender) {
+        if (!(sender instanceof PendingIntentRecord)) {
+            return;
+        }
+        synchronized (mLock) {
+            final PendingIntentRecord rec = (PendingIntentRecord) sender;
+            try {
+                final int uid = AppGlobals.getPackageManager().getPackageUid(rec.key.packageName,
+                        MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getCallingUserId());
+                if (!UserHandle.isSameApp(uid, Binder.getCallingUid())) {
+                    String msg = "Permission Denial: cancelIntentSender() from pid="
+                            + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
+                            + " is not allowed to cancel package " + rec.key.packageName;
+                    Slog.w(TAG, msg);
+                    throw new SecurityException(msg);
+                }
+            } catch (RemoteException e) {
+                throw new SecurityException(e);
+            }
+            cancelIntentSender(rec, true);
+        }
+    }
+
+    public void cancelIntentSender(PendingIntentRecord rec, boolean cleanActivity) {
+        synchronized (mLock) {
+            makeIntentSenderCanceled(rec);
+            mIntentSenderRecords.remove(rec.key);
+            if (cleanActivity && rec.key.activity != null) {
+                final Message m = PooledLambda.obtainMessage(
+                        PendingIntentController::clearPendingResultForActivity, this,
+                        rec.key.activity, rec.ref);
+                mH.sendMessage(m);
+            }
+        }
+    }
+
+    private void makeIntentSenderCanceled(PendingIntentRecord rec) {
+        rec.canceled = true;
+        final RemoteCallbackList<IResultReceiver> callbacks = rec.detachCancelListenersLocked();
+        if (callbacks != null) {
+            final Message m = PooledLambda.obtainMessage(
+                    PendingIntentController::handlePendingIntentCancelled, this, callbacks);
+            mH.sendMessage(m);
+        }
+    }
+
+    private void handlePendingIntentCancelled(RemoteCallbackList<IResultReceiver> callbacks) {
+        int N = callbacks.beginBroadcast();
+        for (int i = 0; i < N; i++) {
+            try {
+                callbacks.getBroadcastItem(i).send(Activity.RESULT_CANCELED, null);
+            } catch (RemoteException e) {
+                // Process is not longer running...whatever.
+            }
+        }
+        callbacks.finishBroadcast();
+        // We have to clean up the RemoteCallbackList here, because otherwise it will
+        // needlessly hold the enclosed callbacks until the remote process dies.
+        callbacks.kill();
+    }
+
+    private void clearPendingResultForActivity(IBinder activityToken,
+            WeakReference<PendingIntentRecord> pir) {
+        mAtmInternal.clearPendingResultForActivity(activityToken, pir);
+    }
+
+    void dumpPendingIntents(PrintWriter pw, boolean dumpAll, String dumpPackage) {
+        synchronized (mLock) {
+            boolean printed = false;
+
+            pw.println("ACTIVITY MANAGER PENDING INTENTS (dumpsys activity intents)");
+
+            if (mIntentSenderRecords.size() > 0) {
+                // Organize these by package name, so they are easier to read.
+                final ArrayMap<String, ArrayList<PendingIntentRecord>> byPackage = new ArrayMap<>();
+                final ArrayList<WeakReference<PendingIntentRecord>> weakRefs = new ArrayList<>();
+                final Iterator<WeakReference<PendingIntentRecord>> it
+                        = mIntentSenderRecords.values().iterator();
+                while (it.hasNext()) {
+                    WeakReference<PendingIntentRecord> ref = it.next();
+                    PendingIntentRecord rec = ref != null ? ref.get() : null;
+                    if (rec == null) {
+                        weakRefs.add(ref);
+                        continue;
+                    }
+                    if (dumpPackage != null && !dumpPackage.equals(rec.key.packageName)) {
+                        continue;
+                    }
+                    ArrayList<PendingIntentRecord> list = byPackage.get(rec.key.packageName);
+                    if (list == null) {
+                        list = new ArrayList<>();
+                        byPackage.put(rec.key.packageName, list);
+                    }
+                    list.add(rec);
+                }
+                for (int i = 0; i < byPackage.size(); i++) {
+                    ArrayList<PendingIntentRecord> intents = byPackage.valueAt(i);
+                    printed = true;
+                    pw.print("  * "); pw.print(byPackage.keyAt(i));
+                    pw.print(": "); pw.print(intents.size()); pw.println(" items");
+                    for (int j = 0; j < intents.size(); j++) {
+                        pw.print("    #"); pw.print(j); pw.print(": "); pw.println(intents.get(j));
+                        if (dumpAll) {
+                            intents.get(j).dump(pw, "      ");
+                        }
+                    }
+                }
+                if (weakRefs.size() > 0) {
+                    printed = true;
+                    pw.println("  * WEAK REFS:");
+                    for (int i = 0; i < weakRefs.size(); i++) {
+                        pw.print("    #"); pw.print(i); pw.print(": "); pw.println(weakRefs.get(i));
+                    }
+                }
+            }
+
+            if (!printed) {
+                pw.println("  (nothing)");
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index ee1166e..b9c6fa6 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -38,15 +38,16 @@
 import android.util.TimeUtils;
 
 import com.android.internal.os.IResultReceiver;
+import com.android.internal.util.function.pooled.PooledLambda;
 
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.util.Objects;
 
-final class PendingIntentRecord extends IIntentSender.Stub {
+public final class PendingIntentRecord extends IIntentSender.Stub {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "PendingIntentRecord" : TAG_AM;
 
-    final ActivityManagerService owner;
+    final PendingIntentController controller;
     final Key key;
     final int uid;
     final WeakReference<PendingIntentRecord> ref;
@@ -62,7 +63,7 @@
     final static class Key {
         final int type;
         final String packageName;
-        final ActivityRecord activity;
+        final IBinder activity;
         final String who;
         final int requestCode;
         final Intent requestIntent;
@@ -76,7 +77,7 @@
 
         private static final int ODD_PRIME_NUMBER = 37;
 
-        Key(int _t, String _p, ActivityRecord _a, String _w,
+        Key(int _t, String _p, IBinder _a, String _w,
                 int _r, Intent[] _i, String[] _it, int _f, SafeActivityOptions _o, int _userId) {
             type = _t;
             packageName = _p;
@@ -114,6 +115,7 @@
             //        + Integer.toHexString(hashCode));
         }
 
+        @Override
         public boolean equals(Object otherObj) {
             if (otherObj == null) {
                 return false;
@@ -188,11 +190,11 @@
         }
     }
 
-    PendingIntentRecord(ActivityManagerService _owner, Key _k, int _u) {
-        owner = _owner;
+    PendingIntentRecord(PendingIntentController _controller, Key _k, int _u) {
+        controller = _controller;
         key = _k;
         uid = _u;
-        ref = new WeakReference<PendingIntentRecord>(this);
+        ref = new WeakReference<>(this);
     }
 
     void setWhitelistDurationLocked(IBinder whitelistToken, long duration) {
@@ -247,189 +249,196 @@
     }
 
     int sendInner(int code, Intent intent, String resolvedType, IBinder whitelistToken,
-            IIntentReceiver finishedReceiver,
-            String requiredPermission, IBinder resultTo, String resultWho, int requestCode,
-            int flagsMask, int flagsValues, Bundle options) {
+            IIntentReceiver finishedReceiver, String requiredPermission, IBinder resultTo,
+            String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle options) {
         if (intent != null) intent.setDefusable(true);
         if (options != null) options.setDefusable(true);
 
-        synchronized (owner) {
-            if (!canceled) {
-                sent = true;
-                if ((key.flags&PendingIntent.FLAG_ONE_SHOT) != 0) {
-                    owner.cancelIntentSenderLocked(this, true);
-                }
+        Long duration = null;
+        Intent finalIntent = null;
+        Intent[] allIntents = null;
+        String[] allResolvedTypes = null;
+        SafeActivityOptions mergedOptions = null;
+        synchronized (controller.mLock) {
+            if (canceled) {
+                return ActivityManager.START_CANCELED;
+            }
 
-                Intent finalIntent = key.requestIntent != null
-                        ? new Intent(key.requestIntent) : new Intent();
+            sent = true;
+            if ((key.flags & PendingIntent.FLAG_ONE_SHOT) != 0) {
+                controller.cancelIntentSender(this, true);
+            }
 
-                final boolean immutable = (key.flags & PendingIntent.FLAG_IMMUTABLE) != 0;
-                if (!immutable) {
-                    if (intent != null) {
-                        int changes = finalIntent.fillIn(intent, key.flags);
-                        if ((changes & Intent.FILL_IN_DATA) == 0) {
-                            resolvedType = key.requestResolvedType;
-                        }
-                    } else {
+            finalIntent = key.requestIntent != null ? new Intent(key.requestIntent) : new Intent();
+
+            final boolean immutable = (key.flags & PendingIntent.FLAG_IMMUTABLE) != 0;
+            if (!immutable) {
+                if (intent != null) {
+                    int changes = finalIntent.fillIn(intent, key.flags);
+                    if ((changes & Intent.FILL_IN_DATA) == 0) {
                         resolvedType = key.requestResolvedType;
                     }
-                    flagsMask &= ~Intent.IMMUTABLE_FLAGS;
-                    flagsValues &= flagsMask;
-                    finalIntent.setFlags((finalIntent.getFlags() & ~flagsMask) | flagsValues);
                 } else {
                     resolvedType = key.requestResolvedType;
                 }
-
-                final int callingUid = Binder.getCallingUid();
-                final int callingPid = Binder.getCallingPid();
-
-                // Extract options before clearing calling identity
-                SafeActivityOptions mergedOptions = key.options;
-                if (mergedOptions == null) {
-                    mergedOptions = SafeActivityOptions.fromBundle(options);
-                } else {
-                    mergedOptions.setCallerOptions(ActivityOptions.fromBundle(options));
-                }
-
-                final long origId = Binder.clearCallingIdentity();
-
-                if (whitelistDuration != null) {
-                    Long duration = whitelistDuration.get(whitelistToken);
-                    if (duration != null) {
-                        int procState = owner.getUidState(callingUid);
-                        if (!ActivityManager.isProcStateBackground(procState)) {
-                            StringBuilder tag = new StringBuilder(64);
-                            tag.append("pendingintent:");
-                            UserHandle.formatUid(tag, callingUid);
-                            tag.append(":");
-                            if (finalIntent.getAction() != null) {
-                                tag.append(finalIntent.getAction());
-                            } else if (finalIntent.getComponent() != null) {
-                                finalIntent.getComponent().appendShortString(tag);
-                            } else if (finalIntent.getData() != null) {
-                                tag.append(finalIntent.getData().toSafeString());
-                            }
-                            owner.tempWhitelistForPendingIntentLocked(callingPid,
-                                    callingUid, uid, duration, tag.toString());
-                        } else {
-                            Slog.w(TAG, "Not doing whitelist " + this + ": caller state="
-                                    + procState);
-                        }
-                    }
-                }
-
-                boolean sendFinish = finishedReceiver != null;
-                int userId = key.userId;
-                if (userId == UserHandle.USER_CURRENT) {
-                    userId = owner.mUserController.getCurrentOrTargetUserId();
-                }
-                int res = START_SUCCESS;
-                switch (key.type) {
-                    case ActivityManager.INTENT_SENDER_ACTIVITY:
-                        try {
-                            // Note when someone has a pending intent, even from different
-                            // users, then there's no need to ensure the calling user matches
-                            // the target user, so validateIncomingUser is always false below.
-
-                            if (key.allIntents != null && key.allIntents.length > 1) {
-                                Intent[] allIntents = new Intent[key.allIntents.length];
-                                String[] allResolvedTypes = new String[key.allIntents.length];
-                                System.arraycopy(key.allIntents, 0, allIntents, 0,
-                                        key.allIntents.length);
-                                if (key.allResolvedTypes != null) {
-                                    System.arraycopy(key.allResolvedTypes, 0, allResolvedTypes, 0,
-                                            key.allResolvedTypes.length);
-                                }
-                                allIntents[allIntents.length-1] = finalIntent;
-                                allResolvedTypes[allResolvedTypes.length-1] = resolvedType;
-
-                                res = owner.mActivityTaskManager.getActivityStartController().startActivitiesInPackage(
-                                        uid, key.packageName, allIntents, allResolvedTypes,
-                                        resultTo, mergedOptions, userId,
-                                        false /* validateIncomingUser */,
-                                        this /* originatingPendingIntent */);
-                            } else {
-                                res = owner.mActivityTaskManager.getActivityStartController().startActivityInPackage(uid,
-                                        callingPid, callingUid, key.packageName, finalIntent,
-                                        resolvedType, resultTo, resultWho, requestCode, 0,
-                                        mergedOptions, userId, null, "PendingIntentRecord",
-                                        false /* validateIncomingUser */,
-                                        this /* originatingPendingIntent */);
-                            }
-                        } catch (RuntimeException e) {
-                            Slog.w(TAG, "Unable to send startActivity intent", e);
-                        }
-                        break;
-                    case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
-                        final ActivityStack stack = key.activity.getStack();
-                        if (stack != null) {
-                            stack.sendActivityResultLocked(-1, key.activity, key.who,
-                                    key.requestCode, code, finalIntent);
-                        }
-                        break;
-                    case ActivityManager.INTENT_SENDER_BROADCAST:
-                        try {
-                            // If a completion callback has been requested, require
-                            // that the broadcast be delivered synchronously
-                            int sent = owner.broadcastIntentInPackage(key.packageName, uid,
-                                    finalIntent, resolvedType, finishedReceiver, code, null, null,
-                                    requiredPermission, options, (finishedReceiver != null),
-                                    false, userId);
-                            if (sent == ActivityManager.BROADCAST_SUCCESS) {
-                                sendFinish = false;
-                            }
-                        } catch (RuntimeException e) {
-                            Slog.w(TAG, "Unable to send startActivity intent", e);
-                        }
-                        break;
-                    case ActivityManager.INTENT_SENDER_SERVICE:
-                    case ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE:
-                        try {
-                            owner.startServiceInPackage(uid, finalIntent, resolvedType,
-                                    key.type == ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE,
-                                    key.packageName, userId);
-                        } catch (RuntimeException e) {
-                            Slog.w(TAG, "Unable to send startService intent", e);
-                        } catch (TransactionTooLargeException e) {
-                            res = ActivityManager.START_CANCELED;
-                        }
-                        break;
-                }
-
-                if (sendFinish && res != ActivityManager.START_CANCELED) {
-                    try {
-                        finishedReceiver.performReceive(new Intent(finalIntent), 0,
-                                null, null, false, false, key.userId);
-                    } catch (RemoteException e) {
-                    }
-                }
-
-                Binder.restoreCallingIdentity(origId);
-
-                return res;
+                flagsMask &= ~Intent.IMMUTABLE_FLAGS;
+                flagsValues &= flagsMask;
+                finalIntent.setFlags((finalIntent.getFlags() & ~flagsMask) | flagsValues);
+            } else {
+                resolvedType = key.requestResolvedType;
             }
+
+            // Extract options before clearing calling identity
+            mergedOptions = key.options;
+            if (mergedOptions == null) {
+                mergedOptions = SafeActivityOptions.fromBundle(options);
+            } else {
+                mergedOptions.setCallerOptions(ActivityOptions.fromBundle(options));
+            }
+
+            if (whitelistDuration != null) {
+                duration = whitelistDuration.get(whitelistToken);
+            }
+
+            if (key.type == ActivityManager.INTENT_SENDER_ACTIVITY
+                    && key.allIntents != null && key.allIntents.length > 1) {
+                // Copy all intents and resolved types while we have the controller lock so we can
+                // use it later when the lock isn't held.
+                allIntents = new Intent[key.allIntents.length];
+                allResolvedTypes = new String[key.allIntents.length];
+                System.arraycopy(key.allIntents, 0, allIntents, 0, key.allIntents.length);
+                if (key.allResolvedTypes != null) {
+                    System.arraycopy(key.allResolvedTypes, 0, allResolvedTypes, 0,
+                            key.allResolvedTypes.length);
+                }
+                allIntents[allIntents.length - 1] = finalIntent;
+                allResolvedTypes[allResolvedTypes.length - 1] = resolvedType;
+            }
+
         }
-        return ActivityManager.START_CANCELED;
+        // We don't hold the controller lock beyond this point as we will be calling into AM and WM.
+
+        final int callingUid = Binder.getCallingUid();
+        final int callingPid = Binder.getCallingPid();
+        final long origId = Binder.clearCallingIdentity();
+
+        int res = START_SUCCESS;
+        try {
+            if (duration != null) {
+                int procState = controller.mAmInternal.getUidProcessState(callingUid);
+                if (!ActivityManager.isProcStateBackground(procState)) {
+                    StringBuilder tag = new StringBuilder(64);
+                    tag.append("pendingintent:");
+                    UserHandle.formatUid(tag, callingUid);
+                    tag.append(":");
+                    if (finalIntent.getAction() != null) {
+                        tag.append(finalIntent.getAction());
+                    } else if (finalIntent.getComponent() != null) {
+                        finalIntent.getComponent().appendShortString(tag);
+                    } else if (finalIntent.getData() != null) {
+                        tag.append(finalIntent.getData().toSafeString());
+                    }
+                    controller.mAmInternal.tempWhitelistForPendingIntent(callingPid, callingUid,
+                            uid, duration, tag.toString());
+                } else {
+                    Slog.w(TAG, "Not doing whitelist " + this + ": caller state=" + procState);
+                }
+            }
+
+            boolean sendFinish = finishedReceiver != null;
+            int userId = key.userId;
+            if (userId == UserHandle.USER_CURRENT) {
+                userId = controller.mUserController.getCurrentOrTargetUserId();
+            }
+
+            switch (key.type) {
+                case ActivityManager.INTENT_SENDER_ACTIVITY:
+                    try {
+                        // Note when someone has a pending intent, even from different
+                        // users, then there's no need to ensure the calling user matches
+                        // the target user, so validateIncomingUser is always false below.
+
+                        if (key.allIntents != null && key.allIntents.length > 1) {
+                            res = controller.mAtmInternal.startActivitiesInPackage(
+                                    uid, key.packageName, allIntents, allResolvedTypes, resultTo,
+                                    mergedOptions, userId, false /* validateIncomingUser */,
+                                    this /* originatingPendingIntent */);
+                        } else {
+                            res = controller.mAtmInternal.startActivityInPackage(
+                                    uid, callingPid, callingUid, key.packageName, finalIntent,
+                                    resolvedType, resultTo, resultWho, requestCode, 0,
+                                    mergedOptions, userId, null, "PendingIntentRecord",
+                                    false /* validateIncomingUser */,
+                                    this /* originatingPendingIntent */);
+                        }
+                    } catch (RuntimeException e) {
+                        Slog.w(TAG, "Unable to send startActivity intent", e);
+                    }
+                    break;
+                case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
+                    controller.mAtmInternal.sendActivityResult(-1, key.activity, key.who,
+                                key.requestCode, code, finalIntent);
+                    break;
+                case ActivityManager.INTENT_SENDER_BROADCAST:
+                    try {
+                        // If a completion callback has been requested, require
+                        // that the broadcast be delivered synchronously
+                        int sent = controller.mAmInternal.broadcastIntentInPackage(key.packageName,
+                                uid, finalIntent, resolvedType, finishedReceiver, code, null, null,
+                                requiredPermission, options, (finishedReceiver != null),
+                                false, userId);
+                        if (sent == ActivityManager.BROADCAST_SUCCESS) {
+                            sendFinish = false;
+                        }
+                    } catch (RuntimeException e) {
+                        Slog.w(TAG, "Unable to send startActivity intent", e);
+                    }
+                    break;
+                case ActivityManager.INTENT_SENDER_SERVICE:
+                case ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE:
+                    try {
+                        controller.mAmInternal.startServiceInPackage(uid, finalIntent, resolvedType,
+                                key.type == ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE,
+                                key.packageName, userId);
+                    } catch (RuntimeException e) {
+                        Slog.w(TAG, "Unable to send startService intent", e);
+                    } catch (TransactionTooLargeException e) {
+                        res = ActivityManager.START_CANCELED;
+                    }
+                    break;
+            }
+
+            if (sendFinish && res != ActivityManager.START_CANCELED) {
+                try {
+                    finishedReceiver.performReceive(new Intent(finalIntent), 0,
+                            null, null, false, false, key.userId);
+                } catch (RemoteException e) {
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(origId);
+        }
+
+        return res;
     }
 
     @Override
     protected void finalize() throws Throwable {
         try {
             if (!canceled) {
-                owner.mHandler.sendMessage(owner.mHandler.obtainMessage(
-                        ActivityManagerService.FINALIZE_PENDING_INTENT_MSG, this));
+                controller.mH.sendMessage(PooledLambda.obtainMessage(
+                        PendingIntentRecord::completeFinalize, this));
             }
         } finally {
             super.finalize();
         }
     }
 
-    public void completeFinalize() {
-        synchronized(owner) {
-            WeakReference<PendingIntentRecord> current =
-                    owner.mIntentSenderRecords.get(key);
+    private void completeFinalize() {
+        synchronized(controller.mLock) {
+            WeakReference<PendingIntentRecord> current = controller.mIntentSenderRecords.get(key);
             if (current == ref) {
-                owner.mIntentSenderRecords.remove(key);
+                controller.mIntentSenderRecords.remove(key);
             }
         }
     }
diff --git a/services/core/java/com/android/server/am/ProcessStatsService.java b/services/core/java/com/android/server/am/ProcessStatsService.java
index 8ce650c..6ffd8a9 100644
--- a/services/core/java/com/android/server/am/ProcessStatsService.java
+++ b/services/core/java/com/android/server/am/ProcessStatsService.java
@@ -23,8 +23,10 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.service.procstats.ProcessStatsServiceDumpProto;
+import android.text.format.DateFormat;
 import android.util.ArrayMap;
 import android.util.AtomicFile;
+import android.util.Log;
 import android.util.LongSparseArray;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -47,6 +49,7 @@
 import java.io.InputStream;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.locks.ReentrantLock;
@@ -482,6 +485,23 @@
         return finalRes;
     }
 
+    static int parseSectionOptions(String optionsStr) {
+        final String sep = ",";
+        String[] sectionsStr = optionsStr.split(sep);
+        if (sectionsStr.length == 0) {
+            return ProcessStats.REPORT_ALL;
+        }
+        int res = 0;
+        List<String> optionStrList = Arrays.asList(ProcessStats.OPTIONS_STR);
+        for (String sectionStr : sectionsStr) {
+            int optionIndex = optionStrList.indexOf(sectionStr);
+            if (optionIndex != -1) {
+                res |= ProcessStats.OPTIONS[optionIndex];
+            }
+        }
+        return res;
+    }
+
     public byte[] getCurrentStats(List<ParcelFileDescriptor> historic) {
         mAm.mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.PACKAGE_USAGE_STATS, null);
@@ -514,6 +534,95 @@
         return current.marshall();
     }
 
+    /**
+     * Get stats committed after highWaterMarkMs
+     * @param highWaterMarkMs Report stats committed after this time.
+     * @param section Integer mask to indicage which sections to include in the stats.
+     * @param doAggregate Whether to aggregate the stats or keep them separated.
+     * @return List of proto binary of individual commit files or one that is merged from them.
+     */
+    @Override
+    public long getCommittedStats(long highWaterMarkMs, int section, boolean doAggregate,
+            List<ParcelFileDescriptor> committedStats) {
+        mAm.mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.PACKAGE_USAGE_STATS, null);
+
+        ProcessStats mergedStats = new ProcessStats(false);
+        long newHighWaterMark = highWaterMarkMs;
+        mWriteLock.lock();
+        try {
+            ArrayList<String> files = getCommittedFiles(0, false, true);
+            if (files != null) {
+                String highWaterMarkStr =
+                        DateFormat.format("yyyy-MM-dd-HH-mm-ss", highWaterMarkMs).toString();
+                ProcessStats stats = new ProcessStats(false);
+                for (int i = files.size() - 1; i >= 0; i--) {
+                    String fileName = files.get(i);
+                    try {
+                        String startTimeStr = fileName.substring(
+                                fileName.lastIndexOf(STATE_FILE_PREFIX)
+                                        + STATE_FILE_PREFIX.length(),
+                                fileName.lastIndexOf(STATE_FILE_SUFFIX));
+                        if (startTimeStr.compareToIgnoreCase(highWaterMarkStr) > 0) {
+                            ParcelFileDescriptor pfd = ParcelFileDescriptor.open(
+                                    new File(fileName),
+                                    ParcelFileDescriptor.MODE_READ_ONLY);
+                            InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
+                            stats.reset();
+                            stats.read(is);
+                            is.close();
+                            if (stats.mTimePeriodStartClock > newHighWaterMark) {
+                                newHighWaterMark = stats.mTimePeriodStartClock;
+                            }
+                            if (doAggregate) {
+                                mergedStats.add(stats);
+                            } else {
+                                committedStats.add(protoToParcelFileDescriptor(stats, section));
+                            }
+                            if (stats.mReadError != null) {
+                                Log.w(TAG, "Failure reading process stats: " + stats.mReadError);
+                                continue;
+                            }
+                        }
+                    } catch (IOException e) {
+                        Slog.w(TAG, "Failure opening procstat file " + fileName, e);
+                    } catch (IndexOutOfBoundsException e) {
+                        Slog.w(TAG, "Failure to read and parse commit file " + fileName, e);
+                    }
+                }
+                if (doAggregate) {
+                    committedStats.add(protoToParcelFileDescriptor(mergedStats, section));
+                }
+                return newHighWaterMark;
+            }
+        } catch (IOException e) {
+            Slog.w(TAG, "Failure opening procstat file", e);
+        } finally {
+            mWriteLock.unlock();
+        }
+        return newHighWaterMark;
+    }
+
+    private ParcelFileDescriptor protoToParcelFileDescriptor(ProcessStats stats, int section)
+            throws IOException {
+        final ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe();
+        Thread thr = new Thread("ProcessStats pipe output") {
+            public void run() {
+                try {
+                    FileOutputStream fout = new ParcelFileDescriptor.AutoCloseOutputStream(fds[1]);
+                    final ProtoOutputStream proto = new ProtoOutputStream(fout);
+                    stats.writeToProto(proto, stats.mTimePeriodEndRealtime, section);
+                    proto.flush();
+                    fout.close();
+                } catch (IOException e) {
+                    Slog.w(TAG, "Failure writing pipe", e);
+                }
+            }
+        };
+        thr.start();
+        return fds[0];
+    }
+
     public ParcelFileDescriptor getStatsOverTime(long minTime) {
         mAm.mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.PACKAGE_USAGE_STATS, null);
@@ -594,7 +703,7 @@
 
     private void dumpAggregatedStats(PrintWriter pw, long aggregateHours, long now,
             String reqPackage, boolean isCompact, boolean dumpDetails, boolean dumpFullDetails,
-            boolean dumpAll, boolean activeOnly) {
+            boolean dumpAll, boolean activeOnly, int section) {
         ParcelFileDescriptor pfd = getStatsOverTime(aggregateHours*60*60*1000
                 - (ProcessStats.COMMIT_PERIOD/2));
         if (pfd == null) {
@@ -609,11 +718,11 @@
             return;
         }
         if (isCompact) {
-            stats.dumpCheckinLocked(pw, reqPackage);
+            stats.dumpCheckinLocked(pw, reqPackage, section);
         } else {
             if (dumpDetails || dumpFullDetails) {
                 stats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpDetails, dumpAll,
-                        activeOnly);
+                        activeOnly, section);
             } else {
                 stats.dumpSummaryLocked(pw, reqPackage, now, activeOnly);
             }
@@ -643,6 +752,8 @@
         pw.println("  --max: for -a, max num of historical batches to print.");
         pw.println("  --active: only show currently active processes/services.");
         pw.println("  --commit: commit current stats to disk and reset to start new stats.");
+        pw.println("  --section: proc|pkg-proc|pkg-svc|pkg-asc|pkg-all|all ");
+        pw.println("    options can be combined to select desired stats");
         pw.println("  --reset: reset current stats, without committing.");
         pw.println("  --clear: clear all stats; does both --reset and deletes old stats.");
         pw.println("  --write: write current in-memory stats to disk.");
@@ -696,6 +807,7 @@
         int[] csvMemStats = new int[] { ProcessStats.ADJ_MEM_FACTOR_CRITICAL};
         boolean csvSepProcStats = true;
         int[] csvProcStats = ProcessStats.ALL_PROC_STATES;
+        int section = ProcessStats.REPORT_ALL;
         if (args != null) {
             for (int i=0; i<args.length; i++) {
                 String arg = args[i];
@@ -814,13 +926,14 @@
                         pw.println("Process stats committed.");
                         quit = true;
                     }
-                } else if ("--reset".equals(arg)) {
-                    synchronized (mAm) {
-                        mProcessStats.resetSafely();
-                        mAm.requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false);
-                        pw.println("Process stats reset.");
-                        quit = true;
+                } else if ("--section".equals(arg)) {
+                    i++;
+                    if (i >= args.length) {
+                        pw.println("Error: argument required for --section");
+                        dumpHelp(pw);
+                        return;
                     }
+                    section = parseSectionOptions(args[i]);
                 } else if ("--clear".equals(arg)) {
                     synchronized (mAm) {
                         mProcessStats.resetSafely();
@@ -946,7 +1059,7 @@
         } else if (aggregateHours != 0) {
             pw.print("AGGREGATED OVER LAST "); pw.print(aggregateHours); pw.println(" HOURS:");
             dumpAggregatedStats(pw, aggregateHours, now, reqPackage, isCompact,
-                    dumpDetails, dumpFullDetails, dumpAll, activeOnly);
+                    dumpDetails, dumpFullDetails, dumpAll, activeOnly, section);
             return;
         } else if (lastIndex > 0) {
             pw.print("LAST STATS AT INDEX "); pw.print(lastIndex); pw.println(":");
@@ -968,7 +1081,7 @@
             boolean checkedIn = fileStr.endsWith(STATE_FILE_CHECKIN_SUFFIX);
             if (isCheckin || isCompact) {
                 // Don't really need to lock because we uniquely own this object.
-                processStats.dumpCheckinLocked(pw, reqPackage);
+                processStats.dumpCheckinLocked(pw, reqPackage, section);
             } else {
                 pw.print("COMMITTED STATS FROM ");
                 pw.print(processStats.mTimePeriodStartClockStr);
@@ -976,7 +1089,7 @@
                 pw.println(":");
                 if (dumpDetails || dumpFullDetails) {
                     processStats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpDetails,
-                            dumpAll, activeOnly);
+                            dumpAll, activeOnly, section);
                     if (dumpAll) {
                         pw.print("  mFile="); pw.println(mFile.getBaseFile());
                     }
@@ -1015,7 +1128,7 @@
                             boolean checkedIn = fileStr.endsWith(STATE_FILE_CHECKIN_SUFFIX);
                             if (isCheckin || isCompact) {
                                 // Don't really need to lock because we uniquely own this object.
-                                processStats.dumpCheckinLocked(pw, reqPackage);
+                                processStats.dumpCheckinLocked(pw, reqPackage, section);
                             } else {
                                 if (sepNeeded) {
                                     pw.println();
@@ -1031,7 +1144,7 @@
                                 // much crud.
                                 if (dumpFullDetails) {
                                     processStats.dumpLocked(pw, reqPackage, now, false, false,
-                                            false, activeOnly);
+                                            false, activeOnly, section);
                                 } else {
                                     processStats.dumpSummaryLocked(pw, reqPackage, now, activeOnly);
                                 }
@@ -1054,7 +1167,7 @@
         if (!isCheckin) {
             synchronized (mAm) {
                 if (isCompact) {
-                    mProcessStats.dumpCheckinLocked(pw, reqPackage);
+                    mProcessStats.dumpCheckinLocked(pw, reqPackage, section);
                 } else {
                     if (sepNeeded) {
                         pw.println();
@@ -1062,7 +1175,7 @@
                     pw.println("CURRENT STATS:");
                     if (dumpDetails || dumpFullDetails) {
                         mProcessStats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpDetails,
-                                dumpAll, activeOnly);
+                                dumpAll, activeOnly, section);
                         if (dumpAll) {
                             pw.print("  mFile="); pw.println(mFile.getBaseFile());
                         }
@@ -1078,11 +1191,11 @@
                 }
                 pw.println("AGGREGATED OVER LAST 24 HOURS:");
                 dumpAggregatedStats(pw, 24, now, reqPackage, isCompact,
-                        dumpDetails, dumpFullDetails, dumpAll, activeOnly);
+                        dumpDetails, dumpFullDetails, dumpAll, activeOnly, section);
                 pw.println();
                 pw.println("AGGREGATED OVER LAST 3 HOURS:");
                 dumpAggregatedStats(pw, 3, now, reqPackage, isCompact,
-                        dumpDetails, dumpFullDetails, dumpAll, activeOnly);
+                        dumpDetails, dumpFullDetails, dumpAll, activeOnly, section);
             }
         }
     }
@@ -1099,7 +1212,9 @@
         if (stats.mReadError != null) {
             return;
         }
-        stats.writeToProto(proto, fieldId, now);
+        final long token = proto.start(fieldId);
+        stats.writeToProto(proto, now, ProcessStats.REPORT_ALL);
+        proto.end(token);
     }
 
     private void dumpProto(FileDescriptor fd) {
@@ -1109,7 +1224,9 @@
         long now;
         synchronized (mAm) {
             now = SystemClock.uptimeMillis();
-            mProcessStats.writeToProto(proto,ProcessStatsServiceDumpProto.PROCSTATS_NOW, now);
+            final long token = proto.start(ProcessStatsServiceDumpProto.PROCSTATS_NOW);
+            mProcessStats.writeToProto(proto, now, ProcessStats.REPORT_ALL);
+            proto.end(token);
         }
 
         // aggregated over last 3 hours procstats
diff --git a/services/core/java/com/android/server/am/SafeActivityOptions.java b/services/core/java/com/android/server/am/SafeActivityOptions.java
index f7de7f4..fa0cb47 100644
--- a/services/core/java/com/android/server/am/SafeActivityOptions.java
+++ b/services/core/java/com/android/server/am/SafeActivityOptions.java
@@ -44,7 +44,7 @@
  * the inner options. Also supports having two set of options: Once from the original caller, and
  * once from the caller that is overriding it, which happens when sending a {@link PendingIntent}.
  */
-class SafeActivityOptions {
+public class SafeActivityOptions {
 
     private static final String TAG = TAG_WITH_CLASS_NAME ? "SafeActivityOptions" : TAG_AM;
 
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 9b42d65..ef8cb1c 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -129,7 +129,8 @@
 import java.util.ArrayList;
 import java.util.Objects;
 
-class TaskRecord extends ConfigurationContainer implements TaskWindowContainerListener {
+// TODO: Make package private again once move to WM package is complete.
+public class TaskRecord extends ConfigurationContainer implements TaskWindowContainerListener {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_AM;
     private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
     private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
diff --git a/services/core/java/com/android/server/appbinding/AppBindingService.java b/services/core/java/com/android/server/appbinding/AppBindingService.java
new file mode 100644
index 0000000..91b3b21
--- /dev/null
+++ b/services/core/java/com/android/server/appbinding/AppBindingService.java
@@ -0,0 +1,81 @@
+/*
+ * 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.appbinding;
+
+import android.app.AppGlobals;
+import android.content.Context;
+import android.content.pm.IPackageManager;
+import android.os.Binder;
+import android.os.Handler;
+
+import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.DumpUtils;
+import com.android.server.SystemService;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * System server that keeps a binding to an app to keep it always running.
+ */
+public class AppBindingService extends Binder {
+    public static final String TAG = "AppBindingService";
+
+    private static final boolean DEBUG = false;
+
+    private final Object mLock = new Object();
+
+    private final Injector mInjector;
+    private final Context mContext;
+    private final Handler mHandler;
+    private final IPackageManager mIPackageManager;
+
+    static class Injector {
+        public IPackageManager getIPackageManager() {
+            return AppGlobals.getPackageManager();
+        }
+    }
+
+    /**
+     * System service interacts with this service via this class.
+     */
+    public static final class Lifecycle extends SystemService {
+        final AppBindingService mService;
+
+        public Lifecycle(Context context) {
+            super(context);
+            mService = new AppBindingService(new Injector(), context);
+        }
+
+        @Override
+        public void onStart() {
+            publishBinderService(Context.APP_BINDING_SERVICE, mService);
+        }
+    }
+
+    private AppBindingService(Injector injector, Context context) {
+        mInjector = injector;
+        mContext = context;
+        mIPackageManager = injector.getIPackageManager();
+        mHandler = BackgroundThread.getHandler();
+    }
+
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
+    }
+}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 8caa702..f0ff570 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -627,6 +627,13 @@
     // If absolute volume is supported in AVRCP device
     private boolean mAvrcpAbsVolSupported = false;
 
+    // Pre-scale for Bluetooth Absolute Volume
+    private float[] mPrescaleAbsoluteVolume = new float[] {
+        0.5f,    // Pre-scale for index 1
+        0.7f,    // Pre-scale for index 2
+        0.85f,   // Pre-scale for index 3
+    };
+
     private static Long mLastDeviceConnectMsgTime = new Long(0);
 
     private NotificationManager mNm;
@@ -878,6 +885,23 @@
         mUserManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener);
 
         mRecordMonitor.initMonitor();
+
+        final float[] preScale = new float[3];
+        preScale[0] = mContext.getResources().getFraction(
+                com.android.internal.R.fraction.config_prescaleAbsoluteVolume_index1,
+                1, 1);
+        preScale[1] = mContext.getResources().getFraction(
+                com.android.internal.R.fraction.config_prescaleAbsoluteVolume_index2,
+                1, 1);
+        preScale[2] = mContext.getResources().getFraction(
+                com.android.internal.R.fraction.config_prescaleAbsoluteVolume_index3,
+                1, 1);
+        for (int i = 0; i < preScale.length; i++) {
+            if (0.0f <= preScale[i] && preScale[i] <= 1.0f) {
+                mPrescaleAbsoluteVolume[i] = preScale[i];
+            }
+        }
+
     }
 
     public void systemReady() {
@@ -4661,7 +4685,9 @@
     @Override
     public void setHearingAidDeviceConnectionState(BluetoothDevice device, int state)
     {
-        Log.i(TAG, "setBluetoothHearingAidDeviceConnectionState");
+        mDeviceLogger.log((new AudioEventLogger.StringEvent(
+                "setHearingAidDeviceConnectionState state=" + state
+                        + " addr=" + device.getAddress())).printLog(TAG));
 
         setBluetoothHearingAidDeviceConnectionState(
                 device, state,  false /* suppressNoisyIntent */, AudioSystem.DEVICE_NONE);
@@ -4699,12 +4725,12 @@
     public int setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(BluetoothDevice device,
                 int state, int profile, boolean suppressNoisyIntent, int a2dpVolume)
     {
-        mDeviceLogger.log(new AudioEventLogger.StringEvent(
+        mDeviceLogger.log((new AudioEventLogger.StringEvent(
                 "setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent state=" + state
                 // only querying address as this is the only readily available field on the device
                 + " addr=" + device.getAddress()
                 + " prof=" + profile + " supprNoisy=" + suppressNoisyIntent
-                + " vol=" + a2dpVolume));
+                + " vol=" + a2dpVolume)).printLog(TAG));
         if (mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE, device)) {
             mDeviceLogger.log(new AudioEventLogger.StringEvent("A2DP connection state ignored"));
             return 0;
@@ -4926,18 +4952,12 @@
             if (index == 0) {
                 // 0% for volume 0
                 index = 0;
-            } else if (index == 1) {
-                // 50% for volume 1
-                index = (int)(mIndexMax * 0.5) /10;
-            } else if (index == 2) {
-                // 70% for volume 2
-                index = (int)(mIndexMax * 0.70) /10;
-            } else if (index == 3) {
-                // 85% for volume 3
-                index = (int)(mIndexMax * 0.85) /10;
+            } else if (index > 0 && index <= 3) {
+                // Pre-scale for volume steps 1 2 and 3
+                index = (int) (mIndexMax * mPrescaleAbsoluteVolume[index - 1]) / 10;
             } else {
                 // otherwise, full gain
-                index = (mIndexMax + 5)/10;
+                index = (mIndexMax + 5) / 10;
             }
             return index;
         }
@@ -5870,6 +5890,8 @@
     }
 
     private void onSendBecomingNoisyIntent() {
+        mDeviceLogger.log((new AudioEventLogger.StringEvent(
+                "broadcast ACTION_AUDIO_BECOMING_NOISY")).printLog(TAG));
         sendBroadcastToAll(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY));
     }
 
@@ -7235,7 +7257,7 @@
     // - wired: logged before onSetWiredDeviceConnectionState() is executed
     // - A2DP: logged at reception of method call
     final private AudioEventLogger mDeviceLogger = new AudioEventLogger(
-            LOG_NB_EVENTS_DEVICE_CONNECTION, "wired/A2DP device connection");
+            LOG_NB_EVENTS_DEVICE_CONNECTION, "wired/A2DP/hearing aid device connection");
 
     final private AudioEventLogger mForceUseLogger = new AudioEventLogger(
             LOG_NB_EVENTS_FORCE_USE,
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index fa22b84..87cf9c4 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -19,6 +19,7 @@
 import static android.Manifest.permission.USE_BIOMETRIC;
 import static android.Manifest.permission.USE_FINGERPRINT;
 
+import android.app.AppOpsManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.hardware.biometrics.BiometricAuthenticator;
@@ -38,6 +39,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.util.Slog;
 
 import com.android.internal.R;
@@ -80,6 +82,7 @@
             BIOMETRIC_FACE
     };
 
+    private final AppOpsManager mAppOps;
     private final Handler mHandler;
     private final boolean mHasFeatureFingerprint;
     private final boolean mHasFeatureIris;
@@ -154,9 +157,18 @@
                     } else if (mCurrentModality == BIOMETRIC_IRIS) {
                         Slog.w(TAG, "Unsupported modality");
                     } else if (mCurrentModality == BIOMETRIC_FACE) {
-                        mFaceService.authenticateFromService(true /* requireConfirmation */, token,
-                                sessionId, userId, receiver, flags, opPackageName, bundle,
-                                dialogReceiver, callingUid, callingPid, callingUserId);
+                        // If the user disabled face for apps, return ERROR_HW_UNAVAILABLE
+                        if (isFaceEnabledForApps()) {
+                            receiver.onError(0 /* deviceId */,
+                                    BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
+                                    FaceManager.getErrorString(getContext(),
+                                            BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
+                                            0 /* vendorCode */));
+                        } else {
+                            mFaceService.authenticateFromService(true /* requireConfirmation */,
+                                    token, sessionId, userId, receiver, flags, opPackageName,
+                                    bundle, dialogReceiver, callingUid, callingPid, callingUserId);
+                        }
                     } else {
                         Slog.w(TAG, "Unsupported modality");
                     }
@@ -166,6 +178,15 @@
             });
         }
 
+        private boolean isFaceEnabledForApps() {
+            // TODO: maybe cache this and eliminate duplicated code with KeyguardUpdateMonitor
+            return Settings.Secure.getIntForUser(
+                    getContext().getContentResolver(),
+                    Settings.Secure.FACE_UNLOCK_APP_ENABLED,
+                    1 /* default */,
+                    UserHandle.USER_CURRENT) == 0;
+        }
+
         @Override // Binder call
         public void cancelAuthentication(IBinder token, String opPackageName)
                 throws RemoteException {
@@ -200,14 +221,20 @@
         }
 
         @Override // Binder call
-        public boolean hasEnrolledBiometrics() {
+        public boolean hasEnrolledBiometrics(String opPackageName) {
             checkPermission();
 
-            boolean hasEnrolled = false;
+            if (mAppOps.noteOp(AppOpsManager.OP_USE_BIOMETRIC, Binder.getCallingUid(),
+                    opPackageName) != AppOpsManager.MODE_ALLOWED) {
+                Slog.w(TAG, "Rejecting " + opPackageName + "; permission denied");
+                throw new SecurityException("Permission denied");
+            }
+
             final long ident = Binder.clearCallingIdentity();
+            boolean hasEnrolled = false;
             try {
-                // Note: On devices with multi-modal authentication, the selection logic will need to
-                // be updated.
+                // Note: On devices with multi-modal authentication, the selection logic will need
+                // to be updated.
                 for (int i = 0; i < mAuthenticators.size(); i++) {
                     if (mAuthenticators.get(i).getAuthenticator().hasEnrolledTemplates()) {
                         hasEnrolled = true;
@@ -241,6 +268,7 @@
     public BiometricService(Context context) {
         super(context);
 
+        mAppOps = context.getSystemService(AppOpsManager.class);
         mHandler = new Handler(Looper.getMainLooper());
 
         final PackageManager pm = context.getPackageManager();
diff --git a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
index b3c7c19..6a22193 100644
--- a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
+++ b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
@@ -84,7 +84,6 @@
 
     private final Context mContext;
     private final String mKeyguardPackage;
-    private final AppOpsManager mAppOps;
     private final SparseBooleanArray mTimedLockoutCleared;
     private final SparseIntArray mFailedAttempts;
     private final IActivityTaskManager mActivityTaskManager;
@@ -102,6 +101,7 @@
             Collections.synchronizedMap(new HashMap<>());
     protected final ResetFailedAttemptsForUserRunnable mResetFailedAttemptsForCurrentUserRunnable =
             new ResetFailedAttemptsForUserRunnable();
+    protected final AppOpsManager mAppOps;
     protected final H mHandler = new H();
 
     private ClientMonitor mCurrentClient;
@@ -206,11 +206,9 @@
     protected abstract void checkUseBiometricPermission();
 
     /**
-     * @return Returns one of the {@link AppOpsManager} constants which pertains to the specific
-     *         biometric service.
+     * Checks if the caller passes the app ops check
      */
-    protected abstract int getAppOp();
-
+    protected abstract boolean checkAppOps(int uid, String opPackageName);
 
     /**
      * Notifies clients of any change in the biometric state (active / idle). This is mainly for
@@ -822,10 +820,11 @@
             Slog.w(getTag(), "Rejecting " + opPackageName + "; not a current user or profile");
             return false;
         }
-        if (mAppOps.noteOp(getAppOp(), uid, opPackageName) != AppOpsManager.MODE_ALLOWED) {
+        if (!checkAppOps(uid, opPackageName)) {
             Slog.w(getTag(), "Rejecting " + opPackageName + "; permission denied");
             return false;
         }
+
         if (requireForeground && !(isForegroundActivity(uid, pid) || isCurrentClient(
                 opPackageName))) {
             Slog.w(getTag(), "Rejecting " + opPackageName + "; not in foreground");
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 75cdcf0..f6af52a 100644
--- a/services/core/java/com/android/server/biometrics/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/face/FaceService.java
@@ -28,10 +28,11 @@
 import android.hardware.biometrics.BiometricAuthenticator;
 import android.hardware.biometrics.BiometricConstants;
 import android.hardware.biometrics.IBiometricPromptReceiver;
-import android.hardware.biometrics.IBiometricServiceReceiver;
 import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
+import android.hardware.biometrics.IBiometricServiceReceiver;
 import android.hardware.biometrics.face.V1_0.IBiometricsFace;
 import android.hardware.biometrics.face.V1_0.IBiometricsFaceClientCallback;
+import android.hardware.biometrics.face.V1_0.Status;
 import android.hardware.face.Face;
 import android.hardware.face.FaceManager;
 import android.hardware.face.IFaceService;
@@ -82,6 +83,7 @@
             "com.android.server.biometrics.face.ACTION_LOCKOUT_RESET";
     private static final int MAX_FAILED_ATTEMPTS_LOCKOUT_TIMED = 3;
     private static final int MAX_FAILED_ATTEMPTS_LOCKOUT_PERMANENT = 12;
+    private static final int CHALLENGE_TIMEOUT_SEC = 600; // 10 minutes
 
     private final class FaceAuthClient extends AuthenticationClientImpl {
         public FaceAuthClient(Context context,
@@ -120,15 +122,15 @@
          * The following methods contain common code which is shared in biometrics/common.
          */
         @Override // Binder call
-        public long preEnroll(IBinder token) {
+        public long generateChallenge(IBinder token) {
             checkPermission(MANAGE_BIOMETRIC);
-            return startPreEnroll(token);
+            return startGenerateChallenge(token);
         }
 
         @Override // Binder call
-        public int postEnroll(IBinder token) {
+        public int revokeChallenge(IBinder token) {
             checkPermission(MANAGE_BIOMETRIC);
-            return startPostEnroll(token);
+            return startRevokeChallenge(token);
         }
 
         @Override // Binder call
@@ -345,6 +347,45 @@
             // TODO: confirm security token when we move timeout management into the HAL layer.
             mHandler.post(mResetFailedAttemptsForCurrentUserRunnable);
         }
+
+        @Override
+        public int setRequireAttention(boolean requireAttention, final byte[] token) {
+            checkPermission(MANAGE_BIOMETRIC);
+
+            final ArrayList<Byte> byteToken = new ArrayList<>();
+            for (int i = 0; i < token.length; i++) {
+                byteToken.add(token[i]);
+            }
+
+            int result;
+            try {
+                result = mDaemon != null ? mDaemon.setRequireAttention(requireAttention, byteToken)
+                        : Status.INTERNAL_ERROR;
+            } catch (RemoteException e) {
+                Slog.e(getTag(), "Unable to setRequireAttention to " + requireAttention);
+                result = Status.INTERNAL_ERROR;
+            }
+
+            return result;
+        }
+
+        @Override
+        public boolean getRequireAttention(final byte[] token) {
+            checkPermission(MANAGE_BIOMETRIC);
+
+            final ArrayList<Byte> byteToken = new ArrayList<>();
+            for (int i = 0; i < token.length; i++) {
+                byteToken.add(token[i]);
+            }
+
+            boolean result = true;
+            try {
+                result = mDaemon != null ? mDaemon.getRequireAttention(byteToken).value : true;
+            } catch (RemoteException e) {
+                Slog.e(getTag(), "Unable to getRequireAttention");
+            }
+            return result;
+        }
     }
 
     /**
@@ -730,8 +771,9 @@
     }
 
     @Override
-    protected int getAppOp() {
-        return AppOpsManager.OP_USE_FACE;
+    protected boolean checkAppOps(int uid, String opPackageName) {
+        return mAppOps.noteOp(AppOpsManager.OP_USE_BIOMETRIC, uid, opPackageName)
+                == AppOpsManager.MODE_ALLOWED;
     }
 
     @Override
@@ -777,30 +819,30 @@
         return mDaemon;
     }
 
-    private long startPreEnroll(IBinder token) {
+    private long startGenerateChallenge(IBinder token) {
         IBiometricsFace daemon = getFaceDaemon();
         if (daemon == null) {
-            Slog.w(TAG, "startPreEnroll: no face HAL!");
+            Slog.w(TAG, "startGenerateChallenge: no face HAL!");
             return 0;
         }
         try {
-            return daemon.generateChallenge().value;
+            return daemon.generateChallenge(CHALLENGE_TIMEOUT_SEC).value;
         } catch (RemoteException e) {
-            Slog.e(TAG, "startPreEnroll failed", e);
+            Slog.e(TAG, "startGenerateChallenge failed", e);
         }
         return 0;
     }
 
-    private int startPostEnroll(IBinder token) {
+    private int startRevokeChallenge(IBinder token) {
         IBiometricsFace daemon = getFaceDaemon();
         if (daemon == null) {
-            Slog.w(TAG, "startPostEnroll: no face HAL!");
+            Slog.w(TAG, "startRevokeChallenge: no face HAL!");
             return 0;
         }
         try {
             return daemon.revokeChallenge();
         } catch (RemoteException e) {
-            Slog.e(TAG, "startPostEnroll failed", e);
+            Slog.e(TAG, "startRevokeChallenge failed", e);
         }
         return 0;
     }
diff --git a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
index d3ae064..b0b788f 100644
--- a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
@@ -902,8 +902,16 @@
     }
 
     @Override
-    protected int getAppOp() {
-        return AppOpsManager.OP_USE_FINGERPRINT;
+    protected boolean checkAppOps(int uid, String opPackageName) {
+        boolean appOpsOk = false;
+        if (mAppOps.noteOp(AppOpsManager.OP_USE_BIOMETRIC, uid, opPackageName)
+                == AppOpsManager.MODE_ALLOWED) {
+            appOpsOk = true;
+        } else if (mAppOps.noteOp(AppOpsManager.OP_USE_FINGERPRINT, uid, opPackageName)
+                == AppOpsManager.MODE_ALLOWED) {
+            appOpsOk = true;
+        }
+        return appOpsOk;
     }
 
     @Override
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index 873a8e3..a769590 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -629,6 +629,11 @@
         if (mAppOps.noteOp(op, callingUid, callingPackage) != AppOpsManager.MODE_ALLOWED) {
             return false;
         }
+        // Shell can access the clipboard for testing purposes.
+        if (mPm.checkPermission(android.Manifest.permission.READ_CLIPBOARD_IN_BACKGROUND,
+                    callingPackage) == PackageManager.PERMISSION_GRANTED) {
+            return true;
+        }
         // The default IME is always allowed to access the clipboard.
         String defaultIme = Settings.Secure.getStringForUser(getContext().getContentResolver(),
                 Settings.Secure.DEFAULT_INPUT_METHOD, UserHandle.getUserId(callingUid));
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 2a80f0e..48082b6 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -163,8 +163,8 @@
     // TODO: create separate trackers for each unique VPN to support
     // automated reconnection
 
-    private Context mContext;
-    private NetworkInfo mNetworkInfo;
+    private final Context mContext;
+    private final NetworkInfo mNetworkInfo;
     private String mPackage;
     private int mOwnerUID;
     private String mInterface;
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
index 2b1d919..1e6bb04 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
@@ -320,9 +320,8 @@
     }
 
     private static boolean getEnableLegacyDhcpServer(Context ctx) {
-        // TODO: make the default false (0) and update javadoc in Settings.java
         final ContentResolver cr = ctx.getContentResolver();
-        final int intVal = Settings.Global.getInt(cr, TETHER_ENABLE_LEGACY_DHCP_SERVER, 1);
+        final int intVal = Settings.Global.getInt(cr, TETHER_ENABLE_LEGACY_DHCP_SERVER, 0);
         return intVal != 0;
     }
 
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index d8d650b..5698fdf 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -1226,7 +1226,7 @@
 
         if (userId == UserHandle.USER_ALL) {
             mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.INTERACT_ACROSS_USERS_FULL, TAG);
+                    Manifest.permission.INTERACT_ACROSS_USERS_FULL, "No access to " + uri);
         } else if (userId < 0) {
             throw new IllegalArgumentException("Invalid user: " + userId);
         } else if (userId != UserHandle.getCallingUserId()) {
@@ -1247,7 +1247,7 @@
                             ? (Manifest.permission.INTERACT_ACROSS_USERS_FULL + " or " +
                                     Manifest.permission.INTERACT_ACROSS_USERS)
                             : Manifest.permission.INTERACT_ACROSS_USERS_FULL;
-                    throw new SecurityException(TAG + "Neither user " + uid
+                    throw new SecurityException("No access to " + uri + ": neither user " + uid
                             + " nor current process has " + permissions);
                 }
             }
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 6f5f90a..a9b0d5c 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -1976,7 +1976,7 @@
             throw new IllegalArgumentException("Unknown id: " + mCurMethodId);
         }
 
-        unbindCurrentMethodLocked(true);
+        unbindCurrentMethodLocked();
 
         mCurIntent = new Intent(InputMethod.SERVICE_INTERFACE);
         mCurIntent.setComponent(info.getComponent());
@@ -2020,7 +2020,7 @@
                 mCurMethod = IInputMethod.Stub.asInterface(service);
                 if (mCurToken == null) {
                     Slog.w(TAG, "Service connected without a token!");
-                    unbindCurrentMethodLocked(false);
+                    unbindCurrentMethodLocked();
                     return;
                 }
                 if (DEBUG) Slog.v(TAG, "Initiating attach with token: " + mCurToken);
@@ -2059,7 +2059,7 @@
         channel.dispose();
     }
 
-    void unbindCurrentMethodLocked(boolean savePosition) {
+    void unbindCurrentMethodLocked() {
         if (mVisibleBound) {
             mContext.unbindService(mVisibleConnection);
             mVisibleBound = false;
@@ -2076,10 +2076,6 @@
                     Slog.v(TAG, "Removing window token: " + mCurToken + " for display: "
                             + mCurTokenDisplayId);
                 }
-                if ((mImeWindowVis & InputMethodService.IME_ACTIVE) != 0 && savePosition) {
-                    // The current IME is shown. Hence an IME switch (transition) is happening.
-                    mWindowManagerInternal.saveLastInputMethodWindowForTransition();
-                }
                 mIWindowManager.removeWindowToken(mCurToken, mCurTokenDisplayId);
             } catch (RemoteException e) {
             }
@@ -2094,7 +2090,7 @@
     void resetCurrentMethodAndClient(
             /* @InputMethodClient.UnbindReason */ final int unbindClientReason) {
         mCurMethodId = null;
-        unbindCurrentMethodLocked(false);
+        unbindCurrentMethodLocked();
         unbindCurrentClientLocked(unbindClientReason);
     }
 
@@ -2865,7 +2861,7 @@
                                 final int newFocusDisplayId =
                                         mWindowManagerInternal.getDisplayIdForWindow(windowToken);
                                 if (newFocusDisplayId != mCurTokenDisplayId) {
-                                    unbindCurrentMethodLocked(false);
+                                    unbindCurrentMethodLocked();
                                 }
                             }
                         } else if (isTextEditor && doAutoShow && (softInputMode &
@@ -3237,19 +3233,6 @@
     }
 
     @BinderThread
-    private void clearLastInputMethodWindowForTransition(IBinder token) {
-        if (!calledFromValidUser()) {
-            return;
-        }
-        synchronized (mMethodMap) {
-            if (!calledWithValidToken(token)) {
-                return;
-            }
-        }
-        mWindowManagerInternal.clearLastInputMethodWindowForTransition();
-    }
-
-    @BinderThread
     private void notifyUserAction(@NonNull IBinder token) {
         if (DEBUG) {
             Slog.d(TAG, "Got the notification of a user action.");
@@ -4957,7 +4940,7 @@
             try {
                 synchronized (mMethodMap) {
                     hideCurrentInputLocked(0, null);
-                    unbindCurrentMethodLocked(false);
+                    unbindCurrentMethodLocked();
                     // Reset the current IME
                     resetSelectedInputMethodAndSubtypeLocked(null);
                     // Also reset the settings of the current IME
@@ -5030,12 +5013,6 @@
 
         @BinderThread
         @Override
-        public void clearLastInputMethodWindowForTransition() {
-            mImms.clearLastInputMethodWindowForTransition(mToken);
-        }
-
-        @BinderThread
-        @Override
         public IInputContentUriToken createInputContentUriToken(Uri contentUri,
                 String packageName) {
             return mImms.createInputContentUriToken(mToken, contentUri, packageName);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index e53eeb0..5005ea7 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1152,15 +1152,18 @@
                 // turn off LED when user passes through lock screen
                 mNotificationLight.turnOff();
             } else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
-                final int user = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
-                // reload per-user settings
-                mSettingsObserver.update(null);
+                final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
                 mUserProfiles.updateCache(context);
-                // Refresh managed services
-                mConditionProviders.onUserSwitched(user);
-                mListeners.onUserSwitched(user);
-                mAssistants.onUserSwitched(user);
-                mZenModeHelper.onUserSwitched(user);
+                if (!mUserProfiles.isManagedProfile(userId)) {
+                    // reload per-user settings
+                    mSettingsObserver.update(null);
+                    // Refresh managed services
+                    mConditionProviders.onUserSwitched(userId);
+                    mListeners.onUserSwitched(userId);
+                    mZenModeHelper.onUserSwitched(userId);
+                }
+                // assistant is the only thing that cares about managed profiles specifically
+                mAssistants.onUserSwitched(userId);
             } else if (action.equals(Intent.ACTION_USER_ADDED)) {
                 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
                 if (userId != USER_NULL) {
@@ -1170,20 +1173,23 @@
                     }
                 }
             } else if (action.equals(Intent.ACTION_USER_REMOVED)) {
-                final int user = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
+                final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
                 mUserProfiles.updateCache(context);
-                mZenModeHelper.onUserRemoved(user);
-                mPreferencesHelper.onUserRemoved(user);
-                mListeners.onUserRemoved(user);
-                mConditionProviders.onUserRemoved(user);
-                mAssistants.onUserRemoved(user);
+                mZenModeHelper.onUserRemoved(userId);
+                mPreferencesHelper.onUserRemoved(userId);
+                mListeners.onUserRemoved(userId);
+                mConditionProviders.onUserRemoved(userId);
+                mAssistants.onUserRemoved(userId);
                 savePolicyFile();
             } else if (action.equals(Intent.ACTION_USER_UNLOCKED)) {
-                final int user = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
-                mConditionProviders.onUserUnlocked(user);
-                mListeners.onUserUnlocked(user);
-                mAssistants.onUserUnlocked(user);
-                mZenModeHelper.onUserUnlocked(user);
+                final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
+                mUserProfiles.updateCache(context);
+                mAssistants.onUserUnlocked(userId);
+                if (!mUserProfiles.isManagedProfile(userId)) {
+                    mConditionProviders.onUserUnlocked(userId);
+                    mListeners.onUserUnlocked(userId);
+                    mZenModeHelper.onUserUnlocked(userId);
+                }
             }
         }
     };
@@ -2391,7 +2397,7 @@
                 String pkg) {
             checkCallerIsSystemOrSameApp(pkg);
             return mPreferencesHelper.getNotificationChannelGroups(
-                    pkg, Binder.getCallingUid(), false, false);
+                    pkg, Binder.getCallingUid(), false, false, true);
         }
 
         @Override
@@ -2467,7 +2473,8 @@
         public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroupsForPackage(
                 String pkg, int uid, boolean includeDeleted) {
             checkCallerIsSystem();
-            return mPreferencesHelper.getNotificationChannelGroups(pkg, uid, includeDeleted, true);
+            return mPreferencesHelper.getNotificationChannelGroups(
+                    pkg, uid, includeDeleted, true, false);
         }
 
         @Override
@@ -4277,8 +4284,13 @@
     @VisibleForTesting
     int resolveNotificationUid(String callingPkg, String targetPkg,
             int callingUid, int userId) {
+        if (userId == UserHandle.USER_ALL) {
+            userId = USER_SYSTEM;
+        }
         // posted from app A on behalf of app A
-        if (isCallerSameApp(targetPkg, callingUid) && TextUtils.equals(callingPkg, targetPkg)) {
+        if (isCallerSameApp(targetPkg, callingUid, userId)
+                && (TextUtils.equals(callingPkg, targetPkg)
+                || isCallerSameApp(callingPkg, callingUid, userId))) {
             return callingUid;
         }
 
@@ -4295,7 +4307,8 @@
             return targetUid;
         }
 
-        throw new SecurityException("Caller " + callingUid + " cannot post for pkg " + targetPkg);
+        throw new SecurityException("Caller " + callingPkg + ":" + callingUid
+                + " cannot post for pkg " + targetPkg + " in user " + userId);
     }
 
     /**
@@ -4315,7 +4328,7 @@
         if (!isSystemNotification && !isNotificationFromListener) {
             synchronized (mNotificationLock) {
                 if (mNotificationsByKey.get(r.sbn.getKey()) == null
-                        && isCallerInstantApp(pkg, callingUid)) {
+                        && isCallerInstantApp(pkg, Binder.getCallingUid(), userId)) {
                     // Ephemeral apps have some special constraints for notifications.
                     // They are not allowed to create new notifications however they are allowed to
                     // update notifications created by the system (e.g. a foreground service
@@ -4721,7 +4734,8 @@
                     if (notification.getSmallIcon() != null) {
                         StatusBarNotification oldSbn = (old != null) ? old.sbn : null;
                         mListeners.notifyPostedLocked(r, old);
-                        if (oldSbn == null || !Objects.equals(oldSbn.getGroup(), n.getGroup())) {
+                        if ((oldSbn == null || !Objects.equals(oldSbn.getGroup(), n.getGroup()))
+                                && !isCritical(r)) {
                             mHandler.post(new Runnable() {
                                 @Override
                                 public void run() {
@@ -4891,6 +4905,19 @@
     }
 
     /**
+     * Check if the notification is classified as critical.
+     *
+     * @param record the record to test for criticality
+     * @return {@code true} if notification is considered critical
+     *
+     * @see CriticalNotificationExtractor for criteria
+     */
+    private boolean isCritical(NotificationRecord record) {
+        // 0 is the most critical
+        return record.getCriticality() < CriticalNotificationExtractor.NORMAL;
+    }
+
+    /**
      * Keeps the last 5 packages that have notified, by user.
      */
     @GuardedBy("mNotificationLock")
@@ -6409,7 +6436,8 @@
         }
     }
 
-    private boolean isCallerInstantApp(String pkg, int callingUid) {
+    @VisibleForTesting
+    boolean isCallerInstantApp(String pkg, int callingUid, int userId) {
         // System is always allowed to act for ephemeral apps.
         if (isUidSystemOrPhone(callingUid)) {
             return false;
@@ -6418,8 +6446,7 @@
         mAppOps.checkPackage(callingUid, pkg);
 
         try {
-            ApplicationInfo ai = mPackageManager.getApplicationInfo(pkg, 0,
-                    UserHandle.getCallingUserId());
+            ApplicationInfo ai = mPackageManager.getApplicationInfo(pkg, 0, userId);
             if (ai == null) {
                 throw new SecurityException("Unknown package " + pkg);
             }
@@ -6431,13 +6458,13 @@
     }
 
     private void checkCallerIsSameApp(String pkg) {
-        checkCallerIsSameApp(pkg, Binder.getCallingUid());
+        checkCallerIsSameApp(pkg, Binder.getCallingUid(), UserHandle.getCallingUserId());
     }
 
-    private void checkCallerIsSameApp(String pkg, int uid) {
+    private void checkCallerIsSameApp(String pkg, int uid, int userId) {
         try {
             ApplicationInfo ai = mPackageManager.getApplicationInfo(
-                    pkg, 0, UserHandle.getCallingUserId());
+                    pkg, 0, userId);
             if (ai == null) {
                 throw new SecurityException("Unknown package " + pkg);
             }
@@ -6459,9 +6486,9 @@
         }
     }
 
-    private boolean isCallerSameApp(String pkg, int uid) {
+    private boolean isCallerSameApp(String pkg, int uid, int userId) {
         try {
-            checkCallerIsSameApp(pkg, uid);
+            checkCallerIsSameApp(pkg, uid, userId);
             return true;
         } catch (SecurityException e) {
             return false;
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 13ff6e8..3a0ab77 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -755,7 +755,7 @@
 
     @Override
     public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroups(String pkg,
-            int uid, boolean includeDeleted, boolean includeNonGrouped) {
+            int uid, boolean includeDeleted, boolean includeNonGrouped, boolean includeEmpty) {
         Preconditions.checkNotNull(pkg);
         Map<String, NotificationChannelGroup> groups = new ArrayMap<>();
         PackagePreferences r = getPackagePreferences(pkg, uid);
@@ -786,6 +786,13 @@
         if (includeNonGrouped && nonGrouped.getChannels().size() > 0) {
             groups.put(null, nonGrouped);
         }
+        if (includeEmpty) {
+            for (NotificationChannelGroup group : r.groups.values()) {
+                if (!groups.containsKey(group.getId())) {
+                    groups.put(group.getId(), group);
+                }
+            }
+        }
         return new ParceledListSlice<>(new ArrayList<>(groups.values()));
     }
 
diff --git a/services/core/java/com/android/server/notification/RankingConfig.java b/services/core/java/com/android/server/notification/RankingConfig.java
index af64683..605348b 100644
--- a/services/core/java/com/android/server/notification/RankingConfig.java
+++ b/services/core/java/com/android/server/notification/RankingConfig.java
@@ -36,7 +36,7 @@
     void createNotificationChannelGroup(String pkg, int uid, NotificationChannelGroup group,
             boolean fromTargetApp);
     ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroups(String pkg,
-            int uid, boolean includeDeleted, boolean includeNonGrouped);
+            int uid, boolean includeDeleted, boolean includeNonGrouped, boolean includeEmpty);
     void createNotificationChannel(String pkg, int uid, NotificationChannel channel,
             boolean fromTargetApp, boolean hasDndAccess);
     void updateNotificationChannel(String pkg, int uid, NotificationChannel channel, boolean fromUser);
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 25f52e7..760f155 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -430,7 +430,7 @@
         for (ZenRule defaultRule : mDefaultConfig.automaticRules.values()) {
             ZenRule currRule = mConfig.automaticRules.get(defaultRule.id);
             // if default rule wasn't modified, use localized name instead of previous
-            if (!currRule.modified && !defaultRule.name.equals(currRule.name)) {
+            if (currRule != null && !currRule.modified && !defaultRule.name.equals(currRule.name)) {
                 if (canManageAutomaticZenRule(defaultRule)) {
                     if (DEBUG) Slog.d(TAG, "Locale change - updating default zen rule name "
                             + "from " + currRule.name + " to " + defaultRule.name);
@@ -1161,13 +1161,13 @@
         final boolean showNotification = mIsBootComplete
                 && zen != Global.ZEN_MODE_OFF
                 && !isWatch
-                && Settings.Global.getInt(mContext.getContentResolver(),
+                && Settings.Secure.getInt(mContext.getContentResolver(),
                 Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0) != 0
-                && Settings.Global.getInt(mContext.getContentResolver(),
+                && Settings.Secure.getInt(mContext.getContentResolver(),
                 Settings.Secure.ZEN_SETTINGS_UPDATED, 0) != 1;
 
         if (isWatch) {
-            Settings.Global.putInt(mContext.getContentResolver(),
+            Settings.Secure.putInt(mContext.getContentResolver(),
                     Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
         }
 
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 8f2833f..006ea75 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -21,6 +21,7 @@
 import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
 import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
 import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
+import static android.content.pm.PackageManager.INSTALL_FAILED_MISSING_SPLIT;
 import static android.content.pm.PackageParser.APK_FILE_EXTENSION;
 import static android.system.OsConstants.O_CREAT;
 import static android.system.OsConstants.O_RDONLY;
@@ -1060,6 +1061,7 @@
     @GuardedBy("mLock")
     private void validateInstallLocked(@Nullable PackageInfo pkgInfo)
             throws PackageManagerException {
+        ApkLite baseApk = null;
         mPackageName = null;
         mVersionCode = -1;
         mSigningDetails = PackageParser.SigningDetails.UNKNOWN;
@@ -1136,6 +1138,7 @@
             // Base is coming from session
             if (apk.splitName == null) {
                 mResolvedBaseFile = targetFile;
+                baseApk = apk;
             }
 
             mResolvedStagedFiles.add(targetFile);
@@ -1221,6 +1224,7 @@
                 if (baseDexMetadataFile != null) {
                     mResolvedInheritedFiles.add(baseDexMetadataFile);
                 }
+                baseApk = existingBase;
             }
 
             // Inherit splits if not overridden
@@ -1300,6 +1304,10 @@
                 }
             }
         }
+        if (baseApk.isSplitRequired && stagedSplits.size() <= 1) {
+            throw new PackageManagerException(INSTALL_FAILED_MISSING_SPLIT,
+                    "Missing split for " + mPackageName);
+        }
     }
 
     @GuardedBy("mLock")
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 91af0ec..329b1da 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -232,6 +232,7 @@
 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;
@@ -2912,13 +2913,15 @@
             if (mIsUpgrade) {
                 final int callingUid = getCallingUid();
 
-                final int numSplitPerms = PackageParser.SPLIT_PERMISSIONS.length;
+                final List<PermissionManager.SplitPermissionInfo> splitPermissions =
+                        mContext.getSystemService(PermissionManager.class).getSplitPermissions();
+                final int numSplitPerms = splitPermissions.size();
                 for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) {
-                    final PackageParser.SplitPermissionInfo splitPerm =
-                            PackageParser.SPLIT_PERMISSIONS[splitPermNum];
-                    final String rootPerm = splitPerm.rootPerm;
+                    final PermissionManager.SplitPermissionInfo splitPerm =
+                            splitPermissions.get(splitPermNum);
+                    final String rootPerm = splitPerm.getRootPermission();
 
-                    if (preUpgradeSdkVersion >= splitPerm.targetSdk) {
+                    if (preUpgradeSdkVersion >= splitPerm.getTargetSdk()) {
                         continue;
                     }
 
@@ -2926,7 +2929,7 @@
                     for (int packageNum = 0; packageNum < numPackages; packageNum++) {
                         final PackageParser.Package pkg = mPackages.valueAt(packageNum);
 
-                        if (pkg.applicationInfo.targetSdkVersion >= splitPerm.targetSdk
+                        if (pkg.applicationInfo.targetSdkVersion >= splitPerm.getTargetSdk()
                                 || !pkg.requestedPermissions.contains(rootPerm)) {
                             continue;
                         }
@@ -2938,7 +2941,7 @@
                             continue;
                         }
 
-                        final String[] newPerms = splitPerm.newPerms;
+                        final String[] newPerms = splitPerm.getNewPermissions();
 
                         final int numNewPerms = newPerms.length;
                         for (int newPermNum = 0; newPermNum < numNewPerms; newPermNum++) {
@@ -8471,7 +8474,7 @@
     private boolean canSkipFullApkVerification(String apkPath) {
         final byte[] rootHashObserved;
         try {
-            rootHashObserved = VerityUtils.generateFsverityRootHash(apkPath);
+            rootHashObserved = VerityUtils.generateApkVerityRootHash(apkPath);
             if (rootHashObserved == null) {
                 return false;  // APK does not contain Merkle tree root hash.
             }
@@ -15336,7 +15339,9 @@
             // This needs to be done before invoking dexopt so that any install-time profile
             // can be used for optimizations.
             mArtManagerService.prepareAppProfiles(
-                    pkg, resolveUserIds(reconciledPkg.installForUser.getIdentifier()));
+                    pkg,
+                    resolveUserIds(reconciledPkg.installForUser.getIdentifier()),
+                    /* updateReferenceProfileContent= */ true);
 
             // Check whether we need to dexopt the app.
             //
@@ -15999,12 +16004,14 @@
             }
             if (apkPath != null) {
                 final VerityUtils.SetupResult result =
-                        VerityUtils.generateApkVeritySetupData(apkPath);
+                        VerityUtils.generateApkVeritySetupData(apkPath, null /* signaturePath */,
+                                true /* skipSigningBlock */);
                 if (result.isOk()) {
                     if (Build.IS_DEBUGGABLE) Slog.i(TAG, "Enabling apk verity to " + apkPath);
                     FileDescriptor fd = result.getUnownedFileDescriptor();
                     try {
-                        final byte[] signedRootHash = VerityUtils.generateFsverityRootHash(apkPath);
+                        final byte[] signedRootHash =
+                                VerityUtils.generateApkVerityRootHash(apkPath);
                         mInstaller.installApkVerity(apkPath, fd, result.getContentSize());
                         mInstaller.assertFsverityRootHashMatches(apkPath, signedRootHash);
                     } catch (InstallerException | IOException | DigestException |
@@ -21184,8 +21191,18 @@
         //
         // We also have to cover non system users because we do not call the usual install package
         // methods for them.
+        //
+        // NOTE: in order to speed up first boot time we only create the current profile and do not
+        // update the content of the reference profile. A system image should already be configured
+        // with the right profile keys and the profiles for the speed-profile prebuilds should
+        // already be copied. That's done in #performDexOptUpgrade.
+        //
+        // TODO(calin, mathieuc): We should use .dm files for prebuilds profiles instead of
+        // manually copying them in #performDexOptUpgrade. When we do that we should have a more
+        // granular check here and only update the existing profiles.
         if (mIsUpgrade || mFirstBoot || (userId != UserHandle.USER_SYSTEM)) {
-            mArtManagerService.prepareAppProfiles(pkg, userId);
+            mArtManagerService.prepareAppProfiles(pkg, userId,
+                /* updateReferenceProfileContent= */ false);
         }
 
         if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 && ceDataInode != -1) {
@@ -23082,7 +23099,9 @@
                 return false;
             }
         }
-        if (sUserManager.hasUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, userId)) {
+        if (sUserManager.hasUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, userId)
+                  || sUserManager.hasUserRestriction(
+                        UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY, userId)) {
             return false;
         }
         if (mExternalSourcesPolicy != null) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index a9f1b5c..93729d1 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -124,6 +124,7 @@
     int mTargetUser;
     boolean mBrief;
     boolean mComponents;
+    int mQueryFlags;
 
     PackageManagerShellCommand(PackageManagerService service) {
         mInterface = service;
@@ -739,6 +740,9 @@
                 } else if ("--components".equals(opt)) {
                     mComponents = true;
                     return true;
+                } else if ("--query-flags".equals(opt)) {
+                    mQueryFlags = Integer.decode(cmd.getNextArgRequired());
+                    return true;
                 }
                 return false;
             }
@@ -784,7 +788,8 @@
             throw new RuntimeException(e.getMessage(), e);
         }
         try {
-            ResolveInfo ri = mInterface.resolveIntent(intent, intent.getType(), 0, mTargetUser);
+            ResolveInfo ri = mInterface.resolveIntent(intent, intent.getType(), mQueryFlags,
+                    mTargetUser);
             PrintWriter pw = getOutPrintWriter();
             if (ri == null) {
                 pw.println("No activity found");
@@ -806,8 +811,8 @@
             throw new RuntimeException(e.getMessage(), e);
         }
         try {
-            List<ResolveInfo> result = mInterface.queryIntentActivities(intent, intent.getType(), 0,
-                    mTargetUser).getList();
+            List<ResolveInfo> result = mInterface.queryIntentActivities(intent, intent.getType(),
+                    mQueryFlags, mTargetUser).getList();
             PrintWriter pw = getOutPrintWriter();
             if (result == null || result.size() <= 0) {
                 pw.println("No activities found");
@@ -840,8 +845,8 @@
             throw new RuntimeException(e.getMessage(), e);
         }
         try {
-            List<ResolveInfo> result = mInterface.queryIntentServices(intent, intent.getType(), 0,
-                    mTargetUser).getList();
+            List<ResolveInfo> result = mInterface.queryIntentServices(intent, intent.getType(),
+                    mQueryFlags, mTargetUser).getList();
             PrintWriter pw = getOutPrintWriter();
             if (result == null || result.size() <= 0) {
                 pw.println("No services found");
@@ -874,8 +879,8 @@
             throw new RuntimeException(e.getMessage(), e);
         }
         try {
-            List<ResolveInfo> result = mInterface.queryIntentReceivers(intent, intent.getType(), 0,
-                    mTargetUser).getList();
+            List<ResolveInfo> result = mInterface.queryIntentReceivers(intent, intent.getType(),
+                    mQueryFlags, mTargetUser).getList();
             PrintWriter pw = getOutPrintWriter();
             if (result == null || result.size() <= 0) {
                 pw.println("No receivers found");
@@ -2731,16 +2736,20 @@
         pw.println("      -d: only list dangerous permissions");
         pw.println("      -u: list only the permissions users will see");
         pw.println("");
-        pw.println("  resolve-activity [--brief] [--components] [--user USER_ID] INTENT");
+        pw.println("  resolve-activity [--brief] [--components] [--query-flags FLAGS]");
+        pw.println("       [--user USER_ID] INTENT");
         pw.println("    Prints the activity that resolves to the given INTENT.");
         pw.println("");
-        pw.println("  query-activities [--brief] [--components] [--user USER_ID] INTENT");
+        pw.println("  query-activities [--brief] [--components] [--query-flags FLAGS]");
+        pw.println("       [--user USER_ID] INTENT");
         pw.println("    Prints all activities that can handle the given INTENT.");
         pw.println("");
-        pw.println("  query-services [--brief] [--components] [--user USER_ID] INTENT");
+        pw.println("  query-services [--brief] [--components] [--query-flags FLAGS]");
+        pw.println("       [--user USER_ID] INTENT");
         pw.println("    Prints all services that can handle the given INTENT.");
         pw.println("");
-        pw.println("  query-receivers [--brief] [--components] [--user USER_ID] INTENT");
+        pw.println("  query-receivers [--brief] [--components] [--query-flags FLAGS]");
+        pw.println("       [--user USER_ID] INTENT");
         pw.println("    Prints all broadcast receivers that can handle the given INTENT.");
         pw.println("");
         pw.println("  install [-lrtsfdg] [-i PACKAGE] [--user USER_ID|all|current]");
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 3f28ee6..1315502 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -16,10 +16,6 @@
 
 package com.android.server.pm;
 
-import com.google.android.collect.Sets;
-
-import com.android.internal.util.Preconditions;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
@@ -42,6 +38,10 @@
 import android.util.Slog;
 import android.util.SparseArray;
 
+import com.android.internal.util.Preconditions;
+
+import com.google.android.collect.Sets;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlSerializer;
 
@@ -77,6 +77,7 @@
             UserManager.DISALLOW_UNINSTALL_APPS,
             UserManager.DISALLOW_SHARE_LOCATION,
             UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
+            UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY,
             UserManager.DISALLOW_CONFIG_BLUETOOTH,
             UserManager.DISALLOW_BLUETOOTH,
             UserManager.DISALLOW_BLUETOOTH_SHARING,
@@ -211,7 +212,8 @@
      */
     private static final Set<String> PROFILE_GLOBAL_RESTRICTIONS = Sets.newArraySet(
             UserManager.ENSURE_VERIFY_APPS,
-            UserManager.DISALLOW_AIRPLANE_MODE
+            UserManager.DISALLOW_AIRPLANE_MODE,
+            UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY
     );
 
     /**
@@ -517,13 +519,18 @@
                                 userId);
                     }
                     break;
+                case UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY:
+                    setInstallMarketAppsRestriction(cr, userId, getNewUserRestrictionSetting(
+                            context, userId, UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
+                            newValue));
+                    break;
                 case UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES:
                     // Since Android O, the secure setting is not available to be changed by the
                     // user. Hence, when the restriction is cleared, we need to reset the state of
                     // the setting to its default value which is now 1.
-                    android.provider.Settings.Secure.putIntForUser(cr,
-                            android.provider.Settings.Secure.INSTALL_NON_MARKET_APPS,
-                            newValue ? 0 : 1, userId);
+                    setInstallMarketAppsRestriction(cr, userId, getNewUserRestrictionSetting(
+                            context, userId, UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY,
+                            newValue));
                     break;
                 case UserManager.DISALLOW_RUN_IN_BACKGROUND:
                     if (newValue) {
@@ -813,4 +820,16 @@
         }
         return false;
     }
+
+    private static void setInstallMarketAppsRestriction(ContentResolver cr, int userId,
+            int settingValue) {
+        android.provider.Settings.Secure.putIntForUser(
+                cr, android.provider.Settings.Secure.INSTALL_NON_MARKET_APPS, settingValue, userId);
+    }
+
+    private static int getNewUserRestrictionSetting(Context context, int userId,
+                String userRestriction, boolean newValue) {
+        return (newValue || UserManager.get(context).hasUserRestriction(userRestriction,
+                UserHandle.of(userId))) ? 0 : 1;
+    }
 }
diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
index 21daa39..910ea73 100644
--- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java
+++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
@@ -389,7 +389,8 @@
      *   - create the current primary profile to save time at app startup time.
      *   - copy the profiles from the associated dex metadata file to the reference profile.
      */
-    public void prepareAppProfiles(PackageParser.Package pkg, @UserIdInt int user) {
+    public void prepareAppProfiles(PackageParser.Package pkg, @UserIdInt int user,
+            boolean updateReferenceProfileContent) {
         final int appId = UserHandle.getAppId(pkg.applicationInfo.uid);
         if (user < 0) {
             Slog.wtf(TAG, "Invalid user id: " + user);
@@ -404,8 +405,14 @@
             for (int i = codePathsProfileNames.size() - 1; i >= 0; i--) {
                 String codePath = codePathsProfileNames.keyAt(i);
                 String profileName = codePathsProfileNames.valueAt(i);
-                File dexMetadata = DexMetadataHelper.findDexMetadataForFile(new File(codePath));
-                String dexMetadataPath = dexMetadata == null ? null : dexMetadata.getAbsolutePath();
+                String dexMetadataPath = null;
+                // Passing the dex metadata file to the prepare method will update the reference
+                // profile content. As such, we look for the dex metadata file only if we need to
+                // perform an update.
+                if (updateReferenceProfileContent) {
+                    File dexMetadata = DexMetadataHelper.findDexMetadataForFile(new File(codePath));
+                    dexMetadataPath = dexMetadata == null ? null : dexMetadata.getAbsolutePath();
+                }
                 synchronized (mInstaller) {
                     boolean result = mInstaller.prepareAppProfile(pkg.packageName, user, appId,
                             profileName, codePath, dexMetadataPath);
@@ -423,9 +430,10 @@
     /**
      * Prepares the app profiles for a set of users. {@see ArtManagerService#prepareAppProfiles}.
      */
-    public void prepareAppProfiles(PackageParser.Package pkg, int[] user) {
+    public void prepareAppProfiles(PackageParser.Package pkg, int[] user,
+            boolean updateReferenceProfileContent) {
         for (int i = 0; i < user.length; i++) {
-            prepareAppProfiles(pkg, user[i]);
+            prepareAppProfiles(pkg, user[i], updateReferenceProfileContent);
         }
     }
 
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 e3e1590..602ce3b 100644
--- a/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
+++ b/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
@@ -93,7 +93,7 @@
     @GuardedBy("mPackageUseInfoMap")
     private final Map<String, PackageUseInfo> mPackageUseInfoMap;
 
-    public PackageDexUsage() {
+    /* package */ PackageDexUsage() {
         super("package-dex-usage.list", "PackageDexUsage_DiskWriter", /*lock*/ false);
         mPackageUseInfoMap = new HashMap<>();
     }
@@ -116,7 +116,7 @@
      * @return true if the dex load constitutes new information, or false if this information
      *         has been seen before.
      */
-    public boolean record(String owningPackageName, String dexPath, int ownerUserId,
+    /* package */ boolean record(String owningPackageName, String dexPath, int ownerUserId,
             String loaderIsa, boolean isUsedByOtherApps, boolean primaryOrSplit,
             String loadingPackageName, String classLoaderContext) {
         if (!PackageManagerServiceUtils.checkISA(loaderIsa)) {
@@ -193,7 +193,7 @@
      * Convenience method for sync reads which does not force the user to pass a useless
      * (Void) null.
      */
-    public void read() {
+    /* package */ void read() {
       read((Void) null);
     }
 
@@ -558,7 +558,7 @@
      * Remove the usage data associated with package {@code packageName}.
      * @return true if the package usage was found and removed successfully.
      */
-    public boolean removePackage(String packageName) {
+    /* package */ boolean removePackage(String packageName) {
         synchronized (mPackageUseInfoMap) {
             return mPackageUseInfoMap.remove(packageName) != null;
         }
@@ -653,11 +653,12 @@
         return packages;
     }
 
-    public void clear() {
+    /* package */ void clear() {
         synchronized (mPackageUseInfoMap) {
             mPackageUseInfoMap.clear();
         }
     }
+
     // Creates a deep copy of the class' mPackageUseInfoMap.
     private Map<String, PackageUseInfo> clonePackageUseInfoMap() {
         Map<String, PackageUseInfo> clone = new HashMap<>();
@@ -679,7 +680,7 @@
         throw new IllegalArgumentException("Unknown bool encoding: " + bool);
     }
 
-    public String dump() {
+    /* package */ String dump() {
         StringWriter sw = new StringWriter();
         write(sw);
         return sw.toString();
diff --git a/services/core/java/com/android/server/pm/dex/TEST_MAPPING b/services/core/java/com/android/server/pm/dex/TEST_MAPPING
new file mode 100644
index 0000000..ad52559
--- /dev/null
+++ b/services/core/java/com/android/server/pm/dex/TEST_MAPPING
@@ -0,0 +1,22 @@
+{
+  "presubmit": [
+    {
+      "name": "DexLoggerTests"
+    },
+    {
+      "name": "DexManagerTests"
+    },
+    {
+      "name": "DexoptOptionsTests"
+    },
+    {
+      "name": "DexoptUtilsTest"
+    },
+    {
+      "name": "PackageDexUsageTests"
+    },
+    {
+      "name": "DexLoggerIntegrationTests"
+    }
+  ]
+}
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 3c9dd63..6f644dd 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -34,7 +34,6 @@
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageManagerInternal.PackagesProvider;
 import android.content.pm.PackageManagerInternal.SyncAdapterPackagesProvider;
-import android.content.pm.PackageParser;
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.media.RingtoneManager;
@@ -48,6 +47,7 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.storage.StorageManager;
+import android.permission.PermissionManager;
 import android.print.PrintManager;
 import android.provider.CalendarContract;
 import android.provider.ContactsContract;
@@ -1024,15 +1024,17 @@
         ApplicationInfo applicationInfo = pkg.applicationInfo;
 
         // Automatically attempt to grant split permissions to older APKs
-        final int numSplitPerms = PackageParser.SPLIT_PERMISSIONS.length;
+        final List<PermissionManager.SplitPermissionInfo> splitPermissions =
+                mContext.getSystemService(PermissionManager.class).getSplitPermissions();
+        final int numSplitPerms = splitPermissions.size();
         for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) {
-            final PackageParser.SplitPermissionInfo splitPerm =
-                    PackageParser.SPLIT_PERMISSIONS[splitPermNum];
+            final PermissionManager.SplitPermissionInfo splitPerm =
+                    splitPermissions.get(splitPermNum);
 
             if (applicationInfo != null
-                    && applicationInfo.targetSdkVersion < splitPerm.targetSdk
-                    && permissionsWithoutSplits.contains(splitPerm.rootPerm)) {
-                Collections.addAll(permissions, splitPerm.newPerms);
+                    && applicationInfo.targetSdkVersion < splitPerm.getTargetSdk()
+                    && permissionsWithoutSplits.contains(splitPerm.getRootPermission())) {
+                Collections.addAll(permissions, splitPerm.getNewPermissions());
             }
         }
 
diff --git a/services/core/java/com/android/server/pm/permission/PermissionsState.java b/services/core/java/com/android/server/pm/permission/PermissionsState.java
index 5e66bfc3..82d6b22 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionsState.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionsState.java
@@ -135,7 +135,8 @@
             final int userCount = other.mPermissionReviewRequired.size();
             for (int i = 0; i < userCount; i++) {
                 final boolean reviewRequired = other.mPermissionReviewRequired.valueAt(i);
-                mPermissionReviewRequired.put(i, reviewRequired);
+                mPermissionReviewRequired.put(other.mPermissionReviewRequired.keyAt(i),
+                        reviewRequired);
             }
         }
     }
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 91fd8d0..2557f46 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -533,8 +533,6 @@
 
     GlobalActions mGlobalActions;
     Handler mHandler;
-    WindowState mLastInputMethodWindow = null;
-    WindowState mLastInputMethodTargetWindow = null;
 
     // FIXME This state is shared between the input reader and handler thread.
     // Technically it's broken and buggy but it has been like this for many years
@@ -2830,7 +2828,8 @@
                 // Assumes it's safe to show starting windows of launched apps while
                 // the keyguard is being hidden. This is okay because starting windows never show
                 // secret information.
-                if (mKeyguardOccluded) {
+                // TODO(b/113840485): Occluded may not only happen on default display
+                if (displayId == DEFAULT_DISPLAY && mKeyguardOccluded) {
                     windowFlags |= FLAG_SHOW_WHEN_LOCKED;
                 }
             }
@@ -4732,12 +4731,6 @@
         }
         final WindowManager.LayoutParams attrs = win.getAttrs();
         final boolean isDefaultDisplay = win.isDefaultDisplay();
-        final boolean needsToOffsetInputMethodTarget =
-                (win == mLastInputMethodTargetWindow) && (mLastInputMethodWindow != null);
-        if (needsToOffsetInputMethodTarget) {
-            if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state");
-            offsetInputMethodWindowLw(mLastInputMethodWindow, displayFrames);
-        }
 
         final int type = attrs.type;
         final int fl = PolicyControl.getWindowFlags(win, attrs);
@@ -5191,7 +5184,6 @@
         // can't appear underneath them.
         if (type == TYPE_INPUT_METHOD && win.isVisibleLw()
                 && !win.getGivenInsetsPendingLw()) {
-            setLastInputMethodWindowLw(null, null);
             offsetInputMethodWindowLw(win, displayFrames);
         }
         if (type == TYPE_VOICE_INTERACTION && win.isVisibleLw()
@@ -7822,12 +7814,6 @@
     }
 
     @Override
-    public void setLastInputMethodWindowLw(WindowState ime, WindowState target) {
-        mLastInputMethodWindow = ime;
-        mLastInputMethodTargetWindow = target;
-    }
-
-    @Override
     public void setDismissImeOnBackKeyPressed(boolean newValue) {
         mDismissImeOnBackKeyPressed = newValue;
     }
@@ -7845,7 +7831,6 @@
         if (statusBar != null) {
             statusBar.setCurrentUser(newUserId);
         }
-        setLastInputMethodWindowLw(null, null);
     }
 
     @Override
@@ -8020,14 +8005,6 @@
         pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream);
                 pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen);
                 pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken);
-        if (mLastInputMethodWindow != null) {
-            pw.print(prefix); pw.print("mLastInputMethodWindow=");
-                    pw.println(mLastInputMethodWindow);
-        }
-        if (mLastInputMethodTargetWindow != null) {
-            pw.print(prefix); pw.print("mLastInputMethodTargetWindow=");
-                    pw.println(mLastInputMethodTargetWindow);
-        }
         if (mStatusBar != null) {
             pw.print(prefix); pw.print("mStatusBar=");
                     pw.print(mStatusBar); pw.print(" isStatusBarKeyguard=");
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 1fcdd63..27ab3ef 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -1536,13 +1536,6 @@
     public void lockNow(Bundle options);
 
     /**
-     * Set the last used input method window state. This state is used to make IME transition
-     * smooth.
-     * @hide
-     */
-    public void setLastInputMethodWindowLw(WindowState ime, WindowState target);
-
-    /**
      * An internal callback (from InputMethodManagerService) to notify a state change regarding
      * whether the back key should dismiss the software keyboard (IME) or not.
      *
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index 68e636a..5adc248 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -190,6 +190,8 @@
         try {
             mBatteryStats.noteInteractive(true);
         } catch (RemoteException ex) { }
+        StatsLog.write(StatsLog.INTERACTIVE_STATE_CHANGED,
+                StatsLog.INTERACTIVE_STATE_CHANGED__STATE__ON);
     }
 
     /**
@@ -401,6 +403,9 @@
             try {
                 mBatteryStats.noteInteractive(interactive);
             } catch (RemoteException ex) { }
+            StatsLog.write(StatsLog.INTERACTIVE_STATE_CHANGED,
+                    interactive ? StatsLog.INTERACTIVE_STATE_CHANGED__STATE__ON :
+                            StatsLog.INTERACTIVE_STATE_CHANGED__STATE__OFF);
 
             // Handle early behaviors.
             mInteractive = interactive;
diff --git a/services/core/java/com/android/server/security/VerityUtils.java b/services/core/java/com/android/server/security/VerityUtils.java
index 9f69702..8070f3a 100644
--- a/services/core/java/com/android/server/security/VerityUtils.java
+++ b/services/core/java/com/android/server/security/VerityUtils.java
@@ -28,40 +28,74 @@
 import android.util.apk.ApkSignatureVerifier;
 import android.util.apk.ByteBufferFactory;
 import android.util.apk.SignatureNotFoundException;
+import android.util.apk.VerityBuilder;
+
+import libcore.util.HexEncoding;
 
 import java.io.FileDescriptor;
 import java.io.IOException;
+import java.io.RandomAccessFile;
 import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.security.DigestException;
+import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.util.Arrays;
 
+import sun.security.pkcs.PKCS7;
+
 /** Provides fsverity related operations. */
 abstract public class VerityUtils {
     private static final String TAG = "VerityUtils";
 
+    /** The maximum size of signature file.  This is just to avoid potential abuse. */
+    private static final int MAX_SIGNATURE_FILE_SIZE_BYTES = 8192;
+
     private static final boolean DEBUG = false;
 
     /**
-     * Generates Merkle tree and fsverity metadata.
+     * Generates Merkle tree and fs-verity metadata.
      *
-     * @return {@code SetupResult} that contains the {@code EsetupResultCode}, and when success, the
+     * @return {@code SetupResult} that contains the result code, and when success, the
      *         {@code FileDescriptor} to read all the data from.
      */
-    public static SetupResult generateApkVeritySetupData(@NonNull String apkPath) {
-        if (DEBUG) Slog.d(TAG, "Trying to install apk verity to " + apkPath);
+    public static SetupResult generateApkVeritySetupData(@NonNull String apkPath,
+            String signaturePath, boolean skipSigningBlock) {
+        if (DEBUG) {
+            Slog.d(TAG, "Trying to install apk verity to " + apkPath + " with signature file "
+                    + signaturePath);
+        }
         SharedMemory shm = null;
         try {
-            byte[] signedRootHash = ApkSignatureVerifier.getVerityRootHash(apkPath);
-            if (signedRootHash == null) {
+            byte[] signedVerityHash;
+            if (skipSigningBlock) {
+                signedVerityHash = ApkSignatureVerifier.getVerityRootHash(apkPath);
+            } else {
+                Path path = Paths.get(signaturePath);
+                if (Files.exists(path)) {
+                    // TODO(112037636): fail early if the signing key is not in .fs-verity keyring.
+                    PKCS7 pkcs7 = new PKCS7(Files.readAllBytes(path));
+                    signedVerityHash = pkcs7.getContentInfo().getContentBytes();
+                    if (DEBUG) {
+                        Slog.d(TAG, "fs-verity measurement = " + bytesToString(signedVerityHash));
+                    }
+                } else {
+                    signedVerityHash = null;
+                }
+            }
+
+            if (signedVerityHash == null) {
                 if (DEBUG) {
-                    Slog.d(TAG, "Skip verity tree generation since there is no root hash");
+                    Slog.d(TAG, "Skip verity tree generation since there is no signed root hash");
                 }
                 return SetupResult.skipped();
             }
 
-            Pair<SharedMemory, Integer> result = generateApkVerityIntoSharedMemory(apkPath,
-                    signedRootHash);
+            Pair<SharedMemory, Integer> result = generateFsVerityIntoSharedMemory(apkPath,
+                    signaturePath, signedVerityHash, skipSigningBlock);
             shm = result.first;
             int contentSize = result.second;
             FileDescriptor rfd = shm.getFileDescriptor();
@@ -81,9 +115,9 @@
     }
 
     /**
-     * {@see ApkSignatureVerifier#generateFsverityRootHash(String)}.
+     * {@see ApkSignatureVerifier#generateApkVerityRootHash(String)}.
      */
-    public static byte[] generateFsverityRootHash(@NonNull String apkPath)
+    public static byte[] generateApkVerityRootHash(@NonNull String apkPath)
             throws NoSuchAlgorithmException, DigestException, IOException {
         return ApkSignatureVerifier.generateApkVerityRootHash(apkPath);
     }
@@ -97,22 +131,114 @@
     }
 
     /**
+     * Generates fs-verity metadata for {@code filePath} in the buffer created by {@code
+     * trackedBufferFactory}. The metadata contains the Merkle tree, fs-verity descriptor and
+     * extensions, including a PKCS#7 signature provided in {@code signaturePath}.
+     *
+     * <p>It is worthy to note that {@code trackedBufferFactory} generates a "tracked" {@code
+     * ByteBuffer}. The data will be used outside this method via the factory itself.
+     *
+     * @return fs-verity measurement of {@code filePath}, which is a SHA-256 of fs-verity descriptor
+     *         and authenticated extensions.
+     */
+    private static byte[] generateFsverityMetadata(String filePath, String signaturePath,
+            @NonNull TrackedShmBufferFactory trackedBufferFactory)
+            throws IOException, SignatureNotFoundException, SecurityException, DigestException,
+                   NoSuchAlgorithmException {
+        try (RandomAccessFile file = new RandomAccessFile(filePath, "r")) {
+            VerityBuilder.VerityResult result = VerityBuilder.generateFsVerityTree(
+                    file, trackedBufferFactory);
+
+            ByteBuffer buffer = result.verityData;
+            buffer.position(result.merkleTreeSize);
+            return generateFsverityDescriptorAndMeasurement(file, result.rootHash, signaturePath,
+                    buffer);
+        }
+    }
+
+    /**
+     * Generates fs-verity descriptor including the extensions to the {@code output} and returns the
+     * fs-verity measurement.
+     *
+     * @return fs-verity measurement, which is a SHA-256 of fs-verity descriptor and authenticated
+     *         extensions.
+     */
+    private static byte[] generateFsverityDescriptorAndMeasurement(
+            @NonNull RandomAccessFile file, @NonNull byte[] rootHash,
+            @NonNull String pkcs7SignaturePath, @NonNull ByteBuffer output)
+            throws IOException, NoSuchAlgorithmException, DigestException {
+        final short kRootHashExtensionId = 1;
+        final short kPkcs7SignatureExtensionId = 3;
+        final int origPosition = output.position();
+
+        // For generating fs-verity file measurement, which consists of the descriptor and
+        // authenticated extensions (but not unauthenticated extensions and the footer).
+        MessageDigest md = MessageDigest.getInstance("SHA-256");
+
+        // 1. Generate fs-verity descriptor.
+        final byte[] desc = constructFsverityDescriptorNative(file.length());
+        output.put(desc);
+        md.update(desc);
+
+        // 2. Generate authenticated extensions.
+        final byte[] authExt =
+                constructFsverityExtensionNative(kRootHashExtensionId, rootHash.length);
+        output.put(authExt);
+        output.put(rootHash);
+        md.update(authExt);
+        md.update(rootHash);
+
+        // 3. Generate unauthenticated extensions.
+        ByteBuffer header = ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN);
+        output.putShort((short) 1);  // number of unauthenticated extensions below
+        output.position(output.position() + 6);
+
+        // Generate PKCS#7 extension. NB: We do not verify agaist trusted certificate (should be
+        // done by the caller if needed).
+        Path path = Paths.get(pkcs7SignaturePath);
+        if (Files.size(path) > MAX_SIGNATURE_FILE_SIZE_BYTES) {
+            throw new IllegalArgumentException("Signature size is unexpectedly large: "
+                    + pkcs7SignaturePath);
+        }
+        final byte[] pkcs7Signature = Files.readAllBytes(path);
+        output.put(constructFsverityExtensionNative(kPkcs7SignatureExtensionId,
+                    pkcs7Signature.length));
+        output.put(pkcs7Signature);
+
+        // 4. Generate the footer.
+        output.put(constructFsverityFooterNative(output.position() - origPosition));
+
+        return md.digest();
+    }
+
+    private static native byte[] constructFsverityDescriptorNative(long fileSize);
+    private static native byte[] constructFsverityExtensionNative(short extensionId,
+            int extensionDataSize);
+    private static native byte[] constructFsverityFooterNative(int offsetToDescriptorHead);
+
+    /**
      * Returns a pair of {@code SharedMemory} and {@code Integer}. The {@code SharedMemory} contains
      * Merkle tree and fsverity headers for the given apk, in the form that can immediately be used
      * for fsverity setup. The data is aligned to the beginning of {@code SharedMemory}, and has
      * length equals to the returned {@code Integer}.
      */
-    private static Pair<SharedMemory, Integer> generateApkVerityIntoSharedMemory(
-            String apkPath, byte[] expectedRootHash)
+    private static Pair<SharedMemory, Integer> generateFsVerityIntoSharedMemory(
+            String apkPath, String signaturePath, @NonNull byte[] expectedRootHash,
+            boolean skipSigningBlock)
             throws IOException, SecurityException, DigestException, NoSuchAlgorithmException,
                    SignatureNotFoundException {
         TrackedShmBufferFactory shmBufferFactory = new TrackedShmBufferFactory();
-        byte[] generatedRootHash = ApkSignatureVerifier.generateApkVerity(apkPath,
-                shmBufferFactory);
+        byte[] generatedRootHash;
+        if (skipSigningBlock) {
+            generatedRootHash = ApkSignatureVerifier.generateApkVerity(apkPath, shmBufferFactory);
+        } else {
+            generatedRootHash = generateFsverityMetadata(apkPath, signaturePath, shmBufferFactory);
+        }
         // We only generate Merkle tree once here, so it's important to make sure the root hash
         // matches the signed one in the apk.
         if (!Arrays.equals(expectedRootHash, generatedRootHash)) {
-            throw new SecurityException("Locally generated verity root hash does not match");
+            throw new SecurityException("verity hash mismatch: "
+                    + bytesToString(generatedRootHash) + " != " + bytesToString(expectedRootHash));
         }
 
         int contentSize = shmBufferFactory.getBufferLimit();
@@ -126,11 +252,15 @@
         return Pair.create(shm, contentSize);
     }
 
+    private static String bytesToString(byte[] bytes) {
+        return HexEncoding.encodeToString(bytes);
+    }
+
     public static class SetupResult {
         /** Result code if verity is set up correctly. */
         private static final int RESULT_OK = 1;
 
-        /** Result code if the apk does not contain a verity root hash. */
+        /** Result code if signature is not provided. */
         private static final int RESULT_SKIPPED = 2;
 
         /** Result code if the setup failed. */
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index bfa03ca..d0de940 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -47,6 +47,7 @@
 import android.os.IStoraged;
 import android.os.IThermalEventListener;
 import android.os.IThermalService;
+import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
 import android.os.Process;
 import android.os.RemoteException;
@@ -63,10 +64,13 @@
 import android.telephony.ModemActivityInfo;
 import android.telephony.TelephonyManager;
 import android.util.ArrayMap;
+import android.util.Log;
 import android.util.Slog;
 import android.util.StatsLog;
 
 import com.android.internal.annotations.GuardedBy;
+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.BinderCallsStats.ExportedCallStat;
 import com.android.internal.os.KernelCpuSpeedReader;
@@ -78,10 +82,12 @@
 import com.android.internal.os.KernelWakelockStats;
 import com.android.internal.os.LooperStats;
 import com.android.internal.os.PowerProfile;
+import com.android.internal.os.StoragedUidIoStatsReader;
 import com.android.internal.util.DumpUtils;
 import com.android.server.BinderCallsStatsService;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
+import com.android.server.SystemServiceManager;
 import com.android.server.storage.DiskStatsFileLogger;
 import com.android.server.storage.DiskStatsLoggingService;
 
@@ -95,6 +101,7 @@
 import java.io.FileDescriptor;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -123,7 +130,7 @@
     public static final String CONFIG_DIR = "/data/misc/stats-service";
 
     static final String TAG = "StatsCompanionService";
-    static final boolean DEBUG = true;
+    static final boolean DEBUG = false;
 
     public static final int CODE_DATA_BROADCAST = 1;
     public static final int CODE_SUBSCRIBER_BROADCAST = 1;
@@ -172,14 +179,18 @@
             new KernelUidCpuActiveTimeReader();
     private KernelUidCpuClusterTimeReader mKernelUidCpuClusterTimeReader =
             new KernelUidCpuClusterTimeReader();
+    private StoragedUidIoStatsReader mStoragedUidIoStatsReader =
+            new StoragedUidIoStatsReader();
 
     private static IThermalService sThermalService;
+    private File mBaseDir =
+            new File(SystemServiceManager.ensureSystemDir(), "stats_companion");
 
     public StatsCompanionService(Context context) {
         super();
         mContext = context;
         mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
-
+        mBaseDir.mkdirs();
         mAppUpdateReceiver = new AppUpdateReceiver();
         mUserUpdateReceiver = new BroadcastReceiver() {
             @Override
@@ -966,6 +977,7 @@
             e.writeLong(processMemoryState.rssInBytes);
             e.writeLong(processMemoryState.cacheInBytes);
             e.writeLong(processMemoryState.swapInBytes);
+            e.writeLong(processMemoryState.rssHighWatermarkInBytes);
             pulledData.add(e);
         }
     }
@@ -1244,6 +1256,107 @@
         Binder.restoreCallingIdentity(token);
     }
 
+    long mLastProcStatsHighWaterMark = readProcStatsHighWaterMark();
+
+    private long readProcStatsHighWaterMark() {
+        try {
+            File[] files = mBaseDir.listFiles();
+            if (files == null || files.length == 0) {
+                return 0;
+            }
+            if (files.length > 1) {
+                Log.e(TAG, "Only 1 file expected for high water mark. Found " + files.length);
+            }
+            return Long.valueOf(files[0].getName());
+        } catch (SecurityException e) {
+            Log.e(TAG, "Failed to get procstats high watermark file.", e);
+        } catch (NumberFormatException e) {
+            Log.e(TAG, "Failed to parse file name.", e);
+        }
+        return 0;
+    }
+
+    private IProcessStats mProcessStats =
+            IProcessStats.Stub.asInterface(ServiceManager.getService(ProcessStats.SERVICE_NAME));
+
+    private void pullProcessStats(
+            int tagId, long elapsedNanos, long wallClockNanos,
+            List<StatsLogEventWrapper> pulledData) {
+        try {
+            List<ParcelFileDescriptor> statsFiles = new ArrayList<>();
+            long highWaterMark = mProcessStats.getCommittedStats(
+                    mLastProcStatsHighWaterMark, ProcessStats.REPORT_ALL, true, statsFiles);
+            if (statsFiles.size() != 1) {
+                return;
+            }
+            InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(statsFiles.get(0));
+            int[] len = new int[1];
+            byte[] stats = readFully(stream, len);
+            StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
+            e.writeStorage(Arrays.copyOf(stats, len[0]));
+            pulledData.add(e);
+            new File(mBaseDir.getAbsolutePath() + "/" + mLastProcStatsHighWaterMark).delete();
+            mLastProcStatsHighWaterMark = highWaterMark;
+            new File(
+                    mBaseDir.getAbsolutePath() + "/" + mLastProcStatsHighWaterMark).createNewFile();
+        } catch (IOException e) {
+            Log.e(TAG, "Getting procstats failed: ", e);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Getting procstats failed: ", e);
+        } catch (SecurityException e) {
+            Log.e(TAG, "Getting procstats failed: ", e);
+        }
+    }
+
+    static byte[] readFully(InputStream stream, int[] outLen) throws IOException {
+        int pos = 0;
+        final int initialAvail = stream.available();
+        byte[] data = new byte[initialAvail > 0 ? (initialAvail + 1) : 16384];
+        while (true) {
+            int amt = stream.read(data, pos, data.length - pos);
+            if (DEBUG) {
+                Slog.i(TAG, "Read " + amt + " bytes at " + pos + " of avail " + data.length);
+            }
+            if (amt < 0) {
+                if (DEBUG) {
+                    Slog.i(TAG, "**** FINISHED READING: pos=" + pos + " len=" + data.length);
+                }
+                outLen[0] = pos;
+                return data;
+            }
+            pos += amt;
+            if (pos >= data.length) {
+                byte[] newData = new byte[pos + 16384];
+                if (DEBUG) {
+                    Slog.i(TAG, "Copying " + pos + " bytes to new array len " + newData.length);
+                }
+                System.arraycopy(data, 0, newData, 0, pos);
+                data = newData;
+            }
+        }
+    }
+
+    private void pullDiskIo(int tagId, long elapsedNanos, final long wallClockNanos,
+            List<StatsLogEventWrapper> pulledData) {
+        mStoragedUidIoStatsReader.readAbsolute((uid, fgCharsRead, fgCharsWrite, fgBytesRead,
+                fgBytesWrite, bgCharsRead, bgCharsWrite, bgBytesRead, bgBytesWrite,
+                fgFsync, bgFsync) -> {
+            StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
+            e.writeInt(uid);
+            e.writeLong(fgCharsRead);
+            e.writeLong(fgCharsWrite);
+            e.writeLong(fgBytesRead);
+            e.writeLong(fgBytesWrite);
+            e.writeLong(bgCharsRead);
+            e.writeLong(bgCharsWrite);
+            e.writeLong(bgBytesRead);
+            e.writeLong(bgBytesWrite);
+            e.writeLong(fgFsync);
+            e.writeLong(bgFsync);
+            pulledData.add(e);
+        });
+    }
+
     /**
      * Pulls various data.
      */
@@ -1357,6 +1470,14 @@
                 pullNumFingerprints(tagId, elapsedNanos, wallClockNanos, ret);
                 break;
             }
+            case StatsLog.PROC_STATS: {
+                pullProcessStats(tagId, elapsedNanos, wallClockNanos, ret);
+                break;
+            }
+            case StatsLog.DISK_IO: {
+                pullDiskIo(tagId, elapsedNanos, wallClockNanos, ret);
+                break;
+            }
             default:
                 Slog.w(TAG, "No such tagId data as " + tagId);
                 return null;
@@ -1367,13 +1488,13 @@
     @Override // Binder call
     public void statsdReady() {
         enforceCallingPermission();
-        if (DEBUG) Slog.d(TAG, "learned that statsdReady");
+        if (DEBUG) {
+            Slog.d(TAG, "learned that statsdReady");
+        }
         sayHiToStatsd(); // tell statsd that we're ready too and link to it
-        mContext.sendBroadcastAsUser(
-                new Intent(StatsManager.ACTION_STATSD_STARTED)
+        mContext.sendBroadcastAsUser(new Intent(StatsManager.ACTION_STATSD_STARTED)
                         .addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND),
-                UserHandle.SYSTEM,
-                android.Manifest.permission.DUMP);
+                UserHandle.SYSTEM, android.Manifest.permission.DUMP);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index 7d2fc15..bcf9212 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.IActivityManager;
 import android.app.IApplicationThread;
 import android.content.ComponentName;
+import android.content.IIntentSender;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.res.CompatibilityInfo;
@@ -32,8 +33,12 @@
 import android.util.SparseIntArray;
 
 import com.android.internal.app.IVoiceInteractor;
+import com.android.server.am.PendingIntentRecord;
+import com.android.server.am.SafeActivityOptions;
+import com.android.server.am.TaskRecord;
 import com.android.server.am.WindowProcessController;
 
+import java.lang.ref.WeakReference;
 import java.util.List;
 
 /**
@@ -178,6 +183,27 @@
             int userId, Intent[] intents, Bundle bOptions);
 
     /**
+     * Start intents as a package.
+     *
+     * @param uid Make a call as if this UID did.
+     * @param callingPackage Make a call as if this package did.
+     * @param intents Intents to start.
+     * @param userId Start the intents on this user.
+     * @param validateIncomingUser Set true to skip checking {@code userId} with the calling UID.
+     * @param originatingPendingIntent PendingIntentRecord that originated this activity start or
+     *        null if not originated by PendingIntent
+     */
+    public abstract int startActivitiesInPackage(int uid, String callingPackage, Intent[] intents,
+            String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId,
+            boolean validateIncomingUser, PendingIntentRecord originatingPendingIntent);
+
+    public abstract int startActivityInPackage(int uid, int realCallingPid, int realCallingUid,
+            String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
+            String resultWho, int requestCode, int startFlags, SafeActivityOptions options,
+            int userId, TaskRecord inTask, String reason, boolean validateIncomingUser,
+            PendingIntentRecord originatingPendingIntent);
+
+    /**
      * Start activity {@code intent} without calling user-id check.
      *
      * - DO NOT call it with the calling UID cleared.
@@ -297,4 +323,13 @@
      * @param displayId The ID of the display showing the IME.
      */
     public abstract void onImeWindowSetOnDisplay(int pid, int displayId);
+
+    public abstract void sendActivityResult(int callingUid, IBinder activityToken,
+            String resultWho, int requestCode, int resultCode, Intent data);
+    public abstract void clearPendingResultForActivity(
+            IBinder activityToken, WeakReference<PendingIntentRecord> pir);
+    public abstract IIntentSender getIntentSender(int type, String packageName,
+            int callingUid, int userId, IBinder token, String resultWho,
+            int requestCode, Intent[] intents, String[] resolvedTypes, int flags,
+            Bundle bOptions);
 }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 4f31ca4..a762fe9 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -2613,6 +2613,12 @@
      */
     void setInputMethodWindowLocked(WindowState win) {
         mInputMethodWindow = win;
+        // Update display configuration for IME process.
+        if (mInputMethodWindow != null) {
+            final int imePid = mInputMethodWindow.mSession.mPid;
+            mService.mAtmInternal.onImeWindowSetOnDisplay(imePid,
+                    mInputMethodWindow.getDisplayId());
+        }
         computeImeTarget(true /* updateImeTarget */);
     }
 
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 8a78b75..6fef1630 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -20,8 +20,8 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.view.RemoteAnimationTarget.MODE_CLOSING;
+import static android.view.RemoteAnimationTarget.MODE_OPENING;
 import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION;
-
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
 import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_RECENTS_ANIM;
 import static com.android.server.wm.AnimationAdapterProto.REMOTE;
@@ -48,16 +48,13 @@
 import android.view.RemoteAnimationTarget;
 import android.view.SurfaceControl;
 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;
-
 import com.google.android.collect.Sets;
-
 import java.io.PrintWriter;
 import java.util.ArrayList;
 
@@ -93,6 +90,7 @@
 
     // The recents component app token that is shown behind the visibile tasks
     private AppWindowToken mTargetAppToken;
+    private int mTargetActivityType;
     private Rect mMinimizedHomeBounds = new Rect();
 
     // We start the RecentsAnimationController in a pending-start state since we need to wait for
@@ -259,23 +257,37 @@
         mDisplayId = displayId;
     }
 
+    public void initialize(int targetActivityType, SparseBooleanArray recentTaskIds) {
+        initialize(mService.mRoot.getDisplayContent(mDisplayId), targetActivityType, recentTaskIds);
+    }
+
     /**
      * Initializes the recents animation controller. This is a separate call from the constructor
      * because it may call cancelAnimation() which needs to properly clean up the controller
      * in the window manager.
      */
-    public void initialize(int targetActivityType, SparseBooleanArray recentTaskIds) {
-        // Make leashes for each of the visible tasks and add it to the recents animation to be
-        // started
-        final DisplayContent dc = mService.mRoot.getDisplayContent(mDisplayId);
+    @VisibleForTesting
+    void initialize(DisplayContent dc, int targetActivityType, SparseBooleanArray recentTaskIds) {
+        mTargetActivityType = targetActivityType;
+
+        // Make leashes for each of the visible/target tasks and add it to the recents animation to
+        // be started
         final ArrayList<Task> visibleTasks = dc.getVisibleTasks();
+        final TaskStack targetStack = dc.getStack(WINDOWING_MODE_UNDEFINED, targetActivityType);
+        if (targetStack != null) {
+            for (int i = targetStack.getChildCount() - 1; i >= 0; i--) {
+                final Task t = targetStack.getChildAt(i);
+                if (!visibleTasks.contains(t)) {
+                    visibleTasks.add(t);
+                }
+            }
+        }
         final int taskCount = visibleTasks.size();
         for (int i = 0; i < taskCount; i++) {
             final Task task = visibleTasks.get(i);
             final WindowConfiguration config = task.getWindowConfiguration();
             if (config.tasksAreFloating()
-                    || config.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
-                    || config.getActivityType() == targetActivityType) {
+                    || config.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
                 continue;
             }
             addAnimation(task, !recentTaskIds.get(task.mTaskId));
@@ -586,7 +598,10 @@
             final Rect insets = new Rect();
             mainWindow.getContentInsets(insets);
             InsetUtils.addInsets(insets, mainWindow.mAppToken.getLetterboxInsets());
-            mTarget = new RemoteAnimationTarget(mTask.mTaskId, MODE_CLOSING, mCapturedLeash,
+            final int mode = topApp.getActivityType() == mTargetActivityType
+                    ? MODE_OPENING
+                    : MODE_CLOSING;
+            mTarget = new RemoteAnimationTarget(mTask.mTaskId, mode, mCapturedLeash,
                     !topApp.fillsParent(), mainWindow.mWinAnimator.mLastClipRect,
                     insets, mTask.getPrefixOrderIndex(), mPosition, mBounds,
                     mTask.getWindowConfiguration(), mIsRecentTaskInvisible);
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index d92818a..a9571be 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -48,7 +48,6 @@
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
 import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_NONE;
 import static com.android.server.wm.WindowManagerService.logSurface;
-import static com.android.server.wm.WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED;
 import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
 import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION;
 import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING;
@@ -91,7 +90,6 @@
     private static final int SET_SCREEN_BRIGHTNESS_OVERRIDE = 1;
     private static final int SET_USER_ACTIVITY_TIMEOUT = 2;
 
-    private boolean mWallpaperForceHidingChanged = false;
     private Object mLastWindowFreezeSource = null;
     private Session mHoldScreen = null;
     private float mScreenBrightness = -1;
@@ -626,18 +624,6 @@
             recentsAnimationController.checkAnimationReady(mWallpaperController);
         }
 
-        if (mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0
-                && !mService.mAppTransition.isReady()) {
-            // At this point, there was a window with a wallpaper that was force hiding other
-            // windows behind it, but now it is going away. This may be simple -- just animate away
-            // the wallpaper and its window -- or it may be hard -- the wallpaper now needs to be
-            // shown behind something that was hidden.
-            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
-            if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
-                    "after animateAwayWallpaperLocked", defaultDisplay.pendingLayoutChanges);
-        }
-        mWallpaperForceHidingChanged = false;
-
         if (mWallpaperMayChange) {
             if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change!  Adjusting");
             defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
@@ -961,10 +947,6 @@
             mWallpaperMayChange = true;
             doRequest = true;
         }
-        if ((bulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0) {
-            mWallpaperForceHidingChanged = true;
-            doRequest = true;
-        }
         if ((bulkUpdateParams & SET_ORIENTATION_CHANGE_COMPLETE) == 0) {
             mOrientationChangeComplete = false;
         } else {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index cc23ab6..6aa0e01 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -561,9 +561,10 @@
 
     @Override
     public SurfaceControl getAnimationLeashParent() {
-        // Reparent to the animation layer so that we aren't clipped by the non-minimized
-        // stack bounds, currently we only animate the task for the recents animation
-        return getAppAnimationLayer(ANIMATION_LAYER_STANDARD);
+        // Currently, only the recents animation will create animation leashes for tasks. In this
+        // case, reparent the task to the home animation layer while it is being animated to allow
+        // the home activity to reorder the app windows relative to its own.
+        return getAppAnimationLayer(ANIMATION_LAYER_HOME);
     }
 
     boolean isTaskAnimating() {
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index a9e4be2..ad0b8ec 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -272,9 +272,6 @@
         if ((bulkUpdateParams & WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE) != 0) {
             builder.append(" WALLPAPER_MAY_CHANGE");
         }
-        if ((bulkUpdateParams & WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED) != 0) {
-            builder.append(" FORCE_HIDING_CHANGED");
-        }
         if ((bulkUpdateParams & WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE) != 0) {
             builder.append(" ORIENTATION_CHANGE_COMPLETE");
         }
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index e860939..4883f97 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -42,10 +42,8 @@
 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;
@@ -71,7 +69,8 @@
 
     /**
      * Animation layer that is reserved for {@link WindowConfiguration#ACTIVITY_TYPE_HOME}
-     * activities that happens below all {@link TaskStack}s.
+     * activities and all activities that are being controlled by the recents animation. This
+     * layer is generally below all {@link TaskStack}s.
      */
     static final int ANIMATION_LAYER_HOME = 2;
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index 27b623b..5410676 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -340,20 +340,6 @@
     public abstract int getInputMethodWindowVisibleHeight(int displayId);
 
     /**
-      * Saves last input method window for transition.
-      *
-      * Note that it is assumed that this method is called only by InputMethodManagerService.
-      */
-    public abstract void saveLastInputMethodWindowForTransition();
-
-    /**
-     * Clears last input method window for transition.
-     *
-     * Note that it is assumed that this method is called only by InputMethodManagerService.
-     */
-    public abstract void clearLastInputMethodWindowForTransition();
-
-    /**
      * Notifies WindowManagerService that the current IME window status is being changed.
      *
      * <p>Only {@link com.android.server.inputmethod.InputMethodManagerService} is the expected and
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index b94ddeb..942e47b 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -227,6 +227,7 @@
 import android.view.WindowManagerPolicyConstants.PointerEventListener;
 
 import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.IResultReceiver;
 import com.android.internal.policy.IKeyguardDismissCallback;
 import com.android.internal.policy.IShortcutService;
@@ -1414,7 +1415,6 @@
 
             win.mToken.addWindow(win);
             if (type == TYPE_INPUT_METHOD) {
-                win.mGivenInsetsPending = true;
                 displayContent.setInputMethodWindowLocked(win);
                 imMayMove = false;
             } else if (type == TYPE_INPUT_METHOD_DIALOG) {
@@ -2715,6 +2715,11 @@
         }
     }
 
+    @VisibleForTesting
+    void setRecentsAnimationController(RecentsAnimationController controller) {
+        mRecentsAnimationController = controller;
+    }
+
     public RecentsAnimationController getRecentsAnimationController() {
         return mRecentsAnimationController;
     }
@@ -5666,11 +5671,6 @@
 
         mInputManagerCallback.freezeInputDispatchingLw();
 
-        // Clear the last input window -- that is just used for
-        // clean transitions between IMEs, and if we are freezing
-        // the screen then the whole world is changing behind the scenes.
-        mPolicy.setLastInputMethodWindowLw(null, null);
-
         if (mAppTransition.isTransitionSet()) {
             mAppTransition.freeze();
         }
@@ -7283,23 +7283,6 @@
         }
 
         @Override
-        public void saveLastInputMethodWindowForTransition() {
-            synchronized (mWindowMap) {
-                final WindowState imeWindow = mRoot.getCurrentInputMethodWindow();
-                if (imeWindow != null) {
-                    mPolicy.setLastInputMethodWindowLw(imeWindow, mInputMethodTarget);
-                }
-            }
-        }
-
-        @Override
-        public void clearLastInputMethodWindowForTransition() {
-            synchronized (mWindowMap) {
-                mPolicy.setLastInputMethodWindowLw(null, null);
-            }
-        }
-
-        @Override
         public void updateInputMethodWindowStatus(@NonNull IBinder imeToken,
                 boolean imeWindowVisible, boolean dismissImeOnBackKeyPressed) {
             mPolicy.setDismissImeOnBackKeyPressed(dismissImeOnBackKeyPressed);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index ad44c33..a4bac31 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -4522,7 +4522,8 @@
         updateSurfacePosition(getPendingTransaction());
     }
 
-    private void updateSurfacePosition(Transaction t) {
+    @VisibleForTesting
+    void updateSurfacePosition(Transaction t) {
         if (mSurfaceControl == null) {
             return;
         }
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 0b02fa3..080a3a2 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -92,9 +92,8 @@
 
     static final int SET_UPDATE_ROTATION                = 1 << 0;
     static final int SET_WALLPAPER_MAY_CHANGE           = 1 << 1;
-    static final int SET_FORCE_HIDING_CHANGED           = 1 << 2;
-    static final int SET_ORIENTATION_CHANGE_COMPLETE    = 1 << 3;
-    static final int SET_WALLPAPER_ACTION_PENDING       = 1 << 4;
+    static final int SET_ORIENTATION_CHANGE_COMPLETE    = 1 << 2;
+    static final int SET_WALLPAPER_ACTION_PENDING       = 1 << 3;
 
     private boolean mTraversalScheduled;
     private int mDeferDepth = 0;
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index becde73..157b634 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -37,6 +37,7 @@
         "com_android_server_locksettings_SyntheticPasswordManager.cpp",
         "com_android_server_net_NetworkStatsService.cpp",
         "com_android_server_power_PowerManagerService.cpp",
+        "com_android_server_security_VerityUtils.cpp",
         "com_android_server_SerialService.cpp",
         "com_android_server_storage_AppFuseBridge.cpp",
         "com_android_server_SystemServer.cpp",
@@ -89,7 +90,6 @@
         "libsensorservicehidl",
         "libgui",
         "libusbhost",
-        "libsuspend",
         "libtinyalsa",
         "libEGL",
         "libGLESv2",
@@ -121,6 +121,7 @@
         "android.hardware.vr@1.0",
         "android.frameworks.schedulerservice@1.0",
         "android.frameworks.sensorservice@1.0",
+        "android.system.suspend@1.0",
     ],
 
     static_libs: [
diff --git a/services/core/jni/com_android_server_am_BatteryStatsService.cpp b/services/core/jni/com_android_server_am_BatteryStatsService.cpp
index 02ad6c7..0ff60e4 100644
--- a/services/core/jni/com_android_server_am_BatteryStatsService.cpp
+++ b/services/core/jni/com_android_server_am_BatteryStatsService.cpp
@@ -30,6 +30,8 @@
 
 #include <android/hardware/power/1.0/IPower.h>
 #include <android/hardware/power/1.1/IPower.h>
+#include <android/system/suspend/1.0/ISystemSuspend.h>
+#include <android/system/suspend/1.0/ISystemSuspendCallback.h>
 #include <android_runtime/AndroidRuntime.h>
 #include <jni.h>
 
@@ -39,7 +41,6 @@
 #include <log/log.h>
 #include <utils/misc.h>
 #include <utils/Log.h>
-#include <suspend/autosuspend.h>
 
 using android::hardware::Return;
 using android::hardware::Void;
@@ -49,6 +50,8 @@
 using android::hardware::power::V1_1::PowerStateSubsystem;
 using android::hardware::power::V1_1::PowerStateSubsystemSleepState;
 using android::hardware::hidl_vec;
+using android::system::suspend::V1_0::ISystemSuspend;
+using android::system::suspend::V1_0::ISystemSuspendCallback;
 using IPowerV1_1 = android::hardware::power::V1_1::IPower;
 using IPowerV1_0 = android::hardware::power::V1_0::IPower;
 
@@ -63,6 +66,7 @@
 extern sp<IPowerV1_0> getPowerHalV1_0();
 extern sp<IPowerV1_1> getPowerHalV1_1();
 extern bool processPowerHalReturn(const Return<void> &ret, const char* functionName);
+extern sp<ISystemSuspend> getSuspendHal();
 
 // Java methods used in getLowPowerStats
 static jmethodID jgetAndUpdatePlatformState = NULL;
@@ -70,16 +74,19 @@
 static jmethodID jputVoter = NULL;
 static jmethodID jputState = NULL;
 
-static void wakeup_callback(bool success)
-{
-    ALOGV("In wakeup_callback: %s", success ? "resumed from suspend" : "suspend aborted");
-    int ret = sem_post(&wakeup_sem);
-    if (ret < 0) {
-        char buf[80];
-        strerror_r(errno, buf, sizeof(buf));
-        ALOGE("Error posting wakeup sem: %s\n", buf);
+class WakeupCallback : public ISystemSuspendCallback {
+public:
+    Return<void> notifyWakeup(bool success) override {
+        ALOGV("In wakeup_callback: %s", success ? "resumed from suspend" : "suspend aborted");
+        int ret = sem_post(&wakeup_sem);
+        if (ret < 0) {
+            char buf[80];
+            strerror_r(errno, buf, sizeof(buf));
+            ALOGE("Error posting wakeup sem: %s\n", buf);
+        }
+        return Void();
     }
-}
+};
 
 static jint nativeWaitWakeup(JNIEnv *env, jobject clazz, jobject outBuf)
 {
@@ -101,11 +108,14 @@
             return -1;
         }
         ALOGV("Registering callback...");
-        autosuspend_set_wakeup_callback(&wakeup_callback);
+        sp<ISystemSuspend> suspendHal = getSuspendHal();
+        suspendHal->registerCallback(new WakeupCallback());
     }
 
     // Wait for wakeup.
     ALOGV("Waiting for wakeup...");
+    // TODO(b/116747600): device can suspend and wakeup after sem_wait() finishes and before wakeup
+    // reason is recorded, i.e. BatteryStats might occasionally miss wakeup events.
     int ret = sem_wait(&wakeup_sem);
     if (ret < 0) {
         char buf[80];
diff --git a/services/core/jni/com_android_server_power_PowerManagerService.cpp b/services/core/jni/com_android_server_power_PowerManagerService.cpp
index b2d35d4..0c9b5f4 100644
--- a/services/core/jni/com_android_server_power_PowerManagerService.cpp
+++ b/services/core/jni/com_android_server_power_PowerManagerService.cpp
@@ -19,6 +19,7 @@
 //#define LOG_NDEBUG 0
 
 #include <android/hardware/power/1.1/IPower.h>
+#include <android/system/suspend/1.0/ISystemSuspend.h>
 #include <nativehelper/JNIHelp.h>
 #include "jni.h"
 
@@ -35,7 +36,7 @@
 #include <utils/Log.h>
 #include <hardware/power.h>
 #include <hardware_legacy/power.h>
-#include <suspend/autosuspend.h>
+#include <hidl/ServiceManagement.h>
 
 #include "com_android_server_power_PowerManagerService.h"
 
@@ -44,6 +45,9 @@
 using android::hardware::power::V1_0::PowerHint;
 using android::hardware::power::V1_0::Feature;
 using android::String8;
+using android::system::suspend::V1_0::ISystemSuspend;
+using android::system::suspend::V1_0::IWakeLock;
+using android::system::suspend::V1_0::WakeLockType;
 using IPowerV1_1 = android::hardware::power::V1_1::IPower;
 using IPowerV1_0 = android::hardware::power::V1_0::IPower;
 
@@ -171,6 +175,46 @@
     }
 }
 
+static sp<ISystemSuspend> gSuspendHal = nullptr;
+static sp<IWakeLock> gSuspendBlocker = nullptr;
+static std::mutex gSuspendMutex;
+
+// Assume SystemSuspend HAL is always alive.
+// TODO: Force device to restart if SystemSuspend HAL dies.
+sp<ISystemSuspend> getSuspendHal() {
+    static std::once_flag suspendHalFlag;
+    std::call_once(suspendHalFlag, [](){
+        ::android::hardware::details::waitForHwService(ISystemSuspend::descriptor, "default");
+        gSuspendHal = ISystemSuspend::getService();
+        assert(gSuspendHal != nullptr);
+    });
+    return gSuspendHal;
+}
+
+void enableAutoSuspend() {
+    static bool enabled = false;
+
+    std::lock_guard<std::mutex> lock(gSuspendMutex);
+    if (!enabled) {
+        sp<ISystemSuspend> suspendHal = getSuspendHal();
+        suspendHal->enableAutosuspend();
+        enabled = true;
+    }
+    if (gSuspendBlocker) {
+        gSuspendBlocker->release();
+        gSuspendBlocker.clear();
+    }
+}
+
+void disableAutoSuspend() {
+    std::lock_guard<std::mutex> lock(gSuspendMutex);
+    if (!gSuspendBlocker) {
+        sp<ISystemSuspend> suspendHal = getSuspendHal();
+        gSuspendBlocker = suspendHal->acquireWakeLock(WakeLockType::PARTIAL,
+                "PowerManager.SuspendLockout");
+    }
+}
+
 // ----------------------------------------------------------------------------
 
 static void nativeInit(JNIEnv* env, jobject obj) {
@@ -207,13 +251,13 @@
 static void nativeSetAutoSuspend(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) {
     if (enable) {
         android::base::Timer t;
-        autosuspend_enable();
+        enableAutoSuspend();
         if (t.duration() > 100ms) {
             ALOGD("Excessive delay in autosuspend_enable() while turning screen off");
         }
     } else {
         android::base::Timer t;
-        autosuspend_disable();
+        disableAutoSuspend();
         if (t.duration() > 100ms) {
             ALOGD("Excessive delay in autosuspend_disable() while turning screen on");
         }
diff --git a/services/core/jni/com_android_server_security_VerityUtils.cpp b/services/core/jni/com_android_server_security_VerityUtils.cpp
new file mode 100644
index 0000000..d0f173b
--- /dev/null
+++ b/services/core/jni/com_android_server_security_VerityUtils.cpp
@@ -0,0 +1,137 @@
+/*
+ * 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 LOG_TAG "VerityUtils"
+
+#include <nativehelper/JNIHelp.h>
+#include "jni.h"
+#include <utils/Log.h>
+
+#include <string.h>
+
+// TODO(112037636): Always include once fsverity.h is upstreamed and backported.
+#define HAS_FSVERITY 0
+
+#if HAS_FSVERITY
+#include <linux/fsverity.h>
+#endif
+
+namespace android {
+
+namespace {
+
+class JavaByteArrayHolder {
+  public:
+    static JavaByteArrayHolder* newArray(JNIEnv* env, jsize size) {
+        return new JavaByteArrayHolder(env, size);
+    }
+
+    jbyte* getRaw() {
+        return mElements;
+    }
+
+    jbyteArray release() {
+        mEnv->ReleaseByteArrayElements(mBytes, mElements, 0);
+        mElements = nullptr;
+        return mBytes;
+    }
+
+  private:
+    JavaByteArrayHolder(JNIEnv* env, jsize size) {
+        mEnv = env;
+        mBytes = mEnv->NewByteArray(size);
+        mElements = mEnv->GetByteArrayElements(mBytes, nullptr);
+        memset(mElements, 0, size);
+    }
+
+    virtual ~JavaByteArrayHolder() {
+        LOG_ALWAYS_FATAL_IF(mElements == nullptr, "Elements are not released");
+    }
+
+    JNIEnv* mEnv;
+    jbyteArray mBytes;
+    jbyte* mElements;
+};
+
+jbyteArray constructFsverityDescriptor(JNIEnv* env, jobject /* clazz */, jlong fileSize) {
+#if HAS_FSVERITY
+    auto raii = JavaByteArrayHolder::newArray(env, sizeof(fsverity_descriptor));
+    fsverity_descriptor* desc = reinterpret_cast<fsverity_descriptor*>(raii->getRaw());
+
+    memcpy(desc->magic, FS_VERITY_MAGIC, sizeof(desc->magic));
+    desc->major_version = 1;
+    desc->minor_version = 0;
+    desc->log_data_blocksize = 12;
+    desc->log_tree_blocksize = 12;
+    desc->data_algorithm = FS_VERITY_ALG_SHA256;
+    desc->tree_algorithm = FS_VERITY_ALG_SHA256;
+    desc->flags = 0;
+    desc->orig_file_size = fileSize;
+    desc->auth_ext_count = 1;
+
+    return raii->release();
+#else
+    LOG_ALWAYS_FATAL("fs-verity is used while not enabled");
+    return 0;
+#endif  // HAS_FSVERITY
+}
+
+jbyteArray constructFsverityExtension(JNIEnv* env, jobject /* clazz */, jshort extensionId,
+        jint extensionDataSize) {
+#if HAS_FSVERITY
+    auto raii = JavaByteArrayHolder::newArray(env, sizeof(fsverity_extension));
+    fsverity_extension* ext = reinterpret_cast<fsverity_extension*>(raii->getRaw());
+
+    ext->length = sizeof(fsverity_extension) + extensionDataSize;
+    ext->type = extensionId;
+
+    return raii->release();
+#else
+    LOG_ALWAYS_FATAL("fs-verity is used while not enabled");
+    return 0;
+#endif  // HAS_FSVERITY
+}
+
+jbyteArray constructFsverityFooter(JNIEnv* env, jobject /* clazz */,
+        jint offsetToDescriptorHead) {
+#if HAS_FSVERITY
+    auto raii = JavaByteArrayHolder::newArray(env, sizeof(fsverity_footer));
+    fsverity_footer* footer = reinterpret_cast<fsverity_footer*>(raii->getRaw());
+
+    footer->desc_reverse_offset = offsetToDescriptorHead + sizeof(fsverity_footer);
+    memcpy(footer->magic, FS_VERITY_MAGIC, sizeof(footer->magic));
+
+    return raii->release();
+#else
+    LOG_ALWAYS_FATAL("fs-verity is used while not enabled");
+    return 0;
+#endif  // HAS_FSVERITY
+}
+
+const JNINativeMethod sMethods[] = {
+    { "constructFsverityDescriptorNative", "(J)[B", (void *)constructFsverityDescriptor },
+    { "constructFsverityExtensionNative", "(SI)[B", (void *)constructFsverityExtension },
+    { "constructFsverityFooterNative", "(I)[B", (void *)constructFsverityFooter },
+};
+
+}  // namespace
+
+int register_android_server_security_VerityUtils(JNIEnv* env) {
+    return jniRegisterNativeMethods(env,
+            "com/android/server/security/VerityUtils", sMethods, NELEM(sMethods));
+}
+
+}  // namespace android
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index bb6e684..918f57e 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -54,6 +54,7 @@
 int register_android_server_GraphicsStatsService(JNIEnv* env);
 int register_android_hardware_display_DisplayViewport(JNIEnv* env);
 int register_android_server_net_NetworkStatsService(JNIEnv* env);
+int register_android_server_security_VerityUtils(JNIEnv* env);
 };
 
 using namespace android;
@@ -101,5 +102,6 @@
     register_android_server_GraphicsStatsService(env);
     register_android_hardware_display_DisplayViewport(env);
     register_android_server_net_NetworkStatsService(env);
+    register_android_server_security_VerityUtils(env);
     return JNI_VERSION_1_4;
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index e76afa3..eeb4ad3 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -10106,13 +10106,15 @@
             if (setting.equals(Settings.Secure.INSTALL_NON_MARKET_APPS)) {
                 if (getTargetSdk(who.getPackageName(), callingUserId) >= Build.VERSION_CODES.O) {
                     throw new UnsupportedOperationException(Settings.Secure.INSTALL_NON_MARKET_APPS
-                            + " is deprecated. Please use the user restriction "
-                            + UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES + " instead.");
+                            + " is deprecated. Please use one of the user restrictions "
+                            + UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES + " or "
+                            + UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY + " instead.");
                 }
                 if (!mUserManager.isManagedProfile(callingUserId)) {
                     Slog.e(LOG_TAG, "Ignoring setSecureSetting request for "
                             + setting + ". User restriction "
-                            + UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES
+                            + UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES + " or "
+                            + UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY
                             + " should be used instead.");
                 } else {
                     try {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index fb95f59..b8241d0 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -65,6 +65,7 @@
 import com.android.internal.widget.ILockSettings;
 import com.android.server.am.ActivityManagerService;
 import com.android.server.am.ActivityTaskManagerService;
+import com.android.server.appbinding.AppBindingService;
 import com.android.server.audio.AudioService;
 import com.android.server.biometrics.BiometricService;
 import com.android.server.broadcastradio.BroadcastRadioService;
@@ -1710,6 +1711,10 @@
             traceEnd();
         }
 
+        traceBeginAndSlog("AppServiceManager");
+        mSystemServiceManager.startService(AppBindingService.Lifecycle.class);
+        traceEnd();
+
         // It is now time to start up the app processes...
 
         traceBeginAndSlog("MakeVibratorServiceReady");
diff --git a/services/net/java/android/net/util/SharedLog.java b/services/net/java/android/net/util/SharedLog.java
index f7bf393..5a73a4e 100644
--- a/services/net/java/android/net/util/SharedLog.java
+++ b/services/net/java/android/net/util/SharedLog.java
@@ -17,6 +17,7 @@
 package android.net.util;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.text.TextUtils;
 import android.util.LocalLog;
 import android.util.Log;
@@ -92,10 +93,17 @@
     }
 
     /**
-     * Log an error due to an exception, with the exception stacktrace.
+     * Log an error due to an exception, with the exception stacktrace if provided.
+     *
+     * <p>The error and exception message appear in the shared log, but the stacktrace is only
+     * logged in general log output (logcat).
      */
-    public void e(@NonNull String msg, @NonNull Throwable e) {
-        Log.e(mTag, record(Category.ERROR, msg + ": " + e.getMessage()), e);
+    public void e(@NonNull String msg, @Nullable Throwable exception) {
+        if (exception == null) {
+            e(msg);
+            return;
+        }
+        Log.e(mTag, record(Category.ERROR, msg + ": " + exception.getMessage()), exception);
     }
 
     public void i(String msg) {
diff --git a/services/robotests/Android.mk b/services/robotests/Android.mk
index 8b59771..78c0be4 100644
--- a/services/robotests/Android.mk
+++ b/services/robotests/Android.mk
@@ -61,6 +61,7 @@
     $(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 \
diff --git a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
index 57ebbfc..de915ab 100644
--- a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
+++ b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
@@ -122,6 +122,13 @@
         ShadowAppBackupUtils.reset();
     }
 
+    @Test
+    public void testMoreDebug_isFalse() throws Exception {
+        boolean moreDebug = BackupManagerService.MORE_DEBUG;
+
+        assertThat(moreDebug).isFalse();
+    }
+
     /* Tests for destination string */
 
     @Test
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
new file mode 100644
index 0000000..383bf1d
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkListingTest.java
@@ -0,0 +1,197 @@
+/*
+ * 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.chunk;
+
+import static com.google.common.truth.Truth.assertThat;
+
+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;
+
+@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"})
+@Presubmit
+public class ChunkListingTest {
+    private static final String CHUNK_A = "CHUNK_A";
+    private static final String CHUNK_B = "CHUNK_B";
+    private static final String CHUNK_C = "CHUNK_C";
+
+    private static final int CHUNK_A_LENGTH = 256;
+    private static final int CHUNK_B_LENGTH = 1024;
+    private static final int CHUNK_C_LENGTH = 4055;
+
+    private ChunkHash mChunkHashA;
+    private ChunkHash mChunkHashB;
+    private ChunkHash mChunkHashC;
+
+    @Before
+    public void setUp() throws Exception {
+        mChunkHashA = getHash(CHUNK_A);
+        mChunkHashB = getHash(CHUNK_B);
+        mChunkHashC = getHash(CHUNK_C);
+    }
+
+    @Test
+    public void testHasChunk_whenChunkInListing_returnsTrue() throws Exception {
+        byte[] chunkListingProto =
+                createChunkListingProto(
+                        new ChunkHash[] {mChunkHashA, mChunkHashB, mChunkHashC},
+                        new int[] {CHUNK_A_LENGTH, CHUNK_B_LENGTH, CHUNK_C_LENGTH});
+        ChunkListing chunkListing =
+                ChunkListing.readFromProto(
+                        new ProtoInputStream(new ByteArrayInputStream(chunkListingProto)));
+
+        boolean chunkAInList = chunkListing.hasChunk(mChunkHashA);
+        boolean chunkBInList = chunkListing.hasChunk(mChunkHashB);
+        boolean chunkCInList = chunkListing.hasChunk(mChunkHashC);
+
+        assertThat(chunkAInList).isTrue();
+        assertThat(chunkBInList).isTrue();
+        assertThat(chunkCInList).isTrue();
+    }
+
+    @Test
+    public void testHasChunk_whenChunkNotInListing_returnsFalse() throws Exception {
+        byte[] chunkListingProto =
+                createChunkListingProto(
+                        new ChunkHash[] {mChunkHashA, mChunkHashB},
+                        new int[] {CHUNK_A_LENGTH, CHUNK_B_LENGTH});
+        ChunkListing chunkListing =
+                ChunkListing.readFromProto(
+                        new ProtoInputStream(new ByteArrayInputStream(chunkListingProto)));
+        ChunkHash chunkHashEmpty = getHash("");
+
+        boolean chunkCInList = chunkListing.hasChunk(mChunkHashC);
+        boolean emptyChunkInList = chunkListing.hasChunk(chunkHashEmpty);
+
+        assertThat(chunkCInList).isFalse();
+        assertThat(emptyChunkInList).isFalse();
+    }
+
+    @Test
+    public void testGetChunkEntry_returnsEntryWithCorrectLength() throws Exception {
+        byte[] chunkListingProto =
+                createChunkListingProto(
+                        new ChunkHash[] {mChunkHashA, mChunkHashB, mChunkHashC},
+                        new int[] {CHUNK_A_LENGTH, CHUNK_B_LENGTH, CHUNK_C_LENGTH});
+        ChunkListing chunkListing =
+                ChunkListing.readFromProto(
+                        new ProtoInputStream(new ByteArrayInputStream(chunkListingProto)));
+
+        ChunkListing.Entry entryA = chunkListing.getChunkEntry(mChunkHashA);
+        ChunkListing.Entry entryB = chunkListing.getChunkEntry(mChunkHashB);
+        ChunkListing.Entry entryC = chunkListing.getChunkEntry(mChunkHashC);
+
+        assertThat(entryA.getLength()).isEqualTo(CHUNK_A_LENGTH);
+        assertThat(entryB.getLength()).isEqualTo(CHUNK_B_LENGTH);
+        assertThat(entryC.getLength()).isEqualTo(CHUNK_C_LENGTH);
+    }
+
+    @Test
+    public void testGetChunkEntry_returnsEntryWithCorrectStart() throws Exception {
+        byte[] chunkListingProto =
+                createChunkListingProto(
+                        new ChunkHash[] {mChunkHashA, mChunkHashB, mChunkHashC},
+                        new int[] {CHUNK_A_LENGTH, CHUNK_B_LENGTH, CHUNK_C_LENGTH});
+        ChunkListing chunkListing =
+                ChunkListing.readFromProto(
+                        new ProtoInputStream(new ByteArrayInputStream(chunkListingProto)));
+
+        ChunkListing.Entry entryA = chunkListing.getChunkEntry(mChunkHashA);
+        ChunkListing.Entry entryB = chunkListing.getChunkEntry(mChunkHashB);
+        ChunkListing.Entry entryC = chunkListing.getChunkEntry(mChunkHashC);
+
+        assertThat(entryA.getStart()).isEqualTo(0);
+        assertThat(entryB.getStart()).isEqualTo(CHUNK_A_LENGTH);
+        assertThat(entryC.getStart()).isEqualTo(CHUNK_A_LENGTH + CHUNK_B_LENGTH);
+    }
+
+    @Test
+    public void testGetChunkEntry_returnsNullForNonExistentChunk() throws Exception {
+        byte[] chunkListingProto =
+                createChunkListingProto(
+                        new ChunkHash[] {mChunkHashA, mChunkHashB},
+                        new int[] {CHUNK_A_LENGTH, CHUNK_B_LENGTH});
+        ChunkListing chunkListing =
+                ChunkListing.readFromProto(
+                        new ProtoInputStream(new ByteArrayInputStream(chunkListingProto)));
+
+        ChunkListing.Entry chunkEntryNonexistentChunk = chunkListing.getChunkEntry(mChunkHashC);
+
+        assertThat(chunkEntryNonexistentChunk).isNull();
+    }
+
+    @Test
+    public void testReadFromProto_whenEmptyProto_returnsChunkListingWith0Chunks() throws Exception {
+        ProtoInputStream emptyProto = new ProtoInputStream(new ByteArrayInputStream(new byte[] {}));
+
+        ChunkListing chunkListing = ChunkListing.readFromProto(emptyProto);
+
+        assertThat(chunkListing.getChunkCount()).isEqualTo(0);
+    }
+
+    @Test
+    public void testReadFromProto_returnsChunkListingWithCorrectSize() throws Exception {
+        byte[] chunkListingProto =
+                createChunkListingProto(
+                        new ChunkHash[] {mChunkHashA, mChunkHashB, mChunkHashC},
+                        new int[] {CHUNK_A_LENGTH, CHUNK_B_LENGTH, CHUNK_C_LENGTH});
+
+        ChunkListing chunkListing =
+                ChunkListing.readFromProto(
+                        new ProtoInputStream(new ByteArrayInputStream(chunkListingProto)));
+
+        assertThat(chunkListing.getChunkCount()).isEqualTo(3);
+    }
+
+    private byte[] createChunkListingProto(ChunkHash[] hashes, int[] lengths) {
+        Preconditions.checkArgument(hashes.length == lengths.length);
+        ProtoOutputStream outputStream = new ProtoOutputStream();
+
+        for (int i = 0; i < hashes.length; ++i) {
+            writeToProtoOutputStream(outputStream, hashes[i], lengths[i]);
+        }
+        outputStream.flush();
+
+        return outputStream.getBytes();
+    }
+
+    private void writeToProtoOutputStream(ProtoOutputStream out, ChunkHash chunkHash, int length) {
+        long token = out.start(ChunksMetadataProto.ChunkListing.CHUNKS);
+        out.write(ChunksMetadataProto.Chunk.HASH, chunkHash.getHash());
+        out.write(ChunksMetadataProto.Chunk.LENGTH, length);
+        out.end(token);
+    }
+
+    private ChunkHash getHash(String name) {
+        return new ChunkHash(
+                Arrays.copyOf(name.getBytes(Charsets.UTF_8), ChunkHash.HASH_LENGTH_BYTES));
+    }
+}
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
new file mode 100644
index 0000000..1dd7dc8
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkTest.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.server.backup.encryption.chunk;
+
+import static com.google.common.truth.Truth.assertThat;
+
+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;
+
+@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"})
+@Presubmit
+public class ChunkTest {
+    private static final String CHUNK_A = "CHUNK_A";
+    private static final int CHUNK_A_LENGTH = 256;
+
+    private ChunkHash mChunkHashA;
+
+    @Before
+    public void setUp() throws Exception {
+        mChunkHashA = getHash(CHUNK_A);
+    }
+
+    @Test
+    public void testReadFromProto_readsCorrectly() throws Exception {
+        ProtoOutputStream out = new ProtoOutputStream();
+        out.write(ChunksMetadataProto.Chunk.HASH, mChunkHashA.getHash());
+        out.write(ChunksMetadataProto.Chunk.LENGTH, CHUNK_A_LENGTH);
+        out.flush();
+        byte[] protoBytes = out.getBytes();
+
+        Chunk chunk =
+                Chunk.readFromProto(new ProtoInputStream(new ByteArrayInputStream(protoBytes)));
+
+        assertThat(chunk.getHash()).isEqualTo(mChunkHashA.getHash());
+        assertThat(chunk.getLength()).isEqualTo(CHUNK_A_LENGTH);
+    }
+
+    @Test
+    public void testReadFromProto_whenFieldsWrittenInReversedOrder_readsCorrectly()
+            throws Exception {
+        ProtoOutputStream out = new ProtoOutputStream();
+        // Write fields of Chunk proto in reverse order.
+        out.write(ChunksMetadataProto.Chunk.LENGTH, CHUNK_A_LENGTH);
+        out.write(ChunksMetadataProto.Chunk.HASH, mChunkHashA.getHash());
+        out.flush();
+        byte[] protoBytes = out.getBytes();
+
+        Chunk chunk =
+                Chunk.readFromProto(new ProtoInputStream(new ByteArrayInputStream(protoBytes)));
+
+        assertThat(chunk.getHash()).isEqualTo(mChunkHashA.getHash());
+        assertThat(chunk.getLength()).isEqualTo(CHUNK_A_LENGTH);
+    }
+
+    @Test
+    public void testReadFromProto_whenEmptyProto_returnsEmptyHash() throws Exception {
+        ProtoInputStream emptyProto = new ProtoInputStream(new ByteArrayInputStream(new byte[] {}));
+
+        Chunk chunk = Chunk.readFromProto(emptyProto);
+
+        assertThat(chunk.getHash()).asList().hasSize(0);
+        assertThat(chunk.getLength()).isEqualTo(0);
+    }
+
+    @Test
+    public void testReadFromProto_whenOnlyHashSet_returnsChunkWithOnlyHash() throws Exception {
+        ProtoOutputStream out = new ProtoOutputStream();
+        out.write(ChunksMetadataProto.Chunk.HASH, mChunkHashA.getHash());
+        out.flush();
+        byte[] protoBytes = out.getBytes();
+
+        Chunk chunk =
+                Chunk.readFromProto(new ProtoInputStream(new ByteArrayInputStream(protoBytes)));
+
+        assertThat(chunk.getHash()).isEqualTo(mChunkHashA.getHash());
+        assertThat(chunk.getLength()).isEqualTo(0);
+    }
+
+    @Test
+    public void testReadFromProto_whenOnlyLengthSet_returnsChunkWithOnlyLength() throws Exception {
+        ProtoOutputStream out = new ProtoOutputStream();
+        out.write(ChunksMetadataProto.Chunk.LENGTH, CHUNK_A_LENGTH);
+        out.flush();
+        byte[] protoBytes = out.getBytes();
+
+        Chunk chunk =
+                Chunk.readFromProto(new ProtoInputStream(new ByteArrayInputStream(protoBytes)));
+
+        assertThat(chunk.getHash()).isEqualTo(new byte[] {});
+        assertThat(chunk.getLength()).isEqualTo(CHUNK_A_LENGTH);
+    }
+
+    private ChunkHash getHash(String name) {
+        return new ChunkHash(
+                Arrays.copyOf(name.getBytes(Charsets.UTF_8), ChunkHash.HASH_LENGTH_BYTES));
+    }
+}
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
new file mode 100644
index 0000000..1cd1528
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/encryption/chunk/EncryptedChunkOrderingTest.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 com.android.server.backup.encryption.chunk;
+
+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;
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, sdk = 26)
+@SystemLoaderPackages({"com.android.server.backup"})
+@Presubmit
+public class EncryptedChunkOrderingTest {
+    private static final byte[] TEST_BYTE_ARRAY_1 = new byte[] {1, 2, 3, 4, 5};
+    private static final byte[] TEST_BYTE_ARRAY_2 = new byte[] {5, 4, 3, 2, 1};
+
+    @Test
+    public void testEncryptedChunkOrdering_returnsValue() {
+        EncryptedChunkOrdering encryptedChunkOrdering =
+                EncryptedChunkOrdering.create(TEST_BYTE_ARRAY_1);
+
+        byte[] bytes = encryptedChunkOrdering.encryptedChunkOrdering();
+
+        assertThat(bytes)
+                .asList()
+                .containsExactlyElementsIn(Bytes.asList(TEST_BYTE_ARRAY_1))
+                .inOrder();
+    }
+
+    @Test
+    public void testEquals() {
+        EncryptedChunkOrdering chunkOrdering1 = EncryptedChunkOrdering.create(TEST_BYTE_ARRAY_1);
+        EncryptedChunkOrdering equalChunkOrdering1 =
+                EncryptedChunkOrdering.create(TEST_BYTE_ARRAY_1);
+        EncryptedChunkOrdering chunkOrdering2 = EncryptedChunkOrdering.create(TEST_BYTE_ARRAY_2);
+
+        assertThat(chunkOrdering1).isEqualTo(equalChunkOrdering1);
+        assertThat(chunkOrdering1).isNotEqualTo(chunkOrdering2);
+    }
+
+    @Test
+    public void testHashCode() {
+        EncryptedChunkOrdering chunkOrdering1 = EncryptedChunkOrdering.create(TEST_BYTE_ARRAY_1);
+        EncryptedChunkOrdering equalChunkOrdering1 =
+                EncryptedChunkOrdering.create(TEST_BYTE_ARRAY_1);
+        EncryptedChunkOrdering chunkOrdering2 = EncryptedChunkOrdering.create(TEST_BYTE_ARRAY_2);
+
+        int hash1 = chunkOrdering1.hashCode();
+        int equalHash1 = equalChunkOrdering1.hashCode();
+        int hash2 = chunkOrdering2.hashCode();
+
+        assertThat(hash1).isEqualTo(equalHash1);
+        assertThat(hash1).isNotEqualTo(hash2);
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/keyvalue/AgentExceptionTest.java b/services/robotests/src/com/android/server/backup/keyvalue/AgentExceptionTest.java
new file mode 100644
index 0000000..3730335
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/keyvalue/AgentExceptionTest.java
@@ -0,0 +1,70 @@
+/*
+ * 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.keyvalue;
+
+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 org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+import java.io.IOException;
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, sdk = 26)
+@SystemLoaderPackages({"com.android.server.backup"})
+@Presubmit
+public class AgentExceptionTest {
+    @Test
+    public void testTransitory_isTransitory() throws Exception {
+        AgentException exception = AgentException.transitory();
+
+        assertThat(exception.isTransitory()).isTrue();
+    }
+
+    @Test
+    public void testTransitory_withCause() throws Exception {
+        Exception cause = new IOException();
+
+        AgentException exception = AgentException.transitory(cause);
+
+        assertThat(exception.isTransitory()).isTrue();
+        assertThat(exception.getCause()).isEqualTo(cause);
+    }
+
+    @Test
+    public void testPermanent_isNotTransitory() throws Exception {
+        AgentException exception = AgentException.permanent();
+
+        assertThat(exception.isTransitory()).isFalse();
+    }
+
+    @Test
+    public void testPermanent_withCause() throws Exception {
+        Exception cause = new IOException();
+
+        AgentException exception = AgentException.permanent(cause);
+
+        assertThat(exception.isTransitory()).isFalse();
+        assertThat(exception.getCause()).isEqualTo(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
new file mode 100644
index 0000000..5ea74f1
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/keyvalue/BackupExceptionTest.java
@@ -0,0 +1,45 @@
+/*
+ * 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.keyvalue;
+
+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 org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+import java.io.IOException;
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, sdk = 26)
+@SystemLoaderPackages({"com.android.server.backup"})
+@Presubmit
+public class BackupExceptionTest {
+    @Test
+    public void testConstructor_passesCause() {
+        Exception cause = new IOException();
+
+        Exception exception = new BackupException(cause);
+
+        assertThat(exception.getCause()).isEqualTo(cause);
+    }
+}
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 21b90f1..31e8333 100644
--- a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupReporterTest.java
+++ b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupReporterTest.java
@@ -62,6 +62,13 @@
     }
 
     @Test
+    public void testMoreDebug_isFalse() throws Exception {
+        boolean moreDebug = KeyValueBackupReporter.MORE_DEBUG;
+
+        assertThat(moreDebug).isFalse();
+    }
+
+    @Test
     public void testOnNewThread_logsCorrectly() throws Exception {
         KeyValueBackupReporter.onNewThread("foo");
 
@@ -81,39 +88,4 @@
 
         assertThat(observer).isEqualTo(mObserver);
     }
-
-    @Test
-    public void testOnRevertTask_logsCorrectly() throws Exception {
-        setMoreDebug(true);
-
-        mReporter.onRevertTask();
-
-        assertLogcat(TAG, Log.INFO);
-    }
-
-    @Test
-    public void testOnRemoteCallReturned_logsCorrectly() throws Exception {
-        setMoreDebug(true);
-
-        mReporter.onRemoteCallReturned(RemoteResult.of(3), "onFoo()");
-
-        assertLogcat(TAG, Log.VERBOSE);
-        ShadowLog.LogItem log = ShadowLog.getLogsForTag(TAG).get(0);
-        assertThat(log.msg).contains("onFoo()");
-        assertThat(log.msg).contains("3");
-    }
-
-    /**
-     * HACK: We actually want {@link KeyValueBackupReporter#MORE_DEBUG} to be a constant to be able
-     * to strip those lines at build time. So, we have to do this to test :(
-     */
-    private static void setMoreDebug(boolean value)
-            throws NoSuchFieldException, IllegalAccessException {
-        if (KeyValueBackupReporter.MORE_DEBUG == value) {
-            return;
-        }
-        Field moreDebugField = KeyValueBackupReporter.class.getDeclaredField("MORE_DEBUG");
-        moreDebugField.setAccessible(true);
-        moreDebugField.set(null, value);
-    }
 }
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 b4bc9d1..fb57d68 100644
--- a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
+++ b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
@@ -155,9 +155,7 @@
 import java.util.concurrent.TimeoutException;
 import java.util.stream.Stream;
 
-// TODO: When returning to RUNNING_QUEUE vs FINAL, RUNNING_QUEUE sets status = OK. Why? Verify?
-// TODO: Check queue in general, behavior w/ multiple packages
-// TODO: Test PM invocation
+// TODO: Test agents timing out
 @RunWith(FrameworkRobolectricTestRunner.class)
 @Config(
         manifest = Config.NONE,
@@ -370,6 +368,47 @@
     }
 
     @Test
+    public void testRunTask_whenOnePackage_cleansUpPmFiles() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgent(PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+
+        runTask(task);
+
+        assertCleansUpFiles(mTransport, PM_PACKAGE);
+    }
+
+    @Test
+    public void testRunTask_whenTransportReturnsTransportErrorForPm_cleansUpPmFiles()
+            throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PM_PACKAGE)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_PACKAGE_REJECTED);
+        setUpAgent(PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+
+        runTask(task);
+
+        assertCleansUpFiles(mTransport, PM_PACKAGE);
+    }
+
+    @Test
+    public void testRunTask_whenTransportReturnsTransportErrorForPm_resetsBackupState()
+            throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PM_PACKAGE)), any(), anyInt()))
+                .thenReturn(BackupTransport.TRANSPORT_PACKAGE_REJECTED);
+        setUpAgent(PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+
+        runTask(task);
+
+        verify(mBackupManagerService).resetBackupState(getStateDirectory(mTransport).toFile());
+    }
+
+    @Test
     public void testRunTask_whenOnePackage_updatesBookkeeping() throws Exception {
         // Transport has to be initialized to not reset current token
         TransportMock transportMock = setUpInitializedTransport(mTransport);
@@ -418,7 +457,7 @@
     public void testRunTask_whenNonPmPackageAndNonIncremental_doesNotBackUpPm() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         setUpAgentWithData(PACKAGE_1);
-        PackageManagerBackupAgent pmAgent = spy(createPmAgent());
+        BackupAgent pmAgent = spy(createPmAgent());
         when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
         KeyValueBackupTask task = createKeyValueBackupTask(transportMock, true, PACKAGE_1);
 
@@ -431,7 +470,7 @@
     public void testRunTask_whenNonPmPackageAndPmAndNonIncremental_backsUpPm() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         setUpAgentWithData(PACKAGE_1);
-        PackageManagerBackupAgent pmAgent = spy(createPmAgent());
+        BackupAgent pmAgent = spy(createPmAgent());
         when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
         KeyValueBackupTask task =
                 createKeyValueBackupTask(transportMock, true, PACKAGE_1, PM_PACKAGE);
@@ -445,7 +484,7 @@
     public void testRunTask_whenNonPmPackageAndIncremental_backsUpPm() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         setUpAgentWithData(PACKAGE_1);
-        PackageManagerBackupAgent pmAgent = spy(createPmAgent());
+        BackupAgent pmAgent = spy(createPmAgent());
         when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
         KeyValueBackupTask task = createKeyValueBackupTask(transportMock, false, PACKAGE_1);
 
@@ -529,6 +568,35 @@
     }
 
     @Test
+    public void testRunTask_whenPackageUnknown() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        // Not calling setUpAgent() for PACKAGE_1
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+
+        runTask(task);
+
+        verify(transportMock.transport, never())
+                .performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt());
+        verify(mObserver).onResult(PACKAGE_1.packageName, ERROR_PACKAGE_NOT_FOUND);
+        verify(mObserver).backupFinished(SUCCESS);
+        assertBackupNotPendingFor(PACKAGE_1);
+    }
+
+    @Test
+    public void testRunTask_whenFirstPackageUnknown_callsTransportForSecondPackage()
+            throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        // Not calling setUpAgent() for PACKAGE_1
+        setUpAgentWithData(PACKAGE_2);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1, PACKAGE_2);
+
+        runTask(task);
+
+        verify(transportMock.transport)
+                .performBackup(argThat(packageInfo(PACKAGE_2)), any(), anyInt());
+    }
+
+    @Test
     public void testRunTask_whenPackageNotEligibleForBackup() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         AgentMock agentMock = setUpAgentWithData(PACKAGE_1.backupNotAllowed());
@@ -545,6 +613,19 @@
     }
 
     @Test
+    public void testRunTask_whenFirstPackageNotEligibleForBackup_callsTransportForSecondPackage()
+            throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgentsWithData(PACKAGE_1.backupNotAllowed(), PACKAGE_2);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1, PACKAGE_2);
+
+        runTask(task);
+
+        verify(transportMock.transport)
+                .performBackup(argThat(packageInfo(PACKAGE_2)), any(), anyInt());
+    }
+
+    @Test
     public void testRunTask_whenPackageDoesFullBackup() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         PackageData packageData = fullBackupPackage(1);
@@ -561,6 +642,20 @@
     }
 
     @Test
+    public void testRunTask_whenFirstPackageDoesFullBackup_callsTransportForSecondPackage()
+            throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        PackageData packageData = fullBackupPackage(1);
+        setUpAgentsWithData(packageData, PACKAGE_2);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, packageData, PACKAGE_2);
+
+        runTask(task);
+
+        verify(transportMock.transport)
+                .performBackup(argThat(packageInfo(PACKAGE_2)), any(), anyInt());
+    }
+
+    @Test
     public void testRunTask_whenPackageIsStopped() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         AgentMock agentMock = setUpAgentWithData(PACKAGE_1.stopped());
@@ -575,18 +670,16 @@
     }
 
     @Test
-    public void testRunTask_whenPackageUnknown() throws Exception {
+    public void testRunTask_whenFirstPackageIsStopped_callsTransportForSecondPackage()
+            throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
-        // Not calling setUpAgent()
-        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+        setUpAgentsWithData(PACKAGE_1.stopped(), PACKAGE_2);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1, PACKAGE_2);
 
         runTask(task);
 
-        verify(transportMock.transport, never())
-                .performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt());
-        verify(mObserver).onResult(PACKAGE_1.packageName, ERROR_PACKAGE_NOT_FOUND);
-        verify(mObserver).backupFinished(SUCCESS);
-        assertBackupNotPendingFor(PACKAGE_1);
+        verify(transportMock.transport)
+                .performBackup(argThat(packageInfo(PACKAGE_2)), any(), anyInt());
     }
 
     @Test
@@ -629,6 +722,7 @@
         verify(mBackupManagerService).setWorkSource(null);
         verify(mObserver).onResult(PACKAGE_1.packageName, ERROR_AGENT_FAILURE);
         verify(mObserver).backupFinished(BackupManager.SUCCESS);
+        assertBackupPendingFor(PACKAGE_1);
     }
 
     @Test
@@ -645,6 +739,7 @@
         verify(mBackupManagerService).setWorkSource(null);
         verify(mObserver).onResult(PACKAGE_1.packageName, ERROR_AGENT_FAILURE);
         verify(mObserver).backupFinished(BackupManager.SUCCESS);
+        assertBackupPendingFor(PACKAGE_1);
     }
 
     @Test
@@ -798,7 +893,7 @@
 
         runTask(task);
 
-        assertBackupNotPendingFor(PACKAGE_1);
+        assertBackupPendingFor(PACKAGE_1);
     }
 
     @Test
@@ -1140,6 +1235,38 @@
     }
 
     @Test
+    public void testRunTask_whenPmAgentWritesData_callsTransportPerformBackupWithAgentData()
+            throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgent(PACKAGE_1);
+        Path backupDataPath = createTemporaryFile();
+        when(transportMock.transport.performBackup(
+                        argThat(packageInfo(PM_PACKAGE)), any(), anyInt()))
+                .then(copyBackupDataTo(backupDataPath));
+        BackupAgent pmAgent = spy(createPmAgent());
+        when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
+        agentOnBackupDo(
+                pmAgent,
+                (oldState, dataOutput, newState) -> {
+                    writeData(dataOutput, "key1", "data1".getBytes());
+                    writeData(dataOutput, "key2", "data2".getBytes());
+                    writeState(newState, "newState".getBytes());
+                });
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+
+        runTask(task);
+
+        verify(transportMock.transport)
+                .performBackup(argThat(packageInfo(PM_PACKAGE)), any(), anyInt());
+        try (FileInputStream inputStream = new FileInputStream(backupDataPath.toFile())) {
+            BackupDataInput backupData = new BackupDataInput(inputStream.getFD());
+            assertDataHasKeyValue(backupData, "key1", "data1".getBytes());
+            assertDataHasKeyValue(backupData, "key2", "data2".getBytes());
+            assertThat(backupData.readNextHeader()).isFalse();
+        }
+    }
+
+    @Test
     public void testRunTask_whenPerformBackupSucceeds_callsTransportFinishBackup()
             throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
@@ -1176,6 +1303,50 @@
     }
 
     @Test
+    public void testRunTask_whenFinishBackupSucceedsForPm_cleansUp() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgent(PACKAGE_1);
+        when(transportMock.transport.finishBackup()).thenReturn(BackupTransport.TRANSPORT_OK);
+        BackupAgent pmAgent = spy(createPmAgent());
+        when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
+        agentOnBackupDo(
+                pmAgent,
+                (oldState, dataOutput, newState) -> {
+                    writeData(dataOutput, "key", "data".getBytes());
+                    writeState(newState, "newState".getBytes());
+                });
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+
+        runTask(task);
+
+        assertThat(Files.readAllBytes(getStateFile(mTransport, PM_PACKAGE)))
+                .isEqualTo("newState".getBytes());
+        assertCleansUpFiles(mTransport, PM_PACKAGE);
+        // We don't unbind PM
+        verify(mBackupManagerService, never()).unbindAgent(argThat(applicationInfo(PM_PACKAGE)));
+    }
+
+    @Test
+    public void testRunTask_whenFinishBackupSucceedsForPm_doesNotUnbindPm() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgent(PACKAGE_1);
+        when(transportMock.transport.finishBackup()).thenReturn(BackupTransport.TRANSPORT_OK);
+        BackupAgent pmAgent = spy(createPmAgent());
+        when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
+        agentOnBackupDo(
+                pmAgent,
+                (oldState, dataOutput, newState) -> {
+                    writeData(dataOutput, "key", "data".getBytes());
+                    writeState(newState, "newState".getBytes());
+                });
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+
+        runTask(task);
+
+        verify(mBackupManagerService, never()).unbindAgent(argThat(applicationInfo(PM_PACKAGE)));
+    }
+
+    @Test
     public void testRunTask_whenFinishBackupSucceeds_logsBackupPackageEvent() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         setUpAgentWithData(PACKAGE_1);
@@ -1354,6 +1525,7 @@
     public void testRunTask_whenTransportReturnsQuotaExceeded_updatesBookkeeping()
             throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgentWithData(PACKAGE_1);
         when(transportMock.transport.performBackup(
                         argThat(packageInfo(PACKAGE_1)), any(), anyInt()))
                 .thenReturn(BackupTransport.TRANSPORT_QUOTA_EXCEEDED);
@@ -1701,9 +1873,9 @@
     }
 
     @Test
-    public void testRunTask_whenPmAgentFails() throws Exception {
+    public void testRunTask_whenPmAgentFails_reportsCorrectly() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
-        PackageManagerBackupAgent pmAgent = createThrowingPmAgent(new RuntimeException());
+        BackupAgent pmAgent = createThrowingPmAgent(new RuntimeException());
         when(mBackupManagerService.makeMetadataAgent()).thenReturn(pmAgent);
         KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
@@ -1718,6 +1890,75 @@
     }
 
     @Test
+    public void testRunTask_whenPmAgentFails_revertsTask() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgent(PACKAGE_1);
+        BackupAgent pmAgent = createThrowingPmAgent(new RuntimeException());
+        when(mBackupManagerService.makeMetadataAgent()).thenReturn(pmAgent);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+
+        runTask(task);
+
+        assertTaskReverted(transportMock, PACKAGE_1);
+    }
+
+    @Test
+    public void testRunTask_whenPmAgentFails_cleansUpFiles() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgent(PACKAGE_1);
+        BackupAgent pmAgent = createThrowingPmAgent(new RuntimeException());
+        when(mBackupManagerService.makeMetadataAgent()).thenReturn(pmAgent);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+
+        runTask(task);
+
+        assertCleansUpFiles(mTransport, PM_PACKAGE);
+    }
+
+    @Test
+    public void testRunTask_whenPmAgentFails_resetsBackupState() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgent(PACKAGE_1);
+        BackupAgent pmAgent = createThrowingPmAgent(new RuntimeException());
+        when(mBackupManagerService.makeMetadataAgent()).thenReturn(pmAgent);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+
+        runTask(task);
+
+        verify(mBackupManagerService).resetBackupState(getStateDirectory(mTransport).toFile());
+    }
+
+    @Test
+    public void testRunTask_whenMarkCancelDuringPmOnBackup_resetsBackupState() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgent(PACKAGE_1);
+        BackupAgent pmAgent = spy(createPmAgent());
+        when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+        agentOnBackupDo(
+                pmAgent, (oldState, dataOutput, newState) -> runInWorkerThread(task::markCancel));
+
+        runTask(task);
+
+        verify(mBackupManagerService).resetBackupState(getStateDirectory(mTransport).toFile());
+    }
+
+    @Test
+    public void testRunTask_whenMarkCancelDuringPmOnBackup_cleansUpFiles() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgent(PACKAGE_1);
+        BackupAgent pmAgent = spy(createPmAgent());
+        when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+        agentOnBackupDo(
+                pmAgent, (oldState, dataOutput, newState) -> runInWorkerThread(task::markCancel));
+
+        runTask(task);
+
+        assertCleansUpFiles(mTransport, PM_PACKAGE);
+    }
+
+    @Test
     public void testRunTask_whenBackupRunning_doesNotThrow() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         when(mBackupManagerService.isBackupOperationInProgress()).thenReturn(true);
@@ -1736,7 +1977,7 @@
 
         runTask(task);
 
-        verify(mReporter).onReadAgentDataError(eq(PACKAGE_1.packageName), any());
+        verify(mReporter).onAgentDataError(eq(PACKAGE_1.packageName), any());
     }
 
     @Test
@@ -1779,6 +2020,24 @@
     }
 
     @Test
+    public void testRunTask_whenMarkCancelDuringAgentOnBackup_cleansUpFiles() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+        agentOnBackupDo(
+                agentMock,
+                (oldState, dataOutput, newState) -> {
+                    writeData(dataOutput, "key", "data".getBytes());
+                    writeState(newState, "newState".getBytes());
+                    runInWorkerThread(task::markCancel);
+                });
+
+        runTask(task);
+
+        assertCleansUpFiles(mTransport, PACKAGE_1);
+    }
+
+    @Test
     public void
             testRunTask_whenMarkCancelDuringFirstAgentOnBackup_doesNotCallTransportAfterWaitCancel()
                     throws Exception {
@@ -2293,20 +2552,28 @@
      */
     private static void agentOnBackupDo(AgentMock agentMock, BackupAgentOnBackup function)
             throws Exception {
-        doAnswer(
-                        (BackupAgentOnBackup)
-                                (oldState, dataOutput, newState) -> {
-                                    ByteArrayOutputStream outputStream =
-                                            new ByteArrayOutputStream();
-                                    transferStreamedData(
-                                            new FileInputStream(oldState.getFileDescriptor()),
-                                            outputStream);
-                                    agentMock.oldState = outputStream.toByteArray();
-                                    agentMock.oldStateHistory.add(agentMock.oldState);
-                                    function.onBackup(oldState, dataOutput, newState);
-                                })
-                .when(agentMock.agent)
-                .onBackup(any(), any(), any());
+        agentOnBackupDo(
+                agentMock.agent,
+                (oldState, dataOutput, newState) -> {
+                    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+                    transferStreamedData(
+                            new FileInputStream(oldState.getFileDescriptor()), outputStream);
+                    agentMock.oldState = outputStream.toByteArray();
+                    agentMock.oldStateHistory.add(agentMock.oldState);
+                    function.onBackup(oldState, dataOutput, newState);
+                });
+    }
+
+    /**
+     * Implements {@code function} for {@link BackupAgent#onBackup(ParcelFileDescriptor,
+     * BackupDataOutput, ParcelFileDescriptor)} of {@code agentMock}.
+     *
+     * @see #agentOnBackupDo(AgentMock, BackupAgentOnBackup)
+     * @see #remoteAgentOnBackupThrows(AgentMock, BackupAgentOnBackup)
+     */
+    private static void agentOnBackupDo(BackupAgent backupAgent, BackupAgentOnBackup function)
+            throws IOException {
+        doAnswer(function).when(backupAgent).onBackup(any(), any(), any());
     }
 
     /**
@@ -2400,6 +2667,10 @@
             // constructor
             assertJournalDoesNotContain(mBackupManagerService.getJournal(), packageName);
             assertThat(mBackupManagerService.getPendingBackups()).doesNotContainKey(packageName);
+            // Also verifying BMS is never called since for some cases the package wouldn't be
+            // pending for other reasons (for example it's not eligible for backup). Regardless of
+            // these reasons, we shouldn't mark them as pending backup (call dataChangedImpl()).
+            verify(mBackupManagerService, never()).dataChangedImpl(packageName);
         }
     }
 
diff --git a/services/robotests/src/com/android/server/backup/keyvalue/TaskExceptionTest.java b/services/robotests/src/com/android/server/backup/keyvalue/TaskExceptionTest.java
new file mode 100644
index 0000000..4b79657
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/keyvalue/TaskExceptionTest.java
@@ -0,0 +1,152 @@
+/*
+ * 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.keyvalue;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.expectThrows;
+
+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 java.io.IOException;
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, sdk = 26)
+@SystemLoaderPackages({"com.android.server.backup"})
+@Presubmit
+public class TaskExceptionTest {
+    @Test
+    public void testStateCompromised() {
+        TaskException exception = TaskException.stateCompromised();
+
+        assertThat(exception.isStateCompromised()).isTrue();
+        assertThat(exception.getStatus()).isEqualTo(BackupTransport.TRANSPORT_ERROR);
+    }
+
+    @Test
+    public void testStateCompromised_whenCauseInstanceOfTaskException() {
+        Exception cause = TaskException.forStatus(BackupTransport.TRANSPORT_NOT_INITIALIZED);
+
+        TaskException exception = TaskException.stateCompromised(cause);
+
+        assertThat(exception.isStateCompromised()).isTrue();
+        assertThat(exception.getStatus()).isEqualTo(BackupTransport.TRANSPORT_NOT_INITIALIZED);
+        assertThat(exception.getCause()).isEqualTo(cause);
+    }
+
+    @Test
+    public void testStateCompromised_whenCauseNotInstanceOfTaskException() {
+        Exception cause = new IOException();
+
+        TaskException exception = TaskException.stateCompromised(cause);
+
+        assertThat(exception.isStateCompromised()).isTrue();
+        assertThat(exception.getStatus()).isEqualTo(BackupTransport.TRANSPORT_ERROR);
+        assertThat(exception.getCause()).isEqualTo(cause);
+    }
+
+    @Test
+    public void testForStatus_whenTransportOk_throws() {
+        expectThrows(
+                IllegalArgumentException.class,
+                () -> TaskException.forStatus(BackupTransport.TRANSPORT_OK));
+    }
+
+    @Test
+    public void testForStatus_whenTransportNotInitialized() {
+        TaskException exception =
+                TaskException.forStatus(BackupTransport.TRANSPORT_NOT_INITIALIZED);
+
+        assertThat(exception.isStateCompromised()).isFalse();
+        assertThat(exception.getStatus()).isEqualTo(BackupTransport.TRANSPORT_NOT_INITIALIZED);
+    }
+
+    @Test
+    public void testCausedBy_whenCauseInstanceOfTaskException_returnsCause() {
+        Exception cause = TaskException.forStatus(BackupTransport.TRANSPORT_NOT_INITIALIZED);
+
+        TaskException exception = TaskException.causedBy(cause);
+
+        assertThat(exception).isEqualTo(cause);
+    }
+
+    @Test
+    public void testCausedBy_whenCauseNotInstanceOfTaskException() {
+        Exception cause = new IOException();
+
+        TaskException exception = TaskException.causedBy(cause);
+
+        assertThat(exception).isNotEqualTo(cause);
+        assertThat(exception.isStateCompromised()).isFalse();
+        assertThat(exception.getStatus()).isEqualTo(BackupTransport.TRANSPORT_ERROR);
+        assertThat(exception.getCause()).isEqualTo(cause);
+    }
+
+    @Test
+    public void testCreate() {
+        TaskException exception = TaskException.create();
+
+        assertThat(exception.isStateCompromised()).isFalse();
+        assertThat(exception.getStatus()).isEqualTo(BackupTransport.TRANSPORT_ERROR);
+    }
+
+    @Test
+    public void testIsStateCompromised_whenStateCompromised_returnsTrue() {
+        TaskException taskException = TaskException.stateCompromised();
+
+        boolean stateCompromised = taskException.isStateCompromised();
+
+        assertThat(stateCompromised).isTrue();
+    }
+
+    @Test
+    public void testIsStateCompromised_whenCreatedWithCreate_returnsFalse() {
+        TaskException taskException = TaskException.create();
+
+        boolean stateCompromised = taskException.isStateCompromised();
+
+        assertThat(stateCompromised).isFalse();
+    }
+
+    @Test
+    public void testGetStatus_whenStatusIsTransportPackageRejected() {
+        TaskException taskException =
+                TaskException.forStatus(BackupTransport.TRANSPORT_PACKAGE_REJECTED);
+
+        int status = taskException.getStatus();
+
+        assertThat(status).isEqualTo(BackupTransport.TRANSPORT_PACKAGE_REJECTED);
+    }
+
+    @Test
+    public void testGetStatus_whenStatusIsTransportNotInitialized() {
+        TaskException taskException =
+                TaskException.forStatus(BackupTransport.TRANSPORT_NOT_INITIALIZED);
+
+        int status = taskException.getStatus();
+
+        assertThat(status).isEqualTo(BackupTransport.TRANSPORT_NOT_INITIALIZED);
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/testing/TransportData.java b/services/robotests/src/com/android/server/backup/testing/TransportData.java
index 4c67180..77f5d9a4 100644
--- a/services/robotests/src/com/android/server/backup/testing/TransportData.java
+++ b/services/robotests/src/com/android/server/backup/testing/TransportData.java
@@ -48,9 +48,9 @@
 
     public static TransportData localTransport() {
         return new TransportData(
-                "android/com.android.internal.backup.LocalTransport",
-                "android/com.android.internal.backup.LocalTransportService",
-                "com.android.internal.backup.LocalTransport",
+                "com.android.localtransport/.LocalTransport",
+                "com.android.localtransport/.LocalTransportService",
+                "com.android.localtransport.LocalTransport",
                 null,
                 "Backing up to debug-only private cache",
                 null,
diff --git a/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java b/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java
index 06c7437..9a283fe 100644
--- a/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java
@@ -16,9 +16,13 @@
 
 package com.android.server.am;
 
+import static com.android.server.am.MemoryStatUtil.BYTES_IN_KILOBYTE;
 import static com.android.server.am.MemoryStatUtil.MemoryStat;
+import static com.android.server.am.MemoryStatUtil.PAGE_SIZE;
+import static com.android.server.am.MemoryStatUtil.parseMemoryMaxUsageFromMemCg;
 import static com.android.server.am.MemoryStatUtil.parseMemoryStatFromMemcg;
 import static com.android.server.am.MemoryStatUtil.parseMemoryStatFromProcfs;
+import static com.android.server.am.MemoryStatUtil.parseVmHWMFromProcfs;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
@@ -29,10 +33,12 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.Collections;
+
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class MemoryStatUtilTest {
-    private String MEMORY_STAT_CONTENTS = String.join(
+    private static final String MEMORY_STAT_CONTENTS = String.join(
             "\n",
             "cache 96", // keep different from total_cache to catch reading wrong value
             "rss 97", // keep different from total_rss to catch reading wrong value
@@ -67,7 +73,7 @@
             "total_active_file 81920",
             "total_unevictable 0");
 
-    private String PROC_STAT_CONTENTS = String.join(
+    private static final String PROC_STAT_CONTENTS = String.join(
             " ",
             "1040",
             "(system_server)",
@@ -92,7 +98,7 @@
             "0",
             "2206",
             "1257177088",
-            "3", // this is rss in bytes
+            "3", // this is RSS (number of pages)
             "4294967295",
             "2936971264",
             "2936991289",
@@ -122,18 +128,65 @@
             "3198889956",
             "0");
 
+    private static final String PROC_STATUS_CONTENTS = "Name:\tandroid.youtube\n"
+        + "State:\tS (sleeping)\n"
+        + "Tgid:\t12088\n"
+        + "Pid:\t12088\n"
+        + "PPid:\t723\n"
+        + "TracerPid:\t0\n"
+        + "Uid:\t10083\t10083\t10083\t10083\n"
+        + "Gid:\t10083\t10083\t10083\t10083\n"
+        + "Ngid:\t0\n"
+        + "FDSize:\t128\n"
+        + "Groups:\t3003 9997 20083 50083 \n"
+        + "VmPeak:\t 4546844 kB\n"
+        + "VmSize:\t 4542636 kB\n"
+        + "VmLck:\t       0 kB\n"
+        + "VmPin:\t       0 kB\n"
+        + "VmHWM:\t  137668 kB\n" // RSS high watermark
+        + "VmRSS:\t  126776 kB\n"
+        + "RssAnon:\t   37860 kB\n"
+        + "RssFile:\t   88764 kB\n"
+        + "RssShmem:\t     152 kB\n"
+        + "VmData:\t 4125112 kB\n"
+        + "VmStk:\t    8192 kB\n"
+        + "VmExe:\t      24 kB\n"
+        + "VmLib:\t  102432 kB\n"
+        + "VmPTE:\t    1300 kB\n"
+        + "VmPMD:\t      36 kB\n"
+        + "VmSwap:\t       0 kB\n"
+        + "Threads:\t95\n"
+        + "SigQ:\t0/13641\n"
+        + "SigPnd:\t0000000000000000\n"
+        + "ShdPnd:\t0000000000000000\n"
+        + "SigBlk:\t0000000000001204\n"
+        + "SigIgn:\t0000000000000001\n"
+        + "SigCgt:\t00000006400084f8\n"
+        + "CapInh:\t0000000000000000\n"
+        + "CapPrm:\t0000000000000000\n"
+        + "CapEff:\t0000000000000000\n"
+        + "CapBnd:\t0000000000000000\n"
+        + "CapAmb:\t0000000000000000\n"
+        + "Seccomp:\t2\n"
+        + "Cpus_allowed:\tff\n"
+        + "Cpus_allowed_list:\t0-7\n"
+        + "Mems_allowed:\t1\n"
+        + "Mems_allowed_list:\t0\n"
+        + "voluntary_ctxt_switches:\t903\n"
+        + "nonvoluntary_ctxt_switches:\t104\n";
+
     @Test
-    public void testParseMemoryStatFromMemcg_parsesCorrectValues() throws Exception {
+    public void testParseMemoryStatFromMemcg_parsesCorrectValues() {
         MemoryStat stat = parseMemoryStatFromMemcg(MEMORY_STAT_CONTENTS);
-        assertEquals(stat.pgfault, 1);
-        assertEquals(stat.pgmajfault, 2);
-        assertEquals(stat.rssInBytes, 3);
-        assertEquals(stat.cacheInBytes, 4);
-        assertEquals(stat.swapInBytes, 5);
+        assertEquals(1, stat.pgfault);
+        assertEquals(2, stat.pgmajfault);
+        assertEquals(3, stat.rssInBytes);
+        assertEquals(4, stat.cacheInBytes);
+        assertEquals(5, stat.swapInBytes);
     }
 
     @Test
-    public void testParseMemoryStatFromMemcg_emptyMemoryStatContents() throws Exception {
+    public void testParseMemoryStatFromMemcg_emptyMemoryStatContents() {
         MemoryStat stat = parseMemoryStatFromMemcg("");
         assertNull(stat);
 
@@ -142,21 +195,56 @@
     }
 
     @Test
-    public void testParseMemoryStatFromProcfs_parsesCorrectValues() throws Exception {
+    public void testParseMemoryMaxUsageFromMemCg_parsesCorrectValue() {
+        assertEquals(1234, parseMemoryMaxUsageFromMemCg("1234"));
+    }
+
+    @Test
+    public void testParseMemoryMaxUsageFromMemCg_emptyContents() {
+        assertEquals(0, parseMemoryMaxUsageFromMemCg(""));
+
+        assertEquals(0, parseMemoryMaxUsageFromMemCg(null));
+    }
+
+    @Test
+    public void testParseMemoryMaxUsageFromMemCg_incorrectValue() {
+        assertEquals(0, parseMemoryMaxUsageFromMemCg("memory"));
+    }
+
+    @Test
+    public void testParseMemoryStatFromProcfs_parsesCorrectValues() {
         MemoryStat stat = parseMemoryStatFromProcfs(PROC_STAT_CONTENTS);
         assertEquals(1, stat.pgfault);
         assertEquals(2, stat.pgmajfault);
-        assertEquals(3, stat.rssInBytes);
+        assertEquals(3 * PAGE_SIZE, stat.rssInBytes);
         assertEquals(0, stat.cacheInBytes);
         assertEquals(0, stat.swapInBytes);
     }
 
     @Test
-    public void testParseMemoryStatFromProcfs_emptyContents() throws Exception {
+    public void testParseMemoryStatFromProcfs_emptyContents() {
         MemoryStat stat = parseMemoryStatFromProcfs("");
         assertNull(stat);
 
         stat = parseMemoryStatFromProcfs(null);
         assertNull(stat);
     }
+
+    @Test
+    public void testParseMemoryStatFromProcfs_invalidValue() {
+        String contents = String.join(" ", Collections.nCopies(24, "memory"));
+        assertNull(parseMemoryStatFromProcfs(contents));
+    }
+
+    @Test
+    public void testParseVmHWMFromProcfs_parsesCorrectValue() {
+        assertEquals(137668, parseVmHWMFromProcfs(PROC_STATUS_CONTENTS) / BYTES_IN_KILOBYTE);
+    }
+
+    @Test
+    public void testParseVmHWMFromProcfs_emptyContents() {
+        assertEquals(0, parseVmHWMFromProcfs(""));
+
+        assertEquals(0, parseVmHWMFromProcfs(null));
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java b/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
new file mode 100644
index 0000000..5a787ec
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
@@ -0,0 +1,352 @@
+/*
+ * 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.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.UsageStats;
+import android.app.usage.UsageStatsManager;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.Locale;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class UsageStatsDatabaseTest {
+    protected Context mContext;
+    private UsageStatsDatabase mUsageStatsDatabase;
+    private File mTestDir;
+
+    private IntervalStats mIntervalStats = new IntervalStats();
+    private long mEndTime = 0;
+
+    private static final UsageStatsDatabase.StatCombiner<IntervalStats> mIntervalStatsVerifier =
+            new UsageStatsDatabase.StatCombiner<IntervalStats>() {
+                @Override
+                public void combine(IntervalStats stats, boolean mutable,
+                        List<IntervalStats> accResult) {
+                    accResult.add(stats);
+                }
+            };
+
+    @Before
+    public void setUp() {
+        mContext = InstrumentationRegistry.getTargetContext();
+        mTestDir = new File(mContext.getFilesDir(), "UsageStatsDatabaseTest");
+        mUsageStatsDatabase = new UsageStatsDatabase(mTestDir);
+        mUsageStatsDatabase.init(1);
+        populateIntervalStats();
+        clearUsageStatsFiles();
+    }
+
+    /**
+     * A debugging utility for viewing the files currently in the test directory
+     */
+    private void clearUsageStatsFiles() {
+        File[] intervalDirs = mTestDir.listFiles();
+        for (File intervalDir : intervalDirs) {
+            if (intervalDir.isDirectory()) {
+                File[] usageFiles = intervalDir.listFiles();
+                for (File f : usageFiles) {
+                    f.delete();
+                }
+            }
+        }
+    }
+
+    /**
+     * A debugging utility for viewing the files currently in the test directory
+     */
+    private String dumpUsageStatsFiles() {
+        StringBuilder sb = new StringBuilder();
+        File[] intervalDirs = mTestDir.listFiles();
+        for (File intervalDir : intervalDirs) {
+            if (intervalDir.isDirectory()) {
+                File[] usageFiles = intervalDir.listFiles();
+                for (File f : usageFiles) {
+                    sb.append(f.toString());
+                }
+            }
+        }
+        return sb.toString();
+    }
+
+    private void populateIntervalStats() {
+        final int numberOfEvents = 3000;
+        long time = 1;
+        mIntervalStats = new IntervalStats();
+
+        mIntervalStats.beginTime = 1;
+        mIntervalStats.interactiveTracker.count = 2;
+        mIntervalStats.interactiveTracker.duration = 111111;
+        mIntervalStats.nonInteractiveTracker.count = 3;
+        mIntervalStats.nonInteractiveTracker.duration = 222222;
+        mIntervalStats.keyguardShownTracker.count = 4;
+        mIntervalStats.keyguardShownTracker.duration = 333333;
+        mIntervalStats.keyguardHiddenTracker.count = 5;
+        mIntervalStats.keyguardHiddenTracker.duration = 4444444;
+
+        if (mIntervalStats.events == null) {
+            mIntervalStats.events = new EventList();
+        }
+
+        for (int i = 0; i < numberOfEvents; i++) {
+            UsageEvents.Event event = new UsageEvents.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.mTimeStamp = time;
+            event.mEventType = i % 19; //"random" event type
+
+            switch (event.mEventType) {
+                case UsageEvents.Event.CONFIGURATION_CHANGE:
+                    //empty config,
+                    event.mConfiguration = new Configuration();
+                    break;
+                case UsageEvents.Event.SHORTCUT_INVOCATION:
+                    //"random" shortcut
+                    event.mShortcutId = "shortcut" + (i % 8);
+                    break;
+                case UsageEvents.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:
+                    //"random" channel
+                    event.mNotificationChannelId = "channel" + (i % 5);
+                    break;
+            }
+
+            mIntervalStats.events.insert(event);
+            mIntervalStats.update(event.mPackage, event.mTimeStamp, event.mEventType);
+
+            time += 23; // Arbitrary progression of time
+        }
+        mEndTime = time;
+
+        Configuration config1 = new Configuration();
+        config1.fontScale = 3.3f;
+        config1.mcc = 4;
+        mIntervalStats.getOrCreateConfigurationStats(config1);
+
+        Configuration config2 = new Configuration();
+        config2.mnc = 5;
+        config2.setLocale(new Locale("en", "US"));
+        mIntervalStats.getOrCreateConfigurationStats(config2);
+
+        Configuration config3 = new Configuration();
+        config3.touchscreen = 6;
+        config3.keyboard = 7;
+        mIntervalStats.getOrCreateConfigurationStats(config3);
+
+        Configuration config4 = new Configuration();
+        config4.keyboardHidden = 8;
+        config4.hardKeyboardHidden = 9;
+        mIntervalStats.getOrCreateConfigurationStats(config4);
+
+        Configuration config5 = new Configuration();
+        config5.navigation = 10;
+        config5.navigationHidden = 11;
+        mIntervalStats.getOrCreateConfigurationStats(config5);
+
+        Configuration config6 = new Configuration();
+        config6.orientation = 12;
+        //Ignore screen layout, it's determined by locale
+        mIntervalStats.getOrCreateConfigurationStats(config6);
+
+        Configuration config7 = new Configuration();
+        config7.colorMode = 14;
+        config7.uiMode = 15;
+        mIntervalStats.getOrCreateConfigurationStats(config7);
+
+        Configuration config8 = new Configuration();
+        config8.screenWidthDp = 16;
+        config8.screenHeightDp = 17;
+        mIntervalStats.getOrCreateConfigurationStats(config8);
+
+        Configuration config9 = new Configuration();
+        config9.smallestScreenWidthDp = 18;
+        config9.densityDpi = 19;
+        mIntervalStats.getOrCreateConfigurationStats(config9);
+
+        mIntervalStats.activeConfiguration = config9;
+    }
+
+    void compareUsageStats(UsageStats us1, UsageStats us2) {
+        assertEquals(us1.mPackageName, us2.mPackageName);
+        // mBeginTimeStamp is based on the enclosing IntervalStats, don't bother checking
+        // mEndTimeStamp is based on the enclosing IntervalStats, don't bother checking
+        assertEquals(us1.mLastTimeUsed, us2.mLastTimeUsed);
+        assertEquals(us1.mTotalTimeInForeground, us2.mTotalTimeInForeground);
+        // 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) {
+        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:
+                assertEquals(e1.mConfiguration, e2.mConfiguration,
+                        "Usage event " + debugId + e2.mConfiguration.toString());
+                break;
+            case UsageEvents.Event.SHORTCUT_INVOCATION:
+                assertEquals(e1.mShortcutId, e2.mShortcutId, "Usage event " + debugId);
+                break;
+            case UsageEvents.Event.STANDBY_BUCKET_CHANGED:
+                assertEquals(e1.mBucketAndReason, e2.mBucketAndReason, "Usage event " + debugId);
+                break;
+            case UsageEvents.Event.NOTIFICATION_INTERRUPTION:
+                assertEquals(e1.mNotificationChannelId, e2.mNotificationChannelId,
+                        "Usage event " + debugId);
+                break;
+        }
+        assertEquals(e1.mFlags, e2.mFlags);
+    }
+
+    void compareIntervalStats(IntervalStats stats1, IntervalStats stats2) {
+        assertEquals(stats1.beginTime, stats2.beginTime);
+        assertEquals(stats1.endTime, stats2.endTime);
+        assertEquals(stats1.interactiveTracker.count, stats2.interactiveTracker.count);
+        assertEquals(stats1.interactiveTracker.duration, stats2.interactiveTracker.duration);
+        assertEquals(stats1.nonInteractiveTracker.count, stats2.nonInteractiveTracker.count);
+        assertEquals(stats1.nonInteractiveTracker.duration, stats2.nonInteractiveTracker.duration);
+        assertEquals(stats1.keyguardShownTracker.count, stats2.keyguardShownTracker.count);
+        assertEquals(stats1.keyguardShownTracker.duration, stats2.keyguardShownTracker.duration);
+        assertEquals(stats1.keyguardHiddenTracker.count, stats2.keyguardHiddenTracker.count);
+        assertEquals(stats1.keyguardHiddenTracker.duration, stats2.keyguardHiddenTracker.duration);
+
+        String[] usageKey1 = stats1.packageStats.keySet().toArray(new String[0]);
+        String[] usageKey2 = stats2.packageStats.keySet().toArray(new String[0]);
+        for (int i = 0; i < usageKey1.length; i++) {
+            UsageStats usageStats1 = stats1.packageStats.get(usageKey1[i]);
+            UsageStats usageStats2 = stats2.packageStats.get(usageKey2[i]);
+            compareUsageStats(usageStats1, usageStats2);
+        }
+
+        assertEquals(stats1.configurations.size(), stats2.configurations.size());
+        Configuration[] configSet1 = stats1.configurations.keySet().toArray(new Configuration[0]);
+        for (int i = 0; i < configSet1.length; i++) {
+            if (!stats2.configurations.containsKey(configSet1[i])) {
+                Configuration[] configSet2 = stats2.configurations.keySet().toArray(
+                        new Configuration[0]);
+                String debugInfo = "";
+                for (Configuration c : configSet1) {
+                    debugInfo += c.toString() + "\n";
+                }
+                debugInfo += "\n";
+                for (Configuration c : configSet2) {
+                    debugInfo += c.toString() + "\n";
+                }
+                fail("Config " + configSet1[i].toString()
+                        + " not found in deserialized IntervalStat\n" + debugInfo);
+            }
+        }
+        assertEquals(stats1.activeConfiguration, stats2.activeConfiguration);
+
+        assertEquals(stats1.events.size(), stats2.events.size());
+        for (int i = 0; i < stats1.events.size(); i++) {
+            compareUsageEvent(stats1.events.get(i), stats2.events.get(i), i);
+        }
+    }
+
+    /**
+     * Runs the Write Read test.
+     * Will write the generated IntervalStat to disk, read it from disk and compare the two
+     */
+    void runWriteReadTest(int interval) throws IOException {
+        mUsageStatsDatabase.putUsageStats(interval, mIntervalStats);
+        List<IntervalStats> stats = mUsageStatsDatabase.queryUsageStats(interval, 0, mEndTime,
+                mIntervalStatsVerifier);
+
+        assertEquals(1, stats.size());
+        compareIntervalStats(mIntervalStats, stats.get(0));
+    }
+
+    /**
+     * Demonstrate that IntervalStats can be serialized and deserialized from disk without loss of
+     * relevant data.
+     */
+    @Test
+    public void testWriteRead() throws IOException {
+        runWriteReadTest(UsageStatsManager.INTERVAL_DAILY);
+        runWriteReadTest(UsageStatsManager.INTERVAL_WEEKLY);
+        runWriteReadTest(UsageStatsManager.INTERVAL_MONTHLY);
+        runWriteReadTest(UsageStatsManager.INTERVAL_YEARLY);
+    }
+
+    /**
+     * Runs the Version Change tests.
+     * Will write the generated IntervalStat to disk in one version format, "upgrade" to another
+     * version and read the automatically upgraded files on disk in the new file format.
+     */
+    void runVersionChangeTest(int oldVersion, int newVersion, int interval) throws IOException {
+        // Write IntervalStats to disk in old version format
+        UsageStatsDatabase prevDB = new UsageStatsDatabase(mTestDir, oldVersion);
+        prevDB.init(1);
+        prevDB.putUsageStats(interval, mIntervalStats);
+
+        // Simulate an upgrade to a new version and read from the disk
+        UsageStatsDatabase newDB = new UsageStatsDatabase(mTestDir, newVersion);
+        newDB.init(mEndTime);
+        List<IntervalStats> stats = newDB.queryUsageStats(interval, 0, mEndTime,
+                mIntervalStatsVerifier);
+
+        assertEquals(1, stats.size());
+        // The written and read IntervalStats should match
+        compareIntervalStats(mIntervalStats, stats.get(0));
+    }
+
+    /**
+     * Test the version upgrade from 3 to 4
+     */
+    @Test
+    public void testVersionUpgradeFrom3to4() throws IOException {
+        runVersionChangeTest(3, 4, UsageStatsManager.INTERVAL_DAILY);
+        runVersionChangeTest(3, 4, UsageStatsManager.INTERVAL_WEEKLY);
+        runVersionChangeTest(3, 4, UsageStatsManager.INTERVAL_MONTHLY);
+        runVersionChangeTest(3, 4, UsageStatsManager.INTERVAL_YEARLY);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index e7c45d5..088e229 100644
--- a/services/tests/servicestests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/RecentsAnimationControllerTest.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.view.Display.DEFAULT_DISPLAY;
@@ -24,6 +25,8 @@
 import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
 
 import static org.junit.Assert.fail;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.verify;
@@ -33,9 +36,11 @@
 import android.os.Binder;
 import android.os.IInterface;
 import android.platform.test.annotations.Presubmit;
+import android.util.SparseBooleanArray;
 import android.view.IRecentsAnimationRunner;
 import android.view.SurfaceControl;
 
+import androidx.test.filters.FlakyTest;
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
@@ -109,6 +114,25 @@
         }
     }
 
+    @Test
+    @FlakyTest(bugId = 117117823)
+    public void testIncludedApps_expectTargetAndVisible() throws Exception {
+        sWm.setRecentsAnimationController(mController);
+        final AppWindowToken homeAppWindow = createAppWindowToken(mDisplayContent,
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME);
+        final AppWindowToken appWindow = createAppWindowToken(mDisplayContent,
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+        final AppWindowToken hiddenAppWindow = createAppWindowToken(mDisplayContent,
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+        hiddenAppWindow.setHidden(true);
+        mController.initialize(mDisplayContent, ACTIVITY_TYPE_HOME, new SparseBooleanArray());
+
+        // Ensure that we are animating the target activity as well
+        assertTrue(mController.isAnimatingTask(homeAppWindow.getTask()));
+        assertTrue(mController.isAnimatingTask(appWindow.getTask()));
+        assertFalse(mController.isAnimatingTask(hiddenAppWindow.getTask()));
+    }
+
     private static void verifyNoMoreInteractionsExceptAsBinder(IInterface binder) {
         verify(binder, atLeast(0)).asBinder();
         verifyNoMoreInteractions(binder);
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 5fb8997..474e5b7 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -458,12 +458,6 @@
     }
 
     @Override
-    public void setLastInputMethodWindowLw(WindowState ime,
-            WindowState target) {
-
-    }
-
-    @Override
     public void showRecentApps() {
 
     }
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
index 6af3ea7..b7cc9ce 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
@@ -76,7 +76,8 @@
  */
 @SmallTest
 @FlakyTest(bugId = 74078662)
-@Presubmit
+// TODO(b/116597907): Re-enable this test in postsubmit after the bug is fixed.
+// @Presubmit
 @RunWith(AndroidJUnit4.class)
 public class WindowStateTests extends WindowTestsBase {
 
@@ -369,22 +370,31 @@
         final SurfaceControl.Transaction t = mock(SurfaceControl.Transaction.class);
 
         app.mHasSurface = true;
-        app.mToken.mSurfaceControl = mock(SurfaceControl.class);
+        app.mSurfaceControl = mock(SurfaceControl.class);
         try {
             app.getFrameLw().set(10, 20, 60, 80);
+            app.updateSurfacePosition(t);
 
             app.seamlesslyRotateIfAllowed(t, ROTATION_0, ROTATION_90, true);
 
             assertTrue(app.mSeamlesslyRotated);
+
+            // Verify we un-rotate the window state surface.
             Matrix matrix = new Matrix();
             // Un-rotate 90 deg
             matrix.setRotate(270);
             // Translate it back to origin
             matrix.postTranslate(0, mDisplayInfo.logicalWidth);
-            verify(t).setMatrix(eq(app.mToken.mSurfaceControl), eq(matrix), any(float[].class));
+            verify(t).setMatrix(eq(app.mSurfaceControl), eq(matrix), any(float[].class));
+
+            // Verify we update the position as well.
+            float[] currentSurfacePos = {app.mLastSurfacePosition.x, app.mLastSurfacePosition.y};
+            matrix.mapPoints(currentSurfacePos);
+            verify(t).setPosition(eq(app.mSurfaceControl), eq(currentSurfacePos[0]),
+                    eq(currentSurfacePos[1]));
         } finally {
+            app.mSurfaceControl = null;
             app.mHasSurface = false;
-            app.mToken.mSurfaceControl = null;
         }
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTracingTest.java b/services/tests/servicestests/src/com/android/server/wm/WindowTracingTest.java
index bbc6550..01b7c4f 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTracingTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTracingTest.java
@@ -59,7 +59,8 @@
  */
 @SmallTest
 @FlakyTest(bugId = 74078662)
-@Presubmit
+// TODO(b/116597907): Re-enable this test in postsubmit after the bug is fixed.
+// @Presubmit
 @RunWith(AndroidJUnit4.class)
 public class WindowTracingTest extends WindowTestsBase {
 
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 4344285..58aae2b 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -97,6 +97,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.MediaStore;
 import android.provider.Settings.Secure;
 import android.service.notification.Adjustment;
@@ -2191,6 +2192,26 @@
     }
 
     @Test
+    public void testDontAutogroupIfCritical() throws Exception {
+        NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
+        r.setCriticality(CriticalNotificationExtractor.CRITICAL_LOW);
+        mService.addEnqueuedNotification(r);
+        NotificationManagerService.PostNotificationRunnable runnable =
+                mService.new PostNotificationRunnable(r.getKey());
+        runnable.run();
+
+        r = generateNotificationRecord(mTestNotificationChannel, 1, null, false);
+        r.setCriticality(CriticalNotificationExtractor.CRITICAL);
+        runnable = mService.new PostNotificationRunnable(r.getKey());
+        mService.addEnqueuedNotification(r);
+
+        runnable.run();
+        waitForIdle();
+
+        verify(mGroupHelper, never()).onNotificationPosted(any(), anyBoolean());
+    }
+
+    @Test
     public void testNoFakeColorizedPermission() throws Exception {
         when(mPackageManagerClient.checkPermission(any(), any())).thenReturn(PERMISSION_DENIED);
         Notification.Builder nb = new Notification.Builder(mContext,
@@ -3382,10 +3403,44 @@
     }
 
     @Test
+    public void testIsCallerInstantApp_primaryUser() throws Exception {
+        ApplicationInfo info = new ApplicationInfo();
+        info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
+        when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
+
+        assertTrue(mService.isCallerInstantApp("any", 45770, 0));
+
+        info.privateFlags = 0;
+        assertFalse(mService.isCallerInstantApp("any", 575370, 0));
+    }
+
+    @Test
+    public void testIsCallerInstantApp_secondaryUser() throws Exception {
+        ApplicationInfo info = new ApplicationInfo();
+        info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
+        when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
+        when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
+
+        assertTrue(mService.isCallerInstantApp("any", 68638450, 10));
+    }
+
+    @Test
+    public void testResolveNotificationUid_sameApp_nonSystemUser() throws Exception {
+        ApplicationInfo info = new ApplicationInfo();
+        info.uid = Binder.getCallingUid();
+        when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
+        when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
+
+        int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 10);
+
+        assertEquals(info.uid, actualUid);
+    }
+
+    @Test
     public void testResolveNotificationUid_sameApp() throws Exception {
         ApplicationInfo info = new ApplicationInfo();
         info.uid = Binder.getCallingUid();
-        when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(info);
+        when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
 
         int actualUid = mService.resolveNotificationUid("caller", "caller", info.uid, 0);
 
@@ -3393,17 +3448,14 @@
     }
 
     @Test
-    public void testResolveNotificationUid_sameAppWrongPkg() throws Exception {
+    public void testResolveNotificationUid_sameAppDiffPackage() throws Exception {
         ApplicationInfo info = new ApplicationInfo();
         info.uid = Binder.getCallingUid();
-        when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(info);
+        when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
 
-        try {
-            mService.resolveNotificationUid("caller", "other", info.uid, 0);
-            fail("Incorrect pkg didn't throw security exception");
-        } catch (SecurityException e) {
-            // yay
-        }
+        int actualUid = mService.resolveNotificationUid("caller", "callerAlso", info.uid, 0);
+
+        assertEquals(info.uid, actualUid);
     }
 
     @Test
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 750345b..79998a5 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -284,8 +284,8 @@
         compareChannels(channel2,
                 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2.getId(), false));
 
-        List<NotificationChannelGroup> actualGroups =
-                mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1, false, true).getList();
+        List<NotificationChannelGroup> actualGroups = mHelper.getNotificationChannelGroups(
+                PKG_N_MR1, UID_N_MR1, false, true, false).getList();
         boolean foundNcg = false;
         for (NotificationChannelGroup actual : actualGroups) {
             if (ncg.getId().equals(actual.getId())) {
@@ -354,8 +354,8 @@
         compareChannels(channel3,
                 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3.getId(), false));
 
-        List<NotificationChannelGroup> actualGroups =
-                mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1, false, true).getList();
+        List<NotificationChannelGroup> actualGroups = mHelper.getNotificationChannelGroups(
+                PKG_N_MR1, UID_N_MR1, false, true, false).getList();
         boolean foundNcg = false;
         for (NotificationChannelGroup actual : actualGroups) {
             if (ncg.getId().equals(actual.getId())) {
@@ -1350,8 +1350,8 @@
         mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG_N_MR1}, new int[]{
                 UID_N_MR1});
 
-        assertEquals(0,
-                mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1, true, true).getList().size());
+        assertEquals(0, mHelper.getNotificationChannelGroups(
+                PKG_N_MR1, UID_N_MR1, true, true, false).getList().size());
     }
 
     @Test
@@ -1440,8 +1440,8 @@
                 new NotificationChannel("id3", "name1", NotificationManager.IMPORTANCE_HIGH);
         mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3, true, false);
 
-        List<NotificationChannelGroup> actual =
-                mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1, true, true).getList();
+        List<NotificationChannelGroup> actual = mHelper.getNotificationChannelGroups(
+                PKG_N_MR1, UID_N_MR1, true, true, false).getList();
         assertEquals(3, actual.size());
         for (NotificationChannelGroup group : actual) {
             if (group.getId() == null) {
@@ -1473,13 +1473,13 @@
                 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
         channel1.setGroup(ncg.getId());
         mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false);
-        mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1, true, true).getList();
+        mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1, true, true, false).getList();
 
         channel1.setImportance(IMPORTANCE_LOW);
         mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true);
 
-        List<NotificationChannelGroup> actual =
-                mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1, true, true).getList();
+        List<NotificationChannelGroup> actual = mHelper.getNotificationChannelGroups(
+                PKG_N_MR1, UID_N_MR1, true, true, false).getList();
 
         assertEquals(2, actual.size());
         for (NotificationChannelGroup group : actual) {
@@ -1490,6 +1490,32 @@
     }
 
     @Test
+    public void testGetChannelGroups_includeEmptyGroups() {
+        NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true);
+        NotificationChannelGroup ncgEmpty = new NotificationChannelGroup("group2", "name2");
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncgEmpty, true);
+
+        NotificationChannel channel1 =
+                new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
+        channel1.setGroup(ncg.getId());
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false);
+
+        List<NotificationChannelGroup> actual = mHelper.getNotificationChannelGroups(
+                PKG_N_MR1, UID_N_MR1, false, false, true).getList();
+
+        assertEquals(2, actual.size());
+        for (NotificationChannelGroup group : actual) {
+            if (Objects.equals(group.getId(), ncg.getId())) {
+                assertEquals(1, group.getChannels().size());
+            }
+            if (Objects.equals(group.getId(), ncgEmpty.getId())) {
+                assertEquals(0, group.getChannels().size());
+            }
+        }
+    }
+
+    @Test
     public void testCreateChannel_updateName() throws Exception {
         NotificationChannel nc = new NotificationChannel("id", "hello", IMPORTANCE_DEFAULT);
         mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index 702161e..13f3e5e 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -1030,6 +1030,14 @@
         assertEquals(1, mZenModeHelperSpy.mConditions.mSubscriptions.size());
     }
 
+    @Test
+    public void testEmptyDefaultRulesMap() {
+        ZenModeConfig config = new ZenModeConfig();
+        config.automaticRules = new ArrayMap<>();
+        mZenModeHelperSpy.mConfig = config;
+        mZenModeHelperSpy.updateDefaultZenRules(); // shouldn't throw null pointer
+    }
+
     private void setupZenConfig() {
         mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
         mZenModeHelperSpy.mConfig.allowAlarms = false;
diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java
index 4b7e21f..db9972f 100644
--- a/services/usage/java/com/android/server/usage/IntervalStats.java
+++ b/services/usage/java/com/android/server/usage/IntervalStats.java
@@ -24,7 +24,9 @@
 import android.content.res.Configuration;
 import android.util.ArrayMap;
 import android.util.ArraySet;
+import android.util.proto.ProtoInputStream;
 
+import java.io.IOException;
 import java.util.List;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -46,7 +48,7 @@
     // keep hundreds of strings that have the same contents. We will read the string
     // and only keep it if it's not in the cache. The GC will take care of the
     // strings that had identical copies in the cache.
-    private final ArraySet<String> mStringCache = new ArraySet<>();
+    public final ArraySet<String> mStringCache = new ArraySet<>();
 
     public static final class EventTracker {
         public long curStartTime;
@@ -129,6 +131,90 @@
         return event;
     }
 
+    /**
+     * Builds a UsageEvents.Event from a proto, but does not add it internally.
+     * Built here to take advantage of the cached String Refs
+     */
+    UsageEvents.Event buildEvent(ProtoInputStream parser, List<String> stringPool)
+            throws IOException {
+        final UsageEvents.Event event = new UsageEvents.Event();
+        while (true) {
+            switch (parser.nextField()) {
+                case (int) IntervalStatsProto.Event.PACKAGE:
+                    event.mPackage = getCachedStringRef(
+                            parser.readString(IntervalStatsProto.Event.PACKAGE));
+                    break;
+                case (int) IntervalStatsProto.Event.PACKAGE_INDEX:
+                    event.mPackage = getCachedStringRef(stringPool.get(
+                            parser.readInt(IntervalStatsProto.Event.PACKAGE_INDEX) - 1));
+                    break;
+                case (int) IntervalStatsProto.Event.CLASS:
+                    event.mClass = getCachedStringRef(
+                            parser.readString(IntervalStatsProto.Event.CLASS));
+                    break;
+                case (int) IntervalStatsProto.Event.CLASS_INDEX:
+                    event.mClass = getCachedStringRef(stringPool.get(
+                            parser.readInt(IntervalStatsProto.Event.CLASS_INDEX) - 1));
+                    break;
+                case (int) IntervalStatsProto.Event.TIME_MS:
+                    event.mTimeStamp = beginTime + parser.readLong(
+                            IntervalStatsProto.Event.TIME_MS);
+                    break;
+                case (int) IntervalStatsProto.Event.FLAGS:
+                    event.mFlags = parser.readInt(IntervalStatsProto.Event.FLAGS);
+                    break;
+                case (int) IntervalStatsProto.Event.TYPE:
+                    event.mEventType = parser.readInt(IntervalStatsProto.Event.TYPE);
+                    break;
+                case (int) IntervalStatsProto.Event.CONFIG:
+                    event.mConfiguration = new Configuration();
+                    event.mConfiguration.readFromProto(parser, IntervalStatsProto.Event.CONFIG);
+                    break;
+                case (int) IntervalStatsProto.Event.SHORTCUT_ID:
+                    event.mShortcutId = parser.readString(
+                            IntervalStatsProto.Event.SHORTCUT_ID).intern();
+                    break;
+                case (int) IntervalStatsProto.Event.STANDBY_BUCKET:
+                    event.mBucketAndReason = parser.readInt(
+                            IntervalStatsProto.Event.STANDBY_BUCKET);
+                    break;
+                case (int) IntervalStatsProto.Event.NOTIFICATION_CHANNEL:
+                    event.mNotificationChannelId = parser.readString(
+                            IntervalStatsProto.Event.NOTIFICATION_CHANNEL);
+                    break;
+                case (int) IntervalStatsProto.Event.NOTIFICATION_CHANNEL_INDEX:
+                    event.mNotificationChannelId = getCachedStringRef(stringPool.get(
+                            parser.readInt(IntervalStatsProto.Event.NOTIFICATION_CHANNEL_INDEX)
+                                    - 1));
+                    break;
+                case ProtoInputStream.NO_MORE_FIELDS:
+                    // Handle default values for certain events types
+                    switch (event.mEventType) {
+                        case UsageEvents.Event.CONFIGURATION_CHANGE:
+                            if (event.mConfiguration == null) {
+                                event.mConfiguration = new Configuration();
+                            }
+                            break;
+                        case UsageEvents.Event.SHORTCUT_INVOCATION:
+                            if (event.mShortcutId == null) {
+                                event.mShortcutId = "";
+                            }
+                            break;
+                        case UsageEvents.Event.NOTIFICATION_INTERRUPTION:
+                            if (event.mNotificationChannelId == null) {
+                                event.mNotificationChannelId = "";
+                            }
+                            break;
+                    }
+                    if (event.mTimeStamp == 0) {
+                        //mTimestamp not set, assume default value 0 plus beginTime
+                        event.mTimeStamp = beginTime;
+                    }
+                    return event;
+            }
+        }
+    }
+
     private boolean isStatefulEvent(int eventType) {
         switch (eventType) {
             case UsageEvents.Event.MOVE_TO_FOREGROUND:
@@ -143,8 +229,6 @@
     /**
      * Returns whether the event type is one caused by user visible
      * interaction. Excludes those that are internally generated.
-     * @param eventType
-     * @return
      */
     private boolean isUserVisibleEvent(int eventType) {
         return eventType != UsageEvents.Event.SYSTEM_INTERACTION
@@ -184,6 +268,25 @@
         endTime = timeStamp;
     }
 
+    /**
+     * @hide
+     */
+    @VisibleForTesting
+    public void addEvent(UsageEvents.Event event) {
+        if (events == null) {
+            events = new EventList();
+        }
+        // Cache common use strings
+        event.mPackage = getCachedStringRef(event.mPackage);
+        if (event.mClass != null) {
+            event.mClass = getCachedStringRef(event.mClass);
+        }
+        if (event.mEventType == UsageEvents.Event.NOTIFICATION_INTERRUPTION) {
+            event.mNotificationChannelId = getCachedStringRef(event.mNotificationChannelId);
+        }
+        events.insert(event);
+    }
+
     void updateChooserCounts(String packageName, String category, String action) {
         UsageStats usageStats = getOrCreateUsageStats(packageName);
         if (usageStats.mChooserCounts == null) {
diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
index 5ab5dc2..c616685 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
@@ -17,6 +17,7 @@
 package com.android.server.usage;
 
 import android.app.usage.TimeSparseArray;
+import android.app.usage.UsageEvents;
 import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManager;
 import android.os.Build;
@@ -25,6 +26,10 @@
 import android.util.Slog;
 import android.util.TimeUtils;
 
+import com.android.internal.annotations.VisibleForTesting;
+
+import libcore.io.IoUtils;
+
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
 import java.io.ByteArrayInputStream;
@@ -32,18 +37,49 @@
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
 import java.io.FileReader;
 import java.io.FileWriter;
 import java.io.FilenameFilter;
+import java.io.InputStream;
 import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
 import java.util.ArrayList;
 import java.util.List;
 
 /**
- * Provides an interface to query for UsageStat data from an XML database.
+ * Provides an interface to query for UsageStat data from a Protocol Buffer database.
+ *
+ * Prior to version 4, UsageStatsDatabase used XML to store Usage Stats data to disk.
+ * When the UsageStatsDatabase version is upgraded, the files on disk are migrated to the new
+ * version on init. The steps of migration are as follows:
+ * 1) Check if version upgrade breadcrumb exists on disk, if so skip to step 4.
+ * 2) Copy current files to versioned backup files.
+ * 3) Write a temporary breadcrumb file with some info about the backed up files.
+ * 4) Deserialize a versioned backup file using the info written to the breadcrumb for the
+ * correct deserialization methodology.
+ * 5) Reserialize the data read from the file with the new version format and replace the old files
+ * 6) Repeat Step 3 and 4 for each versioned backup file matching the breadcrumb file.
+ * 7) Update the version file with the new version and build fingerprint.
+ * 8) Delete the versioned backup files (unless flagged to be kept).
+ * 9) Delete the breadcrumb file.
+ *
+ * Performing the upgrade steps in this order, protects against unexpected shutdowns mid upgrade
+ *
+ * A versioned backup file is simply a copy of a Usage Stats file with some extra info embedded in
+ * the file name. The structure of the versioned backup filename is as followed:
+ * (original file name).(backup timestamp).(original file version).vak
+ *
+ * During the version upgrade process, the new upgraded file will have it's name set to the original
+ * file name. The backup timestamp helps distinguish between versioned backups if multiple upgrades
+ * and downgrades have taken place. The original file version denotes how to parse the file.
  */
 public class UsageStatsDatabase {
-    private static final int CURRENT_VERSION = 3;
+    private static final int DEFAULT_CURRENT_VERSION = 4;
 
     // Current version of the backup schema
     static final int BACKUP_VERSION = 1;
@@ -52,10 +88,16 @@
     // same as UsageStatsBackupHelper.KEY_USAGE_STATS
     static final String KEY_USAGE_STATS = "usage_stats";
 
+    // Persist versioned backup files.
+    // Should be false, except when testing new versions
+    // STOPSHIP: b/111422946 this should be false on launch
+    static final boolean KEEP_VAK_FILES = true;
 
     private static final String TAG = "UsageStatsDatabase";
-    private static final boolean DEBUG = UsageStatsService.DEBUG;
+    // STOPSHIP: b/111422946 this should be boolean DEBUG = UsageStatsService.DEBUG; on launch
+    private static final boolean DEBUG = true;
     private static final String BAK_SUFFIX = ".bak";
+    private static final String VERSIONED_BAK_SUFFIX = ".vak";
     private static final String CHECKED_IN_SUFFIX = UsageStatsXml.CHECKED_IN_SUFFIX;
     private static final String RETENTION_LEN_KEY = "ro.usagestats.chooser.retention";
     private static final int SELECTION_LOG_RETENTION_LEN =
@@ -66,21 +108,40 @@
     private final TimeSparseArray<AtomicFile>[] mSortedStatFiles;
     private final UnixCalendar mCal;
     private final File mVersionFile;
+    // If this file exists on disk, UsageStatsDatabase is in the middle of migrating files to a new
+    // version. If this file exists on boot, the upgrade was interrupted and needs to be picked up
+    // where it left off.
+    private final File mUpdateBreadcrumb;
+    // Current version of the database files schema
+    private final int mCurrentVersion;
     private boolean mFirstUpdate;
     private boolean mNewUpdate;
 
-    public UsageStatsDatabase(File dir) {
-        mIntervalDirs = new File[] {
+    /**
+     * UsageStatsDatabase constructor that allows setting the version number.
+     * This should only be used for testing.
+     *
+     * @hide
+     */
+    @VisibleForTesting
+    public UsageStatsDatabase(File dir, int version) {
+        mIntervalDirs = new File[]{
                 new File(dir, "daily"),
                 new File(dir, "weekly"),
                 new File(dir, "monthly"),
                 new File(dir, "yearly"),
         };
+        mCurrentVersion = version;
         mVersionFile = new File(dir, "version");
+        mUpdateBreadcrumb = new File(dir, "breadcrumb");
         mSortedStatFiles = new TimeSparseArray[mIntervalDirs.length];
         mCal = new UnixCalendar(0);
     }
 
+    public UsageStatsDatabase(File dir) {
+        this(dir, DEFAULT_CURRENT_VERSION);
+    }
+
     /**
      * Initialize any directories required and index what stats are available.
      */
@@ -154,7 +215,7 @@
             try {
                 IntervalStats stats = new IntervalStats();
                 for (int i = start; i < fileCount - 1; i++) {
-                    UsageStatsXml.read(files.valueAt(i), stats);
+                    readLocked(files.valueAt(i), stats);
                     if (!checkinAction.checkin(stats)) {
                         return false;
                     }
@@ -190,7 +251,7 @@
         final FilenameFilter backupFileFilter = new FilenameFilter() {
             @Override
             public boolean accept(File dir, String name) {
-                return !name.endsWith(BAK_SUFFIX);
+                return !name.endsWith(BAK_SUFFIX) && !name.endsWith(VERSIONED_BAK_SUFFIX);
             }
         };
 
@@ -210,7 +271,7 @@
                 for (File f : files) {
                     final AtomicFile af = new AtomicFile(f);
                     try {
-                        mSortedStatFiles[i].put(UsageStatsXml.parseBeginTime(af), af);
+                        mSortedStatFiles[i].put(parseBeginTime(af), af);
                     } catch (IOException e) {
                         Slog.e(TAG, "failed to index file: " + f, e);
                     }
@@ -252,14 +313,32 @@
             version = 0;
         }
 
-        if (version != CURRENT_VERSION) {
-            Slog.i(TAG, "Upgrading from version " + version + " to " + CURRENT_VERSION);
-            doUpgradeLocked(version);
+        if (version != mCurrentVersion) {
+            Slog.i(TAG, "Upgrading from version " + version + " to " + mCurrentVersion);
+            if (!mUpdateBreadcrumb.exists()) {
+                doUpgradeLocked(version);
+            } else {
+                Slog.i(TAG, "Version upgrade breadcrumb found on disk! Continuing version upgrade");
+            }
+
+            if (mUpdateBreadcrumb.exists()) {
+                int previousVersion;
+                long token;
+                try (BufferedReader reader = new BufferedReader(
+                        new FileReader(mUpdateBreadcrumb))) {
+                    token = Long.parseLong(reader.readLine());
+                    previousVersion = Integer.parseInt(reader.readLine());
+                } catch (NumberFormatException | IOException e) {
+                    Slog.e(TAG, "Failed read version upgrade breadcrumb");
+                    throw new RuntimeException(e);
+                }
+                continueUpgradeLocked(previousVersion, token);
+            }
         }
 
-        if (version != CURRENT_VERSION || mNewUpdate) {
+        if (version != mCurrentVersion || mNewUpdate) {
             try (BufferedWriter writer = new BufferedWriter(new FileWriter(mVersionFile))) {
-                writer.write(Integer.toString(CURRENT_VERSION));
+                writer.write(Integer.toString(mCurrentVersion));
                 writer.write("\n");
                 writer.write(currentFingerprint);
                 writer.write("\n");
@@ -269,6 +348,14 @@
                 throw new RuntimeException(e);
             }
         }
+
+        if (mUpdateBreadcrumb.exists()) {
+            // Files should be up to date with current version. Clear the version update breadcrumb
+            if (!KEEP_VAK_FILES) {
+                removeVersionedBackupFiles();
+            }
+            mUpdateBreadcrumb.delete();
+        }
     }
 
     private String getBuildFingerprint() {
@@ -290,6 +377,119 @@
                     }
                 }
             }
+        } else {
+            // Turn all current usage stats files into versioned backup files
+            final long token = System.currentTimeMillis();
+            final FilenameFilter backupFileFilter = new FilenameFilter() {
+                @Override
+                public boolean accept(File dir, String name) {
+                    return !name.endsWith(BAK_SUFFIX) && !name.endsWith(VERSIONED_BAK_SUFFIX);
+                }
+            };
+
+            for (int i = 0; i < mIntervalDirs.length; i++) {
+                File[] files = mIntervalDirs[i].listFiles(backupFileFilter);
+                if (files != null) {
+                    for (int j = 0; j < files.length; j++) {
+                        final File backupFile = new File(
+                                files[j].toString() + "." + Long.toString(token) + "."
+                                        + Integer.toString(thisVersion) + VERSIONED_BAK_SUFFIX);
+                        if (DEBUG) {
+                            Slog.d(TAG, "Creating versioned (" + Integer.toString(thisVersion)
+                                    + ") backup of " + files[j].toString()
+                                    + " stat files for interval "
+                                    + i + " to " + backupFile.toString());
+                        }
+
+                        try {
+                            // Backup file should not already exist, but make sure it doesn't
+                            Files.deleteIfExists(backupFile.toPath());
+                            Files.move(files[j].toPath(), backupFile.toPath(),
+                                    StandardCopyOption.ATOMIC_MOVE);
+                        } catch (IOException e) {
+                            Slog.e(TAG, "Failed to back up file : " + files[j].toString());
+                            throw new RuntimeException(e);
+                        }
+                    }
+                }
+            }
+
+            // Leave a breadcrumb behind noting that all the usage stats have been copied to a
+            // versioned backup.
+            BufferedWriter writer = null;
+            try {
+                writer = new BufferedWriter(new FileWriter(mUpdateBreadcrumb));
+                writer.write(Long.toString(token));
+                writer.write("\n");
+                writer.write(Integer.toString(thisVersion));
+                writer.write("\n");
+                writer.flush();
+            } catch (IOException e) {
+                Slog.e(TAG, "Failed to write new version upgrade breadcrumb");
+                throw new RuntimeException(e);
+            } finally {
+                IoUtils.closeQuietly(writer);
+            }
+        }
+    }
+
+    private void continueUpgradeLocked(int version, long token) {
+        // Read all the backed ups for the specified version and rewrite them with the current
+        // version's file format.
+        final FilenameFilter versionedBackupFileFilter = new FilenameFilter() {
+            @Override
+            public boolean accept(File dir, String name) {
+                return name.endsWith("." + Long.toString(token) + "." + Integer.toString(version)
+                        + VERSIONED_BAK_SUFFIX);
+            }
+        };
+
+        for (int i = 0; i < mIntervalDirs.length; i++) {
+            File[] files = mIntervalDirs[i].listFiles(versionedBackupFileFilter);
+            if (files != null) {
+                for (int j = 0; j < files.length; j++) {
+                    if (DEBUG) {
+                        Slog.d(TAG,
+                                "Upgrading " + files[j].toString() + " to version ("
+                                        + Integer.toString(
+                                        mCurrentVersion) + ") for interval " + i);
+                    }
+                    try {
+                        IntervalStats stats = new IntervalStats();
+                        readLocked(new AtomicFile(files[j]), stats, version);
+                        writeLocked(new AtomicFile(new File(mIntervalDirs[i],
+                                Long.toString(stats.beginTime))), stats, mCurrentVersion);
+                    } catch (IOException e) {
+                        Slog.e(TAG,
+                                "Failed to upgrade versioned backup file : " + files[j].toString());
+                        throw new RuntimeException(e);
+                    }
+                }
+            }
+        }
+    }
+
+    private void removeVersionedBackupFiles() {
+        final FilenameFilter versionedBackupFileFilter = new FilenameFilter() {
+            @Override
+            public boolean accept(File dir, String name) {
+                return name.endsWith(VERSIONED_BAK_SUFFIX);
+            }
+        };
+
+        for (int i = 0; i < mIntervalDirs.length; i++) {
+            File[] files = mIntervalDirs[i].listFiles(versionedBackupFileFilter);
+            if (files != null) {
+                for (int j = 0; j < files.length; j++) {
+                    if (DEBUG) {
+                        Slog.d(TAG,
+                                "Removing " + files[j].toString() + " for interval " + i);
+                    }
+                    if (!files[j].delete()) {
+                        Slog.e(TAG, "Failed to delete file : " + files[j].toString());
+                    }
+                }
+            }
         }
     }
 
@@ -357,7 +557,7 @@
             try {
                 final AtomicFile f = mSortedStatFiles[intervalType].valueAt(fileCount - 1);
                 IntervalStats stats = new IntervalStats();
-                UsageStatsXml.read(f, stats);
+                readLocked(f, stats);
                 return stats;
             } catch (IOException e) {
                 Slog.e(TAG, "Failed to read usage stats file", e);
@@ -379,8 +579,8 @@
          * which means you should make a copy of the data before adding it to the
          * <code>accumulatedResult</code> list.
          *
-         * @param stats The {@link IntervalStats} object selected.
-         * @param mutable Whether or not the data inside the stats object is mutable.
+         * @param stats             The {@link IntervalStats} object selected.
+         * @param mutable           Whether or not the data inside the stats object is mutable.
          * @param accumulatedResult The list to which to add extracted data.
          */
         void combine(IntervalStats stats, boolean mutable, List<T> accumulatedResult);
@@ -443,7 +643,7 @@
                 }
 
                 try {
-                    UsageStatsXml.read(f, stats);
+                    readLocked(f, stats);
                     if (beginTime < stats.endTime) {
                         combiner.combine(stats, false, results);
                     }
@@ -523,14 +723,9 @@
         File[] files = dir.listFiles();
         if (files != null) {
             for (File f : files) {
-                String path = f.getPath();
-                if (path.endsWith(BAK_SUFFIX)) {
-                    f = new File(path.substring(0, path.length() - BAK_SUFFIX.length()));
-                }
-
                 long beginTime;
                 try {
-                    beginTime = UsageStatsXml.parseBeginTime(f);
+                    beginTime = parseBeginTime(f);
                 } catch (IOException e) {
                     beginTime = 0;
                 }
@@ -542,18 +737,13 @@
         }
     }
 
-    private static void pruneChooserCountsOlderThan(File dir, long expiryTime) {
+    private void pruneChooserCountsOlderThan(File dir, long expiryTime) {
         File[] files = dir.listFiles();
         if (files != null) {
             for (File f : files) {
-                String path = f.getPath();
-                if (path.endsWith(BAK_SUFFIX)) {
-                    f = new File(path.substring(0, path.length() - BAK_SUFFIX.length()));
-                }
-
                 long beginTime;
                 try {
-                    beginTime = UsageStatsXml.parseBeginTime(f);
+                    beginTime = parseBeginTime(f);
                 } catch (IOException e) {
                     beginTime = 0;
                 }
@@ -562,7 +752,7 @@
                     try {
                         final AtomicFile af = new AtomicFile(f);
                         final IntervalStats stats = new IntervalStats();
-                        UsageStatsXml.read(af, stats);
+                        readLocked(af, stats);
                         final int pkgCount = stats.packageStats.size();
                         for (int i = 0; i < pkgCount; i++) {
                             UsageStats pkgStats = stats.packageStats.valueAt(i);
@@ -570,7 +760,7 @@
                                 pkgStats.mChooserCounts.clear();
                             }
                         }
-                        UsageStatsXml.write(af, stats);
+                        writeLocked(af, stats);
                     } catch (IOException e) {
                         Slog.e(TAG, "Failed to delete chooser counts from usage stats file", e);
                     }
@@ -579,6 +769,222 @@
         }
     }
 
+
+    private static long parseBeginTime(AtomicFile file) throws IOException {
+        return parseBeginTime(file.getBaseFile());
+    }
+
+    private static long parseBeginTime(File file) throws IOException {
+        String name = file.getName();
+
+        // Parse out the digits from the the front of the file name
+        for (int i = 0; i < name.length(); i++) {
+            final char c = name.charAt(i);
+            if (c < '0' || c > '9') {
+                // found first char that is not a digit.
+                name = name.substring(0, i);
+                break;
+            }
+        }
+
+        try {
+            return Long.parseLong(name);
+        } catch (NumberFormatException e) {
+            throw new IOException(e);
+        }
+    }
+
+    private void writeLocked(AtomicFile file, IntervalStats stats) throws IOException {
+        writeLocked(file, stats, mCurrentVersion);
+    }
+
+    private static void writeLocked(AtomicFile file, IntervalStats stats, int version)
+            throws IOException {
+        FileOutputStream fos = file.startWrite();
+        try {
+            writeLocked(fos, stats, version);
+            file.finishWrite(fos);
+            fos = null;
+        } finally {
+            // When fos is null (successful write), this will no-op
+            file.failWrite(fos);
+        }
+    }
+
+    private void writeLocked(OutputStream out, IntervalStats stats) throws IOException {
+        writeLocked(out, stats, mCurrentVersion);
+    }
+
+    private static void writeLocked(OutputStream out, IntervalStats stats, int version)
+            throws IOException {
+        switch (version) {
+            case 1:
+            case 2:
+            case 3:
+                UsageStatsXml.write(out, stats);
+                break;
+            case 4:
+                UsageStatsProto.write(out, stats);
+                break;
+            default:
+                throw new RuntimeException(
+                        "Unhandled UsageStatsDatabase version: " + Integer.toString(version)
+                                + " on write.");
+        }
+    }
+
+    private void readLocked(AtomicFile file, IntervalStats statsOut) throws IOException {
+        readLocked(file, statsOut, mCurrentVersion);
+    }
+
+    private static void readLocked(AtomicFile file, IntervalStats statsOut, int version)
+            throws IOException {
+        try {
+            FileInputStream in = file.openRead();
+            try {
+                statsOut.beginTime = parseBeginTime(file);
+                readLocked(in, statsOut, version);
+                statsOut.lastTimeSaved = file.getLastModifiedTime();
+            } finally {
+                try {
+                    in.close();
+                } catch (IOException e) {
+                    // Empty
+                }
+            }
+        } catch (FileNotFoundException e) {
+            Slog.e(TAG, "UsageStatsDatabase", e);
+            throw e;
+        }
+        // STOPSHIP: b/111422946, b/115429334
+        // Everything below this comment is sanity check against the new database version.
+        // After the new version has soaked for some time the following should removed.
+        // The goal of this check is to make sure the the ProtoInputStream is properly reading from
+        // the UsageStats files.
+        final StringBuilder sb = new StringBuilder();
+        final int failureLogLimit = 10;
+        int failures = 0;
+
+        final int packagesSize = statsOut.packageStats.size();
+        for (int i = 0; i < packagesSize; i++) {
+            final UsageStats stat = statsOut.packageStats.valueAt(i);
+            if (stat == null) {
+                // ArrayMap may contain null values, skip them
+                continue;
+            }
+            if (stat.mPackageName.isEmpty()) {
+                if (failures++ < failureLogLimit) {
+                    sb.append("\nUnexpected empty usage stats package name loaded");
+                }
+            }
+            if (stat.mBeginTimeStamp > statsOut.endTime) {
+                if (failures++ < failureLogLimit) {
+                    sb.append("\nUnreasonable usage stats stat begin timestamp ");
+                    sb.append(stat.mBeginTimeStamp);
+                    sb.append(" loaded (beginTime : ");
+                    sb.append(statsOut.beginTime);
+                    sb.append(", endTime : ");
+                    sb.append(statsOut.endTime);
+                    sb.append(")");
+                }
+            }
+            if (stat.mEndTimeStamp > statsOut.endTime) {
+                if (failures++ < failureLogLimit) {
+                    sb.append("\nUnreasonable usage stats stat end timestamp ");
+                    sb.append(stat.mEndTimeStamp);
+                    sb.append(" loaded (beginTime : ");
+                    sb.append(statsOut.beginTime);
+                    sb.append(", endTime : ");
+                    sb.append(statsOut.endTime);
+                    sb.append(")");
+                }
+            }
+            if (stat.mLastTimeUsed > statsOut.endTime) {
+                if (failures++ < failureLogLimit) {
+                    sb.append("\nUnreasonable usage stats stat last used timestamp ");
+                    sb.append(stat.mLastTimeUsed);
+                    sb.append(" loaded (beginTime : ");
+                    sb.append(statsOut.beginTime);
+                    sb.append(", endTime : ");
+                    sb.append(statsOut.endTime);
+                    sb.append(")");
+                }
+            }
+        }
+
+        if (statsOut.events != null) {
+            final int eventSize = statsOut.events.size();
+            for (int i = 0; i < eventSize; i++) {
+                final UsageEvents.Event event = statsOut.events.get(i);
+                if (event.mPackage.isEmpty()) {
+                    if (failures++ < failureLogLimit) {
+                        sb.append("\nUnexpected empty empty package name loaded");
+                    }
+                }
+                if (event.mTimeStamp < statsOut.beginTime || event.mTimeStamp > statsOut.endTime) {
+                    if (failures++ < failureLogLimit) {
+                        sb.append("\nUnexpected event timestamp ");
+                        sb.append(event.mTimeStamp);
+                        sb.append(" loaded (beginTime : ");
+                        sb.append(statsOut.beginTime);
+                        sb.append(", endTime : ");
+                        sb.append(statsOut.endTime);
+                        sb.append(")");
+                    }
+                }
+                if (event.mEventType < 0 || event.mEventType > UsageEvents.Event.MAX_EVENT_TYPE) {
+                    if (failures++ < failureLogLimit) {
+                        sb.append("\nUnexpected event type ");
+                        sb.append(event.mEventType);
+                        sb.append(" loaded");
+                    }
+                }
+                if ((event.mFlags & ~UsageEvents.Event.VALID_FLAG_BITS) != 0) {
+                    if (failures++ < failureLogLimit) {
+                        sb.append("\nUnexpected event flag bit 0b");
+                        sb.append(Integer.toBinaryString(event.mFlags));
+                        sb.append(" loaded");
+                    }
+                }
+            }
+        }
+
+        if (failures != 0) {
+            if (failures > failureLogLimit) {
+                sb.append("\nFailure log limited (");
+                sb.append(failures);
+                sb.append(" total failures found!)");
+            }
+            sb.append("\nError found in:\n");
+            sb.append(file.getBaseFile().getAbsolutePath());
+            sb.append("\nPlease go to b/115429334 to help root cause this issue");
+            Slog.wtf(TAG,sb.toString());
+        }
+    }
+
+    private void readLocked(InputStream in, IntervalStats statsOut) throws IOException {
+        readLocked(in, statsOut, mCurrentVersion);
+    }
+
+    private static void readLocked(InputStream in, IntervalStats statsOut, int version)
+            throws IOException {
+        switch (version) {
+            case 1:
+            case 2:
+            case 3:
+                UsageStatsXml.read(in, statsOut);
+                break;
+            case 4:
+                UsageStatsProto.read(in, statsOut);
+                break;
+            default:
+                throw new RuntimeException(
+                        "Unhandled UsageStatsDatabase version: " + Integer.toString(version)
+                                + " on read.");
+        }
+
+    }
+
     /**
      * Update the stats in the database. They may not be written to disk immediately.
      */
@@ -596,7 +1002,7 @@
                 mSortedStatFiles[intervalType].put(stats.beginTime, f);
             }
 
-            UsageStatsXml.write(f, stats);
+            writeLocked(f, stats);
             stats.lastTimeSaved = f.getLastModifiedTime();
         }
     }
@@ -730,7 +1136,7 @@
             throws IOException {
         IntervalStats stats = new IntervalStats();
         try {
-            UsageStatsXml.read(statsFile, stats);
+            readLocked(statsFile, stats);
         } catch (IOException e) {
             Slog.e(TAG, "Failed to read usage stats file", e);
             out.writeInt(0);
@@ -756,12 +1162,12 @@
         if (stats.events != null) stats.events.clear();
     }
 
-    private static byte[] serializeIntervalStats(IntervalStats stats) {
+    private byte[] serializeIntervalStats(IntervalStats stats) {
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         DataOutputStream out = new DataOutputStream(baos);
         try {
             out.writeLong(stats.beginTime);
-            UsageStatsXml.write(out, stats);
+            writeLocked(out, stats);
         } catch (IOException ioe) {
             Slog.d(TAG, "Serializing IntervalStats Failed", ioe);
             baos.reset();
@@ -769,13 +1175,13 @@
         return baos.toByteArray();
     }
 
-    private static IntervalStats deserializeIntervalStats(byte[] data) {
+    private IntervalStats deserializeIntervalStats(byte[] data) {
         ByteArrayInputStream bais = new ByteArrayInputStream(data);
         DataInputStream in = new DataInputStream(bais);
         IntervalStats stats = new IntervalStats();
         try {
             stats.beginTime = in.readLong();
-            UsageStatsXml.read(in, stats);
+            readLocked(in, stats);
         } catch (IOException ioe) {
             Slog.d(TAG, "DeSerializing IntervalStats Failed", ioe);
             stats = null;
diff --git a/services/usage/java/com/android/server/usage/UsageStatsProto.java b/services/usage/java/com/android/server/usage/UsageStatsProto.java
new file mode 100644
index 0000000..30d303f
--- /dev/null
+++ b/services/usage/java/com/android/server/usage/UsageStatsProto.java
@@ -0,0 +1,552 @@
+/*
+ * 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.usage;
+
+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 android.util.Slog;
+import android.util.proto.ProtoInputStream;
+import android.util.proto.ProtoOutputStream;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.ProtocolException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * UsageStats reader/writer for Protocol Buffer format
+ */
+final class UsageStatsProto {
+    private static String TAG = "UsageStatsProto";
+
+    // Static-only utility class.
+    private UsageStatsProto() {}
+
+    private static List<String> readStringPool(ProtoInputStream proto) throws IOException {
+
+        final long token = proto.start(IntervalStatsProto.STRINGPOOL);
+        List<String> stringPool;
+        if (proto.isNextField(IntervalStatsProto.StringPool.SIZE)) {
+            stringPool = new ArrayList(proto.readInt(IntervalStatsProto.StringPool.SIZE));
+        } else {
+            stringPool = new ArrayList();
+        }
+        while (proto.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+            switch (proto.getFieldNumber()) {
+                case (int) IntervalStatsProto.StringPool.STRINGS:
+                    stringPool.add(proto.readString(IntervalStatsProto.StringPool.STRINGS));
+                    break;
+            }
+        }
+        proto.end(token);
+        return stringPool;
+    }
+
+    private static void loadUsageStats(ProtoInputStream proto, long fieldId,
+            IntervalStats statsOut, List<String> stringPool)
+            throws IOException {
+
+        final long token = proto.start(fieldId);
+        UsageStats stats;
+        if (proto.isNextField(IntervalStatsProto.UsageStats.PACKAGE_INDEX)) {
+            // Fast path reading the package name index. Most cases this should work since it is
+            // written first
+            stats = statsOut.getOrCreateUsageStats(
+                    stringPool.get(proto.readInt(IntervalStatsProto.UsageStats.PACKAGE_INDEX) - 1));
+        } else if (proto.isNextField(IntervalStatsProto.UsageStats.PACKAGE)) {
+            // No package index, try package name instead
+            stats = statsOut.getOrCreateUsageStats(
+                    proto.readString(IntervalStatsProto.UsageStats.PACKAGE));
+        } else {
+            // Temporarily store collected data to a UsageStats object. This is not efficient.
+            stats = new UsageStats();
+        }
+
+        while (proto.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+            switch (proto.getFieldNumber()) {
+                case (int) IntervalStatsProto.UsageStats.PACKAGE:
+                    // Fast track failed from some reason, add UsageStats object to statsOut now
+                    UsageStats tempPackage = statsOut.getOrCreateUsageStats(
+                            proto.readString(IntervalStatsProto.UsageStats.PACKAGE));
+                    tempPackage.mLastTimeUsed = stats.mLastTimeUsed;
+                    tempPackage.mTotalTimeInForeground = stats.mTotalTimeInForeground;
+                    tempPackage.mLastEvent = stats.mLastEvent;
+                    tempPackage.mAppLaunchCount = stats.mAppLaunchCount;
+                    stats = tempPackage;
+                    break;
+                case (int) IntervalStatsProto.UsageStats.PACKAGE_INDEX:
+                    // Fast track failed from some reason, add UsageStats object to statsOut now
+                    UsageStats tempPackageIndex = statsOut.getOrCreateUsageStats(stringPool.get(
+                            proto.readInt(IntervalStatsProto.UsageStats.PACKAGE_INDEX) - 1));
+                    tempPackageIndex.mLastTimeUsed = stats.mLastTimeUsed;
+                    tempPackageIndex.mTotalTimeInForeground = stats.mTotalTimeInForeground;
+                    tempPackageIndex.mLastEvent = stats.mLastEvent;
+                    tempPackageIndex.mAppLaunchCount = stats.mAppLaunchCount;
+                    stats = tempPackageIndex;
+                    break;
+                case (int) IntervalStatsProto.UsageStats.LAST_TIME_ACTIVE_MS:
+                    stats.mLastTimeUsed = statsOut.beginTime + proto.readLong(
+                            IntervalStatsProto.UsageStats.LAST_TIME_ACTIVE_MS);
+                    break;
+                case (int) IntervalStatsProto.UsageStats.TOTAL_TIME_ACTIVE_MS:
+                    stats.mTotalTimeInForeground = proto.readLong(
+                            IntervalStatsProto.UsageStats.TOTAL_TIME_ACTIVE_MS);
+                    break;
+                case (int) IntervalStatsProto.UsageStats.LAST_EVENT:
+                    stats.mLastEvent = proto.readInt(IntervalStatsProto.UsageStats.LAST_EVENT);
+                    break;
+                case (int) IntervalStatsProto.UsageStats.APP_LAUNCH_COUNT:
+                    stats.mAppLaunchCount = proto.readInt(
+                            IntervalStatsProto.UsageStats.APP_LAUNCH_COUNT);
+                    break;
+                case (int) IntervalStatsProto.UsageStats.CHOOSER_ACTIONS:
+                    final long chooserToken = proto.start(
+                            IntervalStatsProto.UsageStats.CHOOSER_ACTIONS);
+                    loadChooserCounts(proto, stats);
+                    proto.end(chooserToken);
+                    break;
+            }
+        }
+        if (stats.mLastTimeUsed == 0) {
+            // mLastTimeUsed was not assigned, assume default value of 0 plus beginTime;
+            stats.mLastTimeUsed = statsOut.beginTime;
+        }
+        proto.end(token);
+    }
+
+    private static void loadCountAndTime(ProtoInputStream proto, long fieldId,
+            IntervalStats.EventTracker tracker) throws IOException {
+        final long token = proto.start(fieldId);
+        while (true) {
+            switch (proto.nextField()) {
+                case (int) IntervalStatsProto.CountAndTime.COUNT:
+                    tracker.count = proto.readInt(IntervalStatsProto.CountAndTime.COUNT);
+                    break;
+                case (int) IntervalStatsProto.CountAndTime.TIME_MS:
+                    tracker.duration = proto.readLong(IntervalStatsProto.CountAndTime.TIME_MS);
+                    break;
+                case ProtoInputStream.NO_MORE_FIELDS:
+                    proto.end(token);
+                    return;
+            }
+        }
+    }
+
+    private static void loadChooserCounts(ProtoInputStream proto, UsageStats usageStats)
+            throws IOException {
+        if (usageStats.mChooserCounts == null) {
+            usageStats.mChooserCounts = new ArrayMap<>();
+        }
+        String action = null;
+        ArrayMap<String, Integer> counts;
+        if (proto.isNextField(IntervalStatsProto.UsageStats.ChooserAction.NAME)) {
+            // Fast path reading the action name. Most cases this should work since it is written
+            // first
+            action = proto.readString(IntervalStatsProto.UsageStats.ChooserAction.NAME);
+            counts = usageStats.mChooserCounts.get(action);
+            if (counts == null) {
+                counts = new ArrayMap<>();
+                usageStats.mChooserCounts.put(action, counts);
+            }
+        } else {
+            // Temporarily store collected data to an ArrayMap. This is not efficient.
+            counts = new ArrayMap<>();
+        }
+
+        while (true) {
+            switch (proto.nextField()) {
+                case (int) IntervalStatsProto.UsageStats.ChooserAction.NAME:
+                    // Fast path failed from some reason, add the ArrayMap object to usageStats now
+                    action = proto.readString(IntervalStatsProto.UsageStats.ChooserAction.NAME);
+                    usageStats.mChooserCounts.put(action, counts);
+                    break;
+                case (int) IntervalStatsProto.UsageStats.ChooserAction.COUNTS:
+                    final long token = proto.start(
+                            IntervalStatsProto.UsageStats.ChooserAction.COUNTS);
+                    loadCountsForAction(proto, counts);
+                    proto.end(token);
+                case ProtoInputStream.NO_MORE_FIELDS:
+                    if (action == null) {
+                        // default string
+                        usageStats.mChooserCounts.put("", counts);
+                    }
+                    return;
+            }
+        }
+    }
+
+    private static void loadCountsForAction(ProtoInputStream proto,
+            ArrayMap<String, Integer> counts) throws IOException {
+        String category = null;
+        int count = 0;
+        while (true) {
+            switch (proto.nextField()) {
+                case (int) IntervalStatsProto.UsageStats.ChooserAction.CategoryCount.NAME:
+                    category = proto.readString(
+                            IntervalStatsProto.UsageStats.ChooserAction.CategoryCount.NAME);
+                    break;
+                case (int) IntervalStatsProto.UsageStats.ChooserAction.CategoryCount.COUNT:
+                    count = proto.readInt(
+                            IntervalStatsProto.UsageStats.ChooserAction.CategoryCount.COUNT);
+                    break;
+                case ProtoInputStream.NO_MORE_FIELDS:
+                    if (category == null) {
+                        counts.put("", count);
+                    } else {
+                        counts.put(category, count);
+                    }
+                    return;
+            }
+        }
+    }
+
+    private static void loadConfigStats(ProtoInputStream proto, long fieldId,
+            IntervalStats statsOut) throws IOException {
+        final long token = proto.start(fieldId);
+        boolean configActive = false;
+        final Configuration config = new Configuration();
+        ConfigurationStats configStats;
+        if (proto.isNextField(IntervalStatsProto.Configuration.CONFIG)) {
+            // Fast path reading the configuration. Most cases this should work since it is
+            // written first
+            config.readFromProto(proto, IntervalStatsProto.Configuration.CONFIG);
+            configStats = statsOut.getOrCreateConfigurationStats(config);
+        } else {
+            // Temporarily store collected data to a ConfigurationStats object. This is not
+            // efficient.
+            configStats = new ConfigurationStats();
+        }
+        while (true) {
+            switch (proto.nextField()) {
+                case (int) IntervalStatsProto.Configuration.CONFIG:
+                    // Fast path failed from some reason, add ConfigStats object to statsOut now
+                    config.readFromProto(proto, IntervalStatsProto.Configuration.CONFIG);
+                    final ConfigurationStats temp = statsOut.getOrCreateConfigurationStats(config);
+                    temp.mLastTimeActive = configStats.mLastTimeActive;
+                    temp.mTotalTimeActive = configStats.mTotalTimeActive;
+                    temp.mActivationCount = configStats.mActivationCount;
+                    configStats = temp;
+                    break;
+                case (int) IntervalStatsProto.Configuration.LAST_TIME_ACTIVE_MS:
+                    configStats.mLastTimeActive = statsOut.beginTime + proto.readLong(
+                            IntervalStatsProto.Configuration.LAST_TIME_ACTIVE_MS);
+                    break;
+                case (int) IntervalStatsProto.Configuration.TOTAL_TIME_ACTIVE_MS:
+                    configStats.mTotalTimeActive = proto.readLong(
+                            IntervalStatsProto.Configuration.TOTAL_TIME_ACTIVE_MS);
+                    break;
+                case (int) IntervalStatsProto.Configuration.COUNT:
+                    configStats.mActivationCount = proto.readInt(
+                            IntervalStatsProto.Configuration.COUNT);
+                    break;
+                case (int) IntervalStatsProto.Configuration.ACTIVE:
+                    configActive = proto.readBoolean(IntervalStatsProto.Configuration.ACTIVE);
+                    break;
+                case ProtoInputStream.NO_MORE_FIELDS:
+                    if (configStats.mLastTimeActive == 0) {
+                        //mLastTimeActive was not assigned, assume default value of 0 plus beginTime
+                        configStats.mLastTimeActive = statsOut.beginTime;
+                    }
+                    if (configActive) {
+                        statsOut.activeConfiguration = configStats.mConfiguration;
+                    }
+                    proto.end(token);
+                    return;
+            }
+        }
+    }
+
+    private static void loadEvent(ProtoInputStream proto, long fieldId, IntervalStats statsOut,
+            List<String> stringPool) throws IOException {
+        final long token = proto.start(fieldId);
+        UsageEvents.Event event = statsOut.buildEvent(proto, stringPool);
+        proto.end(token);
+        if (event.mPackage == null) {
+            throw new ProtocolException("no package field present");
+        }
+
+        if (statsOut.events == null) {
+            statsOut.events = new EventList();
+        }
+        statsOut.events.insert(event);
+    }
+
+    private static void writeStringPool(ProtoOutputStream proto, final IntervalStats stats)
+            throws IOException {
+        final long token = proto.start(IntervalStatsProto.STRINGPOOL);
+        final int size = stats.mStringCache.size();
+        proto.write(IntervalStatsProto.StringPool.SIZE, size);
+        for (int i = 0; i < size; i++) {
+            proto.write(IntervalStatsProto.StringPool.STRINGS, stats.mStringCache.valueAt(i));
+        }
+        proto.end(token);
+    }
+
+    private static void writeUsageStats(ProtoOutputStream proto, long fieldId,
+            final IntervalStats stats, final UsageStats usageStats) throws IOException {
+        final long token = proto.start(fieldId);
+        // Write the package name first, so loadUsageStats can avoid creating an extra object
+        final int packageIndex = stats.mStringCache.indexOf(usageStats.mPackageName);
+        if (packageIndex >= 0) {
+            proto.write(IntervalStatsProto.UsageStats.PACKAGE_INDEX, packageIndex + 1);
+        } else {
+            // Package not in Stringpool for some reason, write full string instead
+            Slog.w(TAG, "UsageStats package name (" + usageStats.mPackageName
+                    + ") not found in IntervalStats string cache");
+            proto.write(IntervalStatsProto.UsageStats.PACKAGE, usageStats.mPackageName);
+        }
+        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.APP_LAUNCH_COUNT, usageStats.mAppLaunchCount);
+        writeChooserCounts(proto, usageStats);
+        proto.end(token);
+    }
+
+    private static void writeCountAndTime(ProtoOutputStream proto, long fieldId, int count,
+            long time) throws IOException {
+        final long token = proto.start(fieldId);
+        proto.write(IntervalStatsProto.CountAndTime.COUNT, count);
+        proto.write(IntervalStatsProto.CountAndTime.TIME_MS, time);
+        proto.end(token);
+    }
+
+
+    private static void writeChooserCounts(ProtoOutputStream proto, final UsageStats usageStats)
+            throws IOException {
+        if (usageStats == null || usageStats.mChooserCounts == null
+                || usageStats.mChooserCounts.keySet().isEmpty()) {
+            return;
+        }
+        final int chooserCountSize = usageStats.mChooserCounts.size();
+        for (int i = 0; i < chooserCountSize; i++) {
+            final String action = usageStats.mChooserCounts.keyAt(i);
+            final ArrayMap<String, Integer> counts = usageStats.mChooserCounts.valueAt(i);
+            if (action == null || counts == null || counts.isEmpty()) {
+                continue;
+            }
+            final long token = proto.start(IntervalStatsProto.UsageStats.CHOOSER_ACTIONS);
+            proto.write(IntervalStatsProto.UsageStats.ChooserAction.NAME, action);
+            writeCountsForAction(proto, counts);
+            proto.end(token);
+        }
+    }
+
+    private static void writeCountsForAction(ProtoOutputStream proto,
+            ArrayMap<String, Integer> counts) throws IOException {
+        final int countsSize = counts.size();
+        for (int i = 0; i < countsSize; i++) {
+            String key = counts.keyAt(i);
+            int count = counts.valueAt(i);
+            if (count > 0) {
+                final long token = proto.start(IntervalStatsProto.UsageStats.ChooserAction.COUNTS);
+                proto.write(IntervalStatsProto.UsageStats.ChooserAction.CategoryCount.NAME, key);
+                proto.write(IntervalStatsProto.UsageStats.ChooserAction.CategoryCount.COUNT, count);
+                proto.end(token);
+            }
+        }
+    }
+
+    private static void writeConfigStats(ProtoOutputStream proto, long fieldId,
+            final IntervalStats stats, final ConfigurationStats configStats, boolean isActive)
+            throws IOException {
+        final long token = proto.start(fieldId);
+        configStats.mConfiguration.writeToProto(proto, IntervalStatsProto.Configuration.CONFIG);
+        proto.write(IntervalStatsProto.Configuration.LAST_TIME_ACTIVE_MS,
+                configStats.mLastTimeActive - stats.beginTime);
+        proto.write(IntervalStatsProto.Configuration.TOTAL_TIME_ACTIVE_MS,
+                configStats.mTotalTimeActive);
+        proto.write(IntervalStatsProto.Configuration.COUNT, configStats.mActivationCount);
+        proto.write(IntervalStatsProto.Configuration.ACTIVE, isActive);
+        proto.end(token);
+
+    }
+
+    private static void writeEvent(ProtoOutputStream proto, long fieldId, final IntervalStats stats,
+            final UsageEvents.Event event) throws IOException {
+        final long token = proto.start(fieldId);
+        final int packageIndex = stats.mStringCache.indexOf(event.mPackage);
+        if (packageIndex >= 0) {
+            proto.write(IntervalStatsProto.Event.PACKAGE_INDEX, packageIndex + 1);
+        } else {
+            // Package not in Stringpool for some reason, write full string instead
+            Slog.w(TAG, "Usage event package name (" + event.mPackage
+                    + ") not found in IntervalStats string cache");
+            proto.write(IntervalStatsProto.Event.PACKAGE, event.mPackage);
+        }
+        if (event.mClass != null) {
+            final int classIndex = stats.mStringCache.indexOf(event.mClass);
+            if (classIndex >= 0) {
+                proto.write(IntervalStatsProto.Event.CLASS_INDEX, classIndex + 1);
+            } else {
+                // Class not in Stringpool for some reason, write full string instead
+                Slog.w(TAG, "Usage event class name (" + event.mClass
+                        + ") not found in IntervalStats string cache");
+                proto.write(IntervalStatsProto.Event.CLASS, event.mClass);
+            }
+        }
+        proto.write(IntervalStatsProto.Event.TIME_MS, event.mTimeStamp - stats.beginTime);
+        proto.write(IntervalStatsProto.Event.FLAGS, event.mFlags);
+        proto.write(IntervalStatsProto.Event.TYPE, event.mEventType);
+        switch (event.mEventType) {
+            case UsageEvents.Event.CONFIGURATION_CHANGE:
+                if (event.mConfiguration != null) {
+                    event.mConfiguration.writeToProto(proto, IntervalStatsProto.Event.CONFIG);
+                }
+                break;
+            case UsageEvents.Event.SHORTCUT_INVOCATION:
+                if (event.mShortcutId != null) {
+                    proto.write(IntervalStatsProto.Event.SHORTCUT_ID, event.mShortcutId);
+                }
+                break;
+            case UsageEvents.Event.STANDBY_BUCKET_CHANGED:
+                if (event.mBucketAndReason != 0) {
+                    proto.write(IntervalStatsProto.Event.STANDBY_BUCKET, event.mBucketAndReason);
+                }
+                break;
+            case UsageEvents.Event.NOTIFICATION_INTERRUPTION:
+                if (event.mNotificationChannelId != null) {
+                    final int channelIndex = stats.mStringCache.indexOf(
+                            event.mNotificationChannelId);
+                    if (channelIndex >= 0) {
+                        proto.write(IntervalStatsProto.Event.NOTIFICATION_CHANNEL_INDEX,
+                                channelIndex + 1);
+                    } else {
+                        // Channel not in Stringpool for some reason, write full string instead
+                        Slog.w(TAG, "Usage event notification channel name ("
+                                + event.mNotificationChannelId
+                                + ") not found in IntervalStats string cache");
+                        proto.write(IntervalStatsProto.Event.NOTIFICATION_CHANNEL,
+                                event.mNotificationChannelId);
+                    }
+                }
+                break;
+        }
+        proto.end(token);
+    }
+
+    /**
+     * Reads from the {@link ProtoInputStream}.
+     *
+     * @param proto    The proto from which to read events.
+     * @param statsOut The stats object to populate with the data from the XML file.
+     */
+    public static void read(InputStream in, IntervalStats statsOut) throws IOException {
+        final ProtoInputStream proto = new ProtoInputStream(in);
+        List<String> stringPool = null;
+
+        statsOut.packageStats.clear();
+        statsOut.configurations.clear();
+        statsOut.activeConfiguration = null;
+
+        if (statsOut.events != null) {
+            statsOut.events.clear();
+        }
+
+        while (true) {
+            switch (proto.nextField()) {
+                case (int) IntervalStatsProto.END_TIME_MS:
+                    statsOut.endTime = statsOut.beginTime + proto.readLong(
+                            IntervalStatsProto.END_TIME_MS);
+                    break;
+                case (int) IntervalStatsProto.INTERACTIVE:
+                    loadCountAndTime(proto, IntervalStatsProto.INTERACTIVE,
+                            statsOut.interactiveTracker);
+                    break;
+                case (int) IntervalStatsProto.NON_INTERACTIVE:
+                    loadCountAndTime(proto, IntervalStatsProto.NON_INTERACTIVE,
+                            statsOut.nonInteractiveTracker);
+                    break;
+                case (int) IntervalStatsProto.KEYGUARD_SHOWN:
+                    loadCountAndTime(proto, IntervalStatsProto.KEYGUARD_SHOWN,
+                            statsOut.keyguardShownTracker);
+                    break;
+                case (int) IntervalStatsProto.KEYGUARD_HIDDEN:
+                    loadCountAndTime(proto, IntervalStatsProto.KEYGUARD_HIDDEN,
+                            statsOut.keyguardHiddenTracker);
+                    break;
+                case (int) IntervalStatsProto.STRINGPOOL:
+                    stringPool = readStringPool(proto);
+                    statsOut.mStringCache.addAll(stringPool);
+                    break;
+                case (int) IntervalStatsProto.PACKAGES:
+                    loadUsageStats(proto, IntervalStatsProto.PACKAGES, statsOut, stringPool);
+                    break;
+                case (int) IntervalStatsProto.CONFIGURATIONS:
+                    loadConfigStats(proto, IntervalStatsProto.CONFIGURATIONS, statsOut);
+                    break;
+                case (int) IntervalStatsProto.EVENT_LOG:
+                    loadEvent(proto, IntervalStatsProto.EVENT_LOG, statsOut, stringPool);
+                    break;
+                case ProtoInputStream.NO_MORE_FIELDS:
+                    if (statsOut.endTime == 0) {
+                        // endTime not assigned, assume default value of 0 plus beginTime
+                        statsOut.endTime = statsOut.beginTime;
+                    }
+                    return;
+            }
+        }
+    }
+
+    /**
+     * Writes the stats object to an ProtoBuf file.
+     *
+     * @param proto The serializer to which to write the packageStats data.
+     * @param stats The stats object to write to the XML file.
+     */
+    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);
+        // String pool should be written before the rest of the usage stats
+        writeStringPool(proto, stats);
+
+        writeCountAndTime(proto, IntervalStatsProto.INTERACTIVE, stats.interactiveTracker.count,
+                stats.interactiveTracker.duration);
+        writeCountAndTime(proto, IntervalStatsProto.NON_INTERACTIVE,
+                stats.nonInteractiveTracker.count, stats.nonInteractiveTracker.duration);
+        writeCountAndTime(proto, IntervalStatsProto.KEYGUARD_SHOWN,
+                stats.keyguardShownTracker.count, stats.keyguardShownTracker.duration);
+        writeCountAndTime(proto, IntervalStatsProto.KEYGUARD_HIDDEN,
+                stats.keyguardHiddenTracker.count, stats.keyguardHiddenTracker.duration);
+
+        final int statsCount = stats.packageStats.size();
+        for (int i = 0; i < statsCount; i++) {
+            writeUsageStats(proto, IntervalStatsProto.PACKAGES, stats,
+                    stats.packageStats.valueAt(i));
+        }
+        final int configCount = stats.configurations.size();
+        for (int i = 0; i < configCount; i++) {
+            boolean active = stats.activeConfiguration.equals(stats.configurations.keyAt(i));
+            writeConfigStats(proto, IntervalStatsProto.CONFIGURATIONS, stats,
+                    stats.configurations.valueAt(i), active);
+        }
+        final int eventCount = stats.events != null ? stats.events.size() : 0;
+        for (int i = 0; i < eventCount; i++) {
+            writeEvent(proto, IntervalStatsProto.EVENT_LOG, stats, stats.events.get(i));
+        }
+
+        proto.flush();
+    }
+}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsXml.java b/services/usage/java/com/android/server/usage/UsageStatsXml.java
index e7db741..f8d1113 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsXml.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsXml.java
@@ -19,6 +19,9 @@
 import android.util.AtomicFile;
 import android.util.Slog;
 import android.util.Xml;
+import android.util.proto.ProtoInputStream;
+import android.util.proto.ProtoOutputStream;
+
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.XmlUtils;
 import org.xmlpull.v1.XmlPullParser;
@@ -33,61 +36,7 @@
     private static final String VERSION_ATTR = "version";
     static final String CHECKED_IN_SUFFIX = "-c";
 
-    public static long parseBeginTime(AtomicFile file) throws IOException {
-        return parseBeginTime(file.getBaseFile());
-    }
-
-    public static long parseBeginTime(File file) throws IOException {
-        String name = file.getName();
-
-        // Eat as many occurrences of -c as possible. This is due to a bug where -c
-        // would be appended more than once to a checked-in file, causing a crash
-        // on boot when indexing files since Long.parseLong() will puke on anything but
-        // a number.
-        while (name.endsWith(CHECKED_IN_SUFFIX)) {
-            name = name.substring(0, name.length() - CHECKED_IN_SUFFIX.length());
-        }
-
-        try {
-            return Long.parseLong(name);
-        } catch (NumberFormatException e) {
-            throw new IOException(e);
-        }
-    }
-
-    public static void read(AtomicFile file, IntervalStats statsOut) throws IOException {
-        try {
-            FileInputStream in = file.openRead();
-            try {
-                statsOut.beginTime = parseBeginTime(file);
-                read(in, statsOut);
-                statsOut.lastTimeSaved = file.getLastModifiedTime();
-            } finally {
-                try {
-                    in.close();
-                } catch (IOException e) {
-                    // Empty
-                }
-            }
-        } catch (FileNotFoundException e) {
-            Slog.e(TAG, "UsageStats Xml", e);
-            throw e;
-        }
-    }
-
-    public static void write(AtomicFile file, IntervalStats stats) throws IOException {
-        FileOutputStream fos = file.startWrite();
-        try {
-            write(fos, stats);
-            file.finishWrite(fos);
-            fos = null;
-        } finally {
-            // When fos is null (successful write), this will no-op
-            file.failWrite(fos);
-        }
-    }
-
-    static void read(InputStream in, IntervalStats statsOut) throws IOException {
+    public static void read(InputStream in, IntervalStats statsOut) throws IOException {
         XmlPullParser parser = Xml.newPullParser();
         try {
             parser.setInput(in, "utf-8");
@@ -113,7 +62,7 @@
         }
     }
 
-    static void write(OutputStream out, IntervalStats stats) throws IOException {
+    public static void write(OutputStream out, IntervalStats stats) throws IOException {
         FastXmlSerializer xml = new FastXmlSerializer();
         xml.setOutput(out, "utf-8");
         xml.startDocument("utf-8", true);
diff --git a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
index 6a1e97a..a68f9d3 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
@@ -196,11 +196,7 @@
                 event.mNotificationChannelId = (channelId != null) ? channelId.intern() : null;
                 break;
         }
-
-        if (statsOut.events == null) {
-            statsOut.events = new EventList();
-        }
-        statsOut.events.insert(event);
+        statsOut.addEvent(event);
     }
 
     private static void writeUsageStats(XmlSerializer xml, final IntervalStats stats,
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 9b194e9..1a8aba0 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -176,12 +176,8 @@
                     currentDailyStats.activeConfiguration, newFullConfig);
         }
 
-        // Add the event to the daily list.
-        if (currentDailyStats.events == null) {
-            currentDailyStats.events = new EventList();
-        }
         if (event.mEventType != UsageEvents.Event.SYSTEM_INTERACTION) {
-            currentDailyStats.events.insert(event);
+            currentDailyStats.addEvent(event);
         }
 
         boolean incrementAppLaunch = false;
diff --git a/startop/tools/view_compiler/Android.bp b/startop/tools/view_compiler/Android.bp
new file mode 100644
index 0000000..c3e9184
--- /dev/null
+++ b/startop/tools/view_compiler/Android.bp
@@ -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.
+//
+
+cc_library_host_static {
+    name: "libviewcompiler",
+    srcs: [
+        "java_lang_builder.cc",
+        "util.cc",
+    ],
+    static_libs: [
+        "libbase"
+    ]
+}
+
+cc_binary_host {
+    name: "viewcompiler",
+    srcs: [
+        "main.cc",
+    ],
+    static_libs: [
+        "libbase",
+        "libtinyxml2",
+        "libgflags",
+        "libviewcompiler",
+    ],
+}
+
+cc_test_host {
+    name: "view-compiler-tests",
+    srcs: [
+        "util_test.cc",
+    ],
+    static_libs: [
+        "libviewcompiler",
+    ]
+}
diff --git a/startop/tools/view_compiler/README.md b/startop/tools/view_compiler/README.md
new file mode 100644
index 0000000..5659501
--- /dev/null
+++ b/startop/tools/view_compiler/README.md
@@ -0,0 +1,25 @@
+# View Compiler
+
+This directory contains an experimental compiler for layout files.
+
+It will take a layout XML file and produce a CompiledLayout.java file with a
+specialized layout inflation function.
+
+To use it, let's assume you had a layout in `my_layout.xml` and your app was in
+the Java language package `com.example.myapp`. Run the following command:
+
+    viewcompiler my_layout.xml --package com.example.myapp --out CompiledView.java
+
+This will produce a `CompiledView.java`, which can then be compiled into your
+Android app. Then to use it, in places where you would have inflated
+`R.layouts.my_layout`, instead call `CompiledView.inflate`.
+
+Precompiling views like this generally improves the time needed to inflate them.
+
+This tool is still in its early stages and has a number of limitations.
+* Currently only one layout can be compiled at a time.
+* `merge` and `include` nodes are not supported.
+* View compilation is a manual process that requires code changes in the
+  application.
+* This only works for apps that do not use a custom layout inflater.
+* Other limitations yet to be discovered.
diff --git a/startop/tools/view_compiler/TEST_MAPPING b/startop/tools/view_compiler/TEST_MAPPING
new file mode 100644
index 0000000..cc4b17a
--- /dev/null
+++ b/startop/tools/view_compiler/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "view-compiler-tests"
+    }
+  ]
+}
diff --git a/startop/tools/view_compiler/java_lang_builder.cc b/startop/tools/view_compiler/java_lang_builder.cc
new file mode 100644
index 0000000..0b8754f
--- /dev/null
+++ b/startop/tools/view_compiler/java_lang_builder.cc
@@ -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.
+ */
+
+#include "java_lang_builder.h"
+
+#include "android-base/stringprintf.h"
+
+using android::base::StringPrintf;
+using std::string;
+
+void JavaLangViewBuilder::Start() const {
+  out_ << StringPrintf("package %s;\n", package_.c_str())
+       << "import android.content.Context;\n"
+          "import android.content.res.Resources;\n"
+          "import android.content.res.XmlResourceParser;\n"
+          "import android.util.AttributeSet;\n"
+          "import android.util.Xml;\n"
+          "import android.view.*;\n"
+          "import android.widget.*;\n"
+          "\n"
+          "public final class CompiledView {\n"
+          "\n"
+          "static <T extends View> T createView(Context context, AttributeSet attrs, View parent, "
+          "String name, LayoutInflater.Factory factory, LayoutInflater.Factory2 factory2) {"
+          "\n"
+          "  if (factory2 != null) {\n"
+          "    return (T)factory2.onCreateView(parent, name, context, attrs);\n"
+          "  } else if (factory != null) {\n"
+          "    return (T)factory.onCreateView(name, context, attrs);\n"
+          "  }\n"
+          // TODO: find a way to call the private factory
+          "  return null;\n"
+          "}\n"
+          "\n"
+          "  public static View inflate(Context context) {\n"
+          "    try {\n"
+          "      LayoutInflater inflater = LayoutInflater.from(context);\n"
+          "      LayoutInflater.Factory factory = inflater.getFactory();\n"
+          "      LayoutInflater.Factory2 factory2 = inflater.getFactory2();\n"
+          "      Resources res = context.getResources();\n"
+       << StringPrintf("      XmlResourceParser xml = res.getLayout(%s.R.layout.%s);\n",
+                       package_.c_str(),
+                       layout_name_.c_str())
+       << "      AttributeSet attrs = Xml.asAttributeSet(xml);\n"
+          // The Java-language XmlPullParser needs a call to next to find the start document tag.
+          "      xml.next(); // start document\n";
+}
+
+void JavaLangViewBuilder::Finish() const {
+  out_ << "    } catch (Exception e) {\n"
+          "      return null;\n"
+          "    }\n"  // end try
+          "  }\n"    // end inflate
+          "}\n";     // end CompiledView
+}
+
+void JavaLangViewBuilder::StartView(const string& class_name) {
+  const string view_var = MakeVar("view");
+  const string layout_var = MakeVar("layout");
+  std::string parent = "null";
+  if (!view_stack_.empty()) {
+    const StackEntry& parent_entry = view_stack_.back();
+    parent = parent_entry.view_var;
+  }
+  out_ << "      xml.next(); // <" << class_name << ">\n"
+       << StringPrintf("      %s %s = createView(context, attrs, %s, \"%s\", factory, factory2);\n",
+                       class_name.c_str(),
+                       view_var.c_str(),
+                       parent.c_str(),
+                       class_name.c_str())
+       << StringPrintf("      if (%s == null) %s = new %s(context, attrs);\n",
+                       view_var.c_str(),
+                       view_var.c_str(),
+                       class_name.c_str());
+  if (!view_stack_.empty()) {
+    out_ << StringPrintf("      ViewGroup.LayoutParams %s = %s.generateLayoutParams(attrs);\n",
+                         layout_var.c_str(),
+                         parent.c_str());
+  }
+  view_stack_.push_back({class_name, view_var, layout_var});
+}
+
+void JavaLangViewBuilder::FinishView() {
+  const StackEntry var = view_stack_.back();
+  view_stack_.pop_back();
+  if (!view_stack_.empty()) {
+    const string& parent = view_stack_.back().view_var;
+    out_ << StringPrintf("      xml.next(); // </%s>\n", var.class_name.c_str())
+         << StringPrintf("      %s.addView(%s, %s);\n",
+                         parent.c_str(),
+                         var.view_var.c_str(),
+                         var.layout_params_var.c_str());
+  } else {
+    out_ << StringPrintf("      return %s;\n", var.view_var.c_str());
+  }
+}
+
+const std::string JavaLangViewBuilder::MakeVar(std::string prefix) {
+  std::stringstream v;
+  v << prefix << view_id_++;
+  return v.str();
+}
diff --git a/startop/tools/view_compiler/java_lang_builder.h b/startop/tools/view_compiler/java_lang_builder.h
new file mode 100644
index 0000000..c8d20b2
--- /dev/null
+++ b/startop/tools/view_compiler/java_lang_builder.h
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+#ifndef JAVA_LANG_BUILDER_H_
+#define JAVA_LANG_BUILDER_H_
+
+#include <iostream>
+#include <sstream>
+#include <vector>
+
+// Build Java language code to instantiate views.
+//
+// This has a very small interface to make it easier to generate additional
+// backends, such as a direct-to-DEX version.
+class JavaLangViewBuilder {
+ public:
+  JavaLangViewBuilder(std::string package, std::string layout_name, std::ostream& out = std::cout)
+      : package_(package), layout_name_(layout_name), out_(out) {}
+
+  // Begin generating a class. Adds the package boilerplate, etc.
+  void Start() const;
+  // Finish generating a class, closing off any open curly braces, etc.
+  void Finish() const;
+
+  // Begin creating a view (i.e. process the opening tag)
+  void StartView(const std::string& class_name);
+  // Finish a view, after all of its child nodes have been processed.
+  void FinishView();
+
+ private:
+  const std::string MakeVar(std::string prefix);
+
+  std::string const package_;
+  std::string const layout_name_;
+
+  std::ostream& out_;
+
+  size_t view_id_ = 0;
+
+  struct StackEntry {
+      // The class name for this view object
+      const std::string class_name;
+
+      // The variable name that is holding the view object
+      const std::string view_var;
+
+      // The variable name that holds the object's layout parameters
+      const std::string layout_params_var;
+  };
+  std::vector<StackEntry> view_stack_;
+};
+
+#endif  // JAVA_LANG_BUILDER_H_
diff --git a/startop/tools/view_compiler/main.cc b/startop/tools/view_compiler/main.cc
new file mode 100644
index 0000000..0ad7e24
--- /dev/null
+++ b/startop/tools/view_compiler/main.cc
@@ -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.
+ */
+
+#include "gflags/gflags.h"
+
+#include "java_lang_builder.h"
+#include "util.h"
+
+#include "tinyxml2.h"
+
+#include <fstream>
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <vector>
+
+using namespace tinyxml2;
+using std::string;
+
+constexpr char kStdoutFilename[]{"stdout"};
+
+DEFINE_string(package, "", "The package name for the generated class (required)");
+DEFINE_string(out, kStdoutFilename, "Where to write the generated class");
+
+namespace {
+class ViewCompilerXmlVisitor : public XMLVisitor {
+ public:
+  ViewCompilerXmlVisitor(JavaLangViewBuilder* builder) : builder_(builder) {}
+
+  bool VisitEnter(const XMLDocument& /*doc*/) override {
+    builder_->Start();
+    return true;
+  }
+
+  bool VisitExit(const XMLDocument& /*doc*/) override {
+    builder_->Finish();
+    return true;
+  }
+
+  bool VisitEnter(const XMLElement& element, const XMLAttribute* /*firstAttribute*/) override {
+    builder_->StartView(element.Name());
+    return true;
+  }
+
+  bool VisitExit(const XMLElement& /*element*/) override {
+    builder_->FinishView();
+    return true;
+  }
+
+ private:
+  JavaLangViewBuilder* builder_;
+};
+}  // end namespace
+
+int main(int argc, char** argv) {
+  constexpr size_t kProgramName = 0;
+  constexpr size_t kFileNameParam = 1;
+  constexpr size_t kNumRequiredArgs = 2;
+
+  gflags::SetUsageMessage(
+      "Compile XML layout files into equivalent Java language code\n"
+      "\n"
+      "  example usage:  viewcompiler layout.xml --package com.example.androidapp");
+  gflags::ParseCommandLineFlags(&argc, &argv, /*remove_flags*/ true);
+
+  gflags::CommandLineFlagInfo cmd = gflags::GetCommandLineFlagInfoOrDie("package");
+  if (argc != kNumRequiredArgs || cmd.is_default) {
+    gflags::ShowUsageWithFlags(argv[kProgramName]);
+    return 1;
+  }
+
+  const char* const filename = argv[kFileNameParam];
+  const string layout_name = FindLayoutNameFromFilename(filename);
+
+  // We want to generate Java language code to inflate exactly this layout. This means
+  // generating code to walk the resource XML too.
+
+  XMLDocument xml;
+  xml.LoadFile(filename);
+
+  std::ofstream outfile;
+  if (FLAGS_out != kStdoutFilename) {
+    outfile.open(FLAGS_out);
+  }
+  JavaLangViewBuilder builder{
+      FLAGS_package, layout_name, FLAGS_out == kStdoutFilename ? std::cout : outfile};
+
+  ViewCompilerXmlVisitor visitor{&builder};
+  xml.Accept(&visitor);
+
+  return 0;
+}
\ No newline at end of file
diff --git a/startop/tools/view_compiler/util.cc b/startop/tools/view_compiler/util.cc
new file mode 100644
index 0000000..69df41d
--- /dev/null
+++ b/startop/tools/view_compiler/util.cc
@@ -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.
+ */
+
+#include "util.h"
+
+using std::string;
+
+// TODO: see if we can borrow this from somewhere else, like aapt2.
+string FindLayoutNameFromFilename(const string& filename) {
+  size_t start = filename.rfind("/");
+  if (start == string::npos) {
+    start = 0;
+  } else {
+    start++;  // advance past '/' character
+  }
+  size_t end = filename.find(".", start);
+
+  return filename.substr(start, end - start);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/events/StoppedDragingEvent.java b/startop/tools/view_compiler/util.h
similarity index 62%
copy from packages/SystemUI/src/com/android/systemui/stackdivider/events/StoppedDragingEvent.java
copy to startop/tools/view_compiler/util.h
index c50d6d6..03e0939 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/events/StoppedDragingEvent.java
+++ b/startop/tools/view_compiler/util.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 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.
@@ -11,15 +11,13 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
  */
+#ifndef UTIL_H_
+#define UTIL_H_
 
-package com.android.systemui.stackdivider.events;
+#include <string>
 
-import com.android.systemui.recents.events.EventBus;
+std::string FindLayoutNameFromFilename(const std::string& filename);
 
-/**
- * Sent when the divider isn't draging anymore.
- */
-public class StoppedDragingEvent extends EventBus.Event {
-}
+#endif  // UTIL_H_
diff --git a/startop/tools/view_compiler/util_test.cc b/startop/tools/view_compiler/util_test.cc
new file mode 100644
index 0000000..d1540d3
--- /dev/null
+++ b/startop/tools/view_compiler/util_test.cc
@@ -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.
+ */
+
+#include "util.h"
+
+#include "gtest/gtest.h"
+
+using std::string;
+
+TEST(UtilTest, FindLayoutNameFromFilename) {
+  EXPECT_EQ("bar", ::FindLayoutNameFromFilename("foo/bar.xml"));
+  EXPECT_EQ("bar", ::FindLayoutNameFromFilename("bar.xml"));
+  EXPECT_EQ("bar", ::FindLayoutNameFromFilename("./foo/bar.xml"));
+  EXPECT_EQ("bar", ::FindLayoutNameFromFilename("/foo/bar.xml"));
+}
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 096cf37..08bc9bc 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -141,6 +141,8 @@
      * The caller must specify the {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE} to indicate to
      * Telecom which {@link PhoneAccountHandle} the {@link Call} should be handed over to.
      * @hide
+     * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
+     * APIs instead.
      */
     public static final String EVENT_REQUEST_HANDOVER =
             "android.telecom.event.REQUEST_HANDOVER";
@@ -149,6 +151,8 @@
      * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event.  Specifies the
      * {@link PhoneAccountHandle} to which a call should be handed over to.
      * @hide
+     * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
+     * APIs instead.
      */
     public static final String EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE =
             "android.telecom.extra.HANDOVER_PHONE_ACCOUNT_HANDLE";
@@ -161,6 +165,8 @@
      * {@link VideoProfile#STATE_BIDIRECTIONAL}, {@link VideoProfile#STATE_RX_ENABLED}, and
      * {@link VideoProfile#STATE_TX_ENABLED}.
      * @hide
+     * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
+     * APIs instead.
      */
     public static final String EXTRA_HANDOVER_VIDEO_STATE =
             "android.telecom.extra.HANDOVER_VIDEO_STATE";
@@ -176,6 +182,8 @@
      * {@link ConnectionService#onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}
      * is called to initate the handover.
      * @hide
+     * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
+     * APIs instead.
      */
     public static final String EXTRA_HANDOVER_EXTRAS = "android.telecom.extra.HANDOVER_EXTRAS";
 
@@ -186,6 +194,8 @@
      * <p>
      * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
      * @hide
+     * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
+     * APIs instead.
      */
     public static final String EVENT_HANDOVER_COMPLETE =
             "android.telecom.event.HANDOVER_COMPLETE";
@@ -198,6 +208,8 @@
      * <p>
      * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
      * @hide
+     * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
+     * APIs instead.
      */
     public static final String EVENT_HANDOVER_SOURCE_DISCONNECTED =
             "android.telecom.event.HANDOVER_SOURCE_DISCONNECTED";
@@ -209,6 +221,8 @@
      * <p>
      * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
      * @hide
+     * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
+     * APIs instead.
      */
     public static final String EVENT_HANDOVER_FAILED =
             "android.telecom.event.HANDOVER_FAILED";
@@ -434,8 +448,15 @@
          */
         public static final int PROPERTY_RTT = 0x00000400;
 
+        /**
+         * Indicates that the call has been identified as the network as an emergency call. This
+         * property may be set for both incoming and outgoing calls which the network identifies as
+         * emergency calls.
+         */
+        public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 0x00000800;
+
         //******************************************************************************************
-        // Next PROPERTY value: 0x00000800
+        // Next PROPERTY value: 0x00001000
         //******************************************************************************************
 
         private final String mTelecomCallId;
@@ -601,6 +622,9 @@
             if(hasProperty(properties, PROPERTY_ASSISTED_DIALING_USED)) {
                 builder.append(" PROPERTY_ASSISTED_DIALING_USED");
             }
+            if (hasProperty(properties, PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL)) {
+                builder.append(" PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL");
+            }
             builder.append("]");
             return builder.toString();
         }
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 120d172..34603a3 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -414,6 +414,13 @@
      */
     public static final int PROPERTY_ASSISTED_DIALING_USED = 1 << 9;
 
+    /**
+     * Set by the framework to indicate that the network has identified a Connection as an emergency
+     * call.
+     * @hide
+     */
+    public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 1 << 10;
+
     //**********************************************************************************************
     // Next PROPERTY value: 1<<10
     //**********************************************************************************************
@@ -587,6 +594,8 @@
      * {@link Call#EVENT_REQUEST_HANDOVER} that the handover from this {@link Connection} has
      * successfully completed.
      * @hide
+     * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
+     * APIs instead.
      */
     public static final String EVENT_HANDOVER_COMPLETE =
             "android.telecom.event.HANDOVER_COMPLETE";
@@ -596,6 +605,8 @@
      * {@link Call#EVENT_REQUEST_HANDOVER} that the handover from this {@link Connection} has failed
      * to complete.
      * @hide
+     * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
+     * APIs instead.
      */
     public static final String EVENT_HANDOVER_FAILED =
             "android.telecom.event.HANDOVER_FAILED";
@@ -803,6 +814,10 @@
             builder.append(isLong ? " PROPERTY_IS_RTT" : " rtt");
         }
 
+        if (can(properties, PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL)) {
+            builder.append(isLong ? " PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL" : " ecall");
+        }
+
         builder.append("]");
         return builder.toString();
     }
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index b747dce3..8c37a21 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1884,6 +1884,27 @@
         }
     }
 
+    /**
+     * Determines if there is an ongoing emergency call.  This can be either an outgoing emergency
+     * call, as identified by the dialed number, or because a call was identified by the network
+     * as an emergency call.
+     * @return {@code true} if there is an ongoing emergency call, {@code false} otherwise.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public boolean isInEmergencyCall() {
+        try {
+            if (isServiceConnected()) {
+                return getTelecomService().isInEmergencyCall();
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException isInEmergencyCall: " + e);
+            return false;
+        }
+        return false;
+    }
+
     private ITelecomService getTelecomService() {
         if (mTelecomServiceOverride != null) {
             return mTelecomServiceOverride;
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index b4e7d56..38247bc 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -279,4 +279,9 @@
      * @see TelecomServiceImpl#acceptHandover
      */
     void acceptHandover(in Uri srcAddr, int videoState, in PhoneAccountHandle destAcct);
+
+    /**
+     * @see TelecomServiceImpl#isInEmergencyCall
+     */
+    boolean isInEmergencyCall();
 }
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 8590176..57b652e 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -271,6 +271,14 @@
             KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL = "hide_carrier_network_settings_bool";
 
     /**
+     * Do only allow auto selection in Advanced Network Settings when in home network.
+     * Manual selection is allowed when in roaming network.
+     * @hide
+     */
+    public static final String
+            KEY_ONLY_AUTO_SELECT_IN_HOME_NETWORK_BOOL = "only_auto_select_in_home_network";
+
+    /**
      * Control whether users receive a simplified network settings UI and improved network
      * selection.
      */
@@ -2115,6 +2123,16 @@
     public static final String KEY_CONFIG_SHOW_ORIG_DIAL_STRING_FOR_CDMA_BOOL =
             "config_show_orig_dial_string_for_cdma";
 
+    /**
+     * Flag specifying whether to show notification(call blocking disabled) when Enhanced Call
+     * Blocking(KEY_SUPPORT_ENHANCED_CALL_BLOCKING_BOOL) is enabled and making emergency call.
+     * When true, notification is shown always.
+     * When false, notification is shown only when any setting of "Enhanced Blocked number" is
+     * enabled.
+     */
+    public static final String KEY_SHOW_CALL_BLOCKING_DISABLED_NOTIFICATION_ALWAYS_BOOL =
+            "show_call_blocking_disabled_notification_always_bool";
+
     /** The default value for every variable. */
     private final static PersistableBundle sDefaults;
 
@@ -2171,6 +2189,7 @@
         sDefaults.putBoolean(KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL, true);
         sDefaults.putBoolean(KEY_HAS_IN_CALL_NOISE_SUPPRESSION_BOOL, false);
         sDefaults.putBoolean(KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, false);
+        sDefaults.putBoolean(KEY_ONLY_AUTO_SELECT_IN_HOME_NETWORK_BOOL, false);
         sDefaults.putBoolean(KEY_SIMPLIFIED_NETWORK_SETTINGS_BOOL, false);
         sDefaults.putBoolean(KEY_HIDE_SIM_LOCK_SETTINGS_BOOL, false);
 
@@ -2453,6 +2472,7 @@
                 });
         sDefaults.putString(KEY_WCDMA_DEFAULT_SIGNAL_STRENGTH_MEASUREMENT_STRING, "");
         sDefaults.putBoolean(KEY_CONFIG_SHOW_ORIG_DIAL_STRING_FOR_CDMA_BOOL, false);
+        sDefaults.putBoolean(KEY_SHOW_CALL_BLOCKING_DISABLED_NOTIFICATION_ALWAYS_BOOL, false);
     }
 
     /**
diff --git a/telephony/java/android/telephony/MbmsGroupCallSession.java b/telephony/java/android/telephony/MbmsGroupCallSession.java
new file mode 100644
index 0000000..e373797
--- /dev/null
+++ b/telephony/java/android/telephony/MbmsGroupCallSession.java
@@ -0,0 +1,300 @@
+/*
+ * 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.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.telephony.mbms.GroupCall;
+import android.telephony.mbms.GroupCallCallback;
+import android.telephony.mbms.InternalGroupCallCallback;
+import android.telephony.mbms.InternalGroupCallSessionCallback;
+import android.telephony.mbms.MbmsErrors;
+import android.telephony.mbms.MbmsGroupCallSessionCallback;
+import android.telephony.mbms.MbmsUtils;
+import android.telephony.mbms.vendor.IMbmsGroupCallService;
+import android.util.ArraySet;
+import android.util.Log;
+
+import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * This class provides functionality for accessing group call functionality over MBMS.
+ */
+public class MbmsGroupCallSession implements AutoCloseable {
+    private static final String LOG_TAG = "MbmsGroupCallSession";
+
+    /**
+     * Service action which must be handled by the middleware implementing the MBMS group call
+     * interface.
+     * @hide
+     */
+    @SystemApi
+    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+    public static final String MBMS_GROUP_CALL_SERVICE_ACTION =
+            "android.telephony.action.EmbmsGroupCall";
+
+    /**
+     * Metadata key that specifies the component name of the service to bind to for group calls.
+     * @hide
+     */
+    @TestApi
+    public static final String MBMS_GROUP_CALL_SERVICE_OVERRIDE_METADATA =
+            "mbms-group-call-service-override";
+
+    private static AtomicBoolean sIsInitialized = new AtomicBoolean(false);
+
+    private AtomicReference<IMbmsGroupCallService> mService = new AtomicReference<>(null);
+    private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
+        @Override
+        public void binderDied() {
+            sIsInitialized.set(false);
+            mInternalCallback.onError(MbmsErrors.ERROR_MIDDLEWARE_LOST,
+                    "Received death notification");
+        }
+    };
+
+    private InternalGroupCallSessionCallback mInternalCallback;
+    private Set<GroupCall> mKnownActiveGroupCalls = new ArraySet<>();
+
+    private final Context mContext;
+    private int mSubscriptionId;
+
+    /** @hide */
+    private MbmsGroupCallSession(Context context, Executor executor, int subscriptionId,
+            MbmsGroupCallSessionCallback callback) {
+        mContext = context;
+        mSubscriptionId = subscriptionId;
+        mInternalCallback = new InternalGroupCallSessionCallback(callback, executor);
+    }
+
+    /**
+     * Create a new {@link MbmsGroupCallSession} using the given subscription ID.
+     *
+     * You may only have one instance of {@link MbmsGroupCallSession} per UID. If you call this
+     * method while there is an active instance of {@link MbmsGroupCallSession} in your process
+     * (in other words, one that has not had {@link #close()} called on it), this method will
+     * throw an {@link IllegalStateException}. If you call this method in a different process
+     * running under the same UID, an error will be indicated via
+     * {@link MbmsGroupCallSessionCallback#onError(int, String)}.
+     *
+     * Note that initialization may fail asynchronously. If you wish to try again after you
+     * receive such an asynchronous error, you must call {@link #close()} on the instance of
+     * {@link MbmsGroupCallSession} that you received before calling this method again.
+     *
+     * @param context The {@link Context} to use.
+     * @param executor The executor on which you wish to execute callbacks.
+     * @param subscriptionId The subscription ID to use.
+     * @param callback A callback object on which you wish to receive results of asynchronous
+     *                 operations.
+     * @return An instance of {@link MbmsGroupCallSession}, or null if an error occurred.
+     */
+    public static @Nullable MbmsGroupCallSession create(@NonNull Context context,
+            @NonNull Executor executor, int subscriptionId,
+            final @NonNull MbmsGroupCallSessionCallback callback) {
+        if (!sIsInitialized.compareAndSet(false, true)) {
+            throw new IllegalStateException("Cannot create two instances of MbmsGroupCallSession");
+        }
+        MbmsGroupCallSession session = new MbmsGroupCallSession(context, executor,
+                subscriptionId, callback);
+
+        final int result = session.bindAndInitialize();
+        if (result != MbmsErrors.SUCCESS) {
+            sIsInitialized.set(false);
+            executor.execute(new Runnable() {
+                @Override
+                public void run() {
+                    callback.onError(result, null);
+                }
+            });
+            return null;
+        }
+        return session;
+    }
+
+    /**
+     * Create a new {@link MbmsGroupCallSession} using the system default data subscription ID.
+     * See {@link #create(Context, Executor, int, MbmsGroupCallSessionCallback)}.
+     */
+    public static MbmsGroupCallSession create(@NonNull Context context,
+            @NonNull Executor executor, @NonNull MbmsGroupCallSessionCallback callback) {
+        return create(context, executor, SubscriptionManager.getDefaultSubscriptionId(), callback);
+    }
+
+    /**
+     * Terminates this instance. Also terminates
+     * any group calls spawned from this instance as if
+     * {@link GroupCall#close()} had been called on them. After this method returns,
+     * no further callbacks originating from the middleware will be enqueued on the provided
+     * instance of {@link MbmsGroupCallSessionCallback}, but callbacks that have already been
+     * enqueued will still be delivered.
+     *
+     * It is safe to call {@link #create(Context, Executor, int, MbmsGroupCallSessionCallback)} to
+     * obtain another instance of {@link MbmsGroupCallSession} immediately after this method
+     * returns.
+     *
+     * May throw an {@link IllegalStateException}
+     */
+    public void close() {
+        try {
+            IMbmsGroupCallService groupCallService = mService.get();
+            if (groupCallService == null) {
+                // Ignore and return, assume already disposed.
+                return;
+            }
+            groupCallService.dispose(mSubscriptionId);
+            for (GroupCall s : mKnownActiveGroupCalls) {
+                s.getCallback().stop();
+            }
+            mKnownActiveGroupCalls.clear();
+        } catch (RemoteException e) {
+            // Ignore for now
+        } finally {
+            mService.set(null);
+            sIsInitialized.set(false);
+            mInternalCallback.stop();
+        }
+    }
+
+    /**
+     * Starts the requested group call, reporting status to the indicated callback.
+     * Returns an object used to control that call.
+     *
+     * May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
+     *
+     * Asynchronous errors through the callback include any of the errors in
+     * {@link MbmsErrors.GeneralErrors}.
+     *
+     * @param executor The executor on which you wish to execute callbacks for this stream.
+     * @param tmgi The TMGI, an identifier for the group call you want to join.
+     * @param saiArray An array of SAIs for the group call that should be negotiated separately with
+     *                the carrier.
+     * @param frequencyArray An array of frequencies for the group call that should be negotiated
+     *                separately with the carrier.
+     * @param callback The callback that you want to receive information about the call on.
+     * @return An instance of {@link GroupCall} through which the call can be controlled.
+     *         May be {@code null} if an error occurred.
+     */
+    public @Nullable GroupCall startGroupCall(@NonNull Executor executor, long tmgi, int[] saiArray,
+            int[] frequencyArray, @NonNull GroupCallCallback callback) {
+        IMbmsGroupCallService groupCallService = mService.get();
+        if (groupCallService == null) {
+            throw new IllegalStateException("Middleware not yet bound");
+        }
+
+        InternalGroupCallCallback serviceCallback = new InternalGroupCallCallback(
+                callback, executor);
+
+        GroupCall serviceForApp = new GroupCall(mSubscriptionId,
+                groupCallService, this, tmgi, serviceCallback);
+        mKnownActiveGroupCalls.add(serviceForApp);
+
+        try {
+            int returnCode = groupCallService.startGroupCall(
+                    mSubscriptionId, tmgi, saiArray, frequencyArray, serviceCallback);
+            if (returnCode == MbmsErrors.UNKNOWN) {
+                // Unbind and throw an obvious error
+                close();
+                throw new IllegalStateException("Middleware must not return an unknown error code");
+            }
+            if (returnCode != MbmsErrors.SUCCESS) {
+                mInternalCallback.onError(returnCode, null);
+                return null;
+            }
+        } catch (RemoteException e) {
+            Log.w(LOG_TAG, "Remote process died");
+            mService.set(null);
+            sIsInitialized.set(false);
+            mInternalCallback.onError(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
+            return null;
+        }
+
+        return serviceForApp;
+    }
+
+    /** @hide */
+    public void onGroupCallStopped(GroupCall service) {
+        mKnownActiveGroupCalls.remove(service);
+    }
+
+    private int bindAndInitialize() {
+        return MbmsUtils.startBinding(mContext, MBMS_GROUP_CALL_SERVICE_ACTION,
+                new ServiceConnection() {
+                    @Override
+                    public void onServiceConnected(ComponentName name, IBinder service) {
+                        IMbmsGroupCallService groupCallService =
+                                IMbmsGroupCallService.Stub.asInterface(service);
+                        int result;
+                        try {
+                            result = groupCallService.initialize(mInternalCallback,
+                                    mSubscriptionId);
+                        } catch (RemoteException e) {
+                            Log.e(LOG_TAG, "Service died before initialization");
+                            mInternalCallback.onError(
+                                    MbmsErrors.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE,
+                                    e.toString());
+                            sIsInitialized.set(false);
+                            return;
+                        } catch (RuntimeException e) {
+                            Log.e(LOG_TAG, "Runtime exception during initialization");
+                            mInternalCallback.onError(
+                                    MbmsErrors.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE,
+                                    e.toString());
+                            sIsInitialized.set(false);
+                            return;
+                        }
+                        if (result == MbmsErrors.UNKNOWN) {
+                            // Unbind and throw an obvious error
+                            close();
+                            throw new IllegalStateException("Middleware must not return"
+                                    + " an unknown error code");
+                        }
+                        if (result != MbmsErrors.SUCCESS) {
+                            mInternalCallback.onError(result,
+                                    "Error returned during initialization");
+                            sIsInitialized.set(false);
+                            return;
+                        }
+                        try {
+                            groupCallService.asBinder().linkToDeath(mDeathRecipient, 0);
+                        } catch (RemoteException e) {
+                            mInternalCallback.onError(MbmsErrors.ERROR_MIDDLEWARE_LOST,
+                                    "Middleware lost during initialization");
+                            sIsInitialized.set(false);
+                            return;
+                        }
+                        mService.set(groupCallService);
+                    }
+
+                    @Override
+                    public void onServiceDisconnected(ComponentName name) {
+                        sIsInitialized.set(false);
+                        mService.set(null);
+                    }
+                });
+    }
+}
diff --git a/telephony/java/android/telephony/NeighboringCellInfo.java b/telephony/java/android/telephony/NeighboringCellInfo.java
index 8e99518..5e4518f 100644
--- a/telephony/java/android/telephony/NeighboringCellInfo.java
+++ b/telephony/java/android/telephony/NeighboringCellInfo.java
@@ -32,7 +32,11 @@
 /**
  * Represents the neighboring cell information, including
  * Received Signal Strength and Cell ID location.
+ *
+ * @deprecated This class should not be used by anyone targeting SDK level 29 (Q) or higher.
+ *      Instead callers should use {@Link android.telephony.CellInfo}.
  */
+@Deprecated
 public class NeighboringCellInfo implements Parcelable
 {
     /**
diff --git a/telephony/java/android/telephony/NetworkScan.java b/telephony/java/android/telephony/NetworkScan.java
index 7c7d7a0..202da68 100644
--- a/telephony/java/android/telephony/NetworkScan.java
+++ b/telephony/java/android/telephony/NetworkScan.java
@@ -16,11 +16,10 @@
 
 package android.telephony;
 
+import android.annotation.IntDef;
 import android.content.Context;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.annotation.IntDef;
-import android.util.Log;
 
 import com.android.internal.telephony.ITelephony;
 
@@ -113,6 +112,8 @@
         }
         try {
             telephony.stopNetworkScan(mSubId, mScanId);
+        } catch (IllegalArgumentException ex) {
+            Rlog.d(TAG,  "stopNetworkScan - no active scan for ScanID=" + mScanId);
         } catch (RemoteException ex) {
             Rlog.e(TAG, "stopNetworkScan  RemoteException", ex);
         } catch (RuntimeException ex) {
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index 498be96..3ea018a 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -281,6 +281,16 @@
      */
     public static final int LISTEN_PHONE_CAPABILITY_CHANGE                 = 0x00200000;
 
+    /**
+     *  Listen for changes to preferred data subId.
+     *  See {@link SubscriptionManager#setPreferredData(int)}
+     *  for more details.
+     *
+     *  @see #onPreferredDataSubIdChanged
+     *  @hide
+     */
+    public static final int LISTEN_PREFERRED_DATA_SUBID_CHANGE              = 0x00400000;
+
     /*
      * Subscription used to listen to the phone state changes
      * @hide
@@ -407,6 +417,9 @@
                         PhoneStateListener.this.onPhoneCapabilityChanged(
                                 (PhoneCapability) msg.obj);
                         break;
+                    case LISTEN_PREFERRED_DATA_SUBID_CHANGE:
+                        PhoneStateListener.this.onPreferredDataSubIdChanged((int) msg.obj);
+                        break;
                 }
             }
         };
@@ -647,6 +660,18 @@
     }
 
     /**
+     * Callback invoked when preferred data subId changes. Requires
+     * the READ_PRIVILEGED_PHONE_STATE permission.
+     * @param subId the new preferred data subId. If it's INVALID_SUBSCRIPTION_ID,
+     *              it means it's unset and defaultDataSub is used to determine which
+     *              modem is preferred.
+     * @hide
+     */
+    public void onPreferredDataSubIdChanged(int subId) {
+        // default implementation empty
+    }
+
+    /**
      * Callback invoked when telephony has received notice from a carrier
      * app that a network action that could result in connectivity loss
      * has been requested by an app using
@@ -777,6 +802,11 @@
         public void onPhoneCapabilityChanged(PhoneCapability capability) {
             send(LISTEN_PHONE_CAPABILITY_CHANGE, 0, 0, capability);
         }
+
+        public void onPreferredDataSubIdChanged(int subId) {
+            send(LISTEN_PREFERRED_DATA_SUBID_CHANGE, 0, 0, subId);
+        }
+
     }
 
     /**
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 777b850..cc143d6 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -1852,6 +1852,19 @@
     }
 
     /**
+     * Checks if the supplied subscription ID corresponds to an active subscription.
+     *
+     * @param subscriptionId the subscription ID.
+     * @return {@code true} if the supplied subscription ID corresponds to an active subscription;
+     * {@code false} if it does not correspond to an active subscription; or throw a
+     * SecurityException if the caller hasn't got the right permission.
+     */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    public boolean isActiveSubscriptionId(int subscriptionId) {
+        return isActiveSubId(subscriptionId);
+    }
+
+    /**
      * @return true if the sub ID is active. i.e. The sub ID corresponds to a known subscription
      * and the SIM providing the subscription is present in a slot and in "LOADED" state.
      * @hide
@@ -1861,7 +1874,7 @@
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
             if (iSub != null) {
-                return iSub.isActiveSubId(subId);
+                return iSub.isActiveSubId(subId, mContext.getOpPackageName());
             }
         } catch (RemoteException ex) {
         }
@@ -2140,9 +2153,15 @@
 
     /**
      * Set preferred default data.
-     * Set on which slot default data will be on.
+     * Set on which slot most cellular data will be on.
+     * It's also usually what we set up internet connection on.
      *
-     * @param slotId which slot is preferred to for cellular data.
+     * PreferredData overwrites user setting of default data subscription. And it's used
+     * by AlternativeNetworkAccessService or carrier apps to switch primary and CBRS
+     * subscription dynamically in multi-SIM devices.
+     *
+     * @param slotId which slot is preferred to for cellular data. If it's INVALID, it means
+     *               it's unset and defaultDataSubId is used to determine which modem is preferred.
      * @hide
      *
      */
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index a8bcbe3..ea9ac39 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -16,6 +16,8 @@
 
 package android.telephony;
 
+import static android.content.Context.TELECOM_SERVICE;
+
 import static com.android.internal.util.Preconditions.checkNotNull;
 
 import android.annotation.IntDef;
@@ -1201,6 +1203,15 @@
             "android.intent.action.DATA_STALL_DETECTED";
 
     /**
+     * A service action that identifies a {@link android.app.SmsAppService} subclass in the
+     * AndroidManifest.xml.
+     *
+     * <p>See {@link android.app.SmsAppService} for the details.
+     */
+    @SdkConstant(SdkConstantType.SERVICE_ACTION)
+    public static final String ACTION_SMS_APP_SERVICE = "android.telephony.action.SMS_APP_SERVICE";
+
+    /**
      * An int extra used with {@link #ACTION_DATA_STALL_DETECTED} to indicate the
      * action associated with the data stall recovery.
      *
@@ -1579,6 +1590,7 @@
      *
      * @return List of NeighboringCellInfo or null if info unavailable.
      *
+     * @removed
      * @deprecated Use {@link #getAllCellInfo} which returns a superset of the information
      *             from NeighboringCellInfo, including LTE cell information.
      */
@@ -2091,10 +2103,37 @@
 
     /** Max network type number. Update as new types are added. Don't add negative types. {@hide} */
     public static final int MAX_NETWORK_TYPE = NETWORK_TYPE_LTE_CA;
+
+    /** @hide */
+    @IntDef({
+            NETWORK_TYPE_UNKNOWN,
+            NETWORK_TYPE_GPRS,
+            NETWORK_TYPE_EDGE,
+            NETWORK_TYPE_UMTS,
+            NETWORK_TYPE_CDMA,
+            NETWORK_TYPE_EVDO_0,
+            NETWORK_TYPE_EVDO_A,
+            NETWORK_TYPE_1xRTT,
+            NETWORK_TYPE_HSDPA,
+            NETWORK_TYPE_HSUPA,
+            NETWORK_TYPE_HSPA,
+            NETWORK_TYPE_IDEN,
+            NETWORK_TYPE_EVDO_B,
+            NETWORK_TYPE_LTE,
+            NETWORK_TYPE_EHRPD,
+            NETWORK_TYPE_HSPAP,
+            NETWORK_TYPE_GSM,
+            NETWORK_TYPE_TD_SCDMA,
+            NETWORK_TYPE_IWLAN,
+            NETWORK_TYPE_LTE_CA,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface NetworkType{}
+
     /**
      * @return the NETWORK_TYPE_xxxx for current data connection.
      */
-    public int getNetworkType() {
+    public @NetworkType int getNetworkType() {
        try {
            ITelephony telephony = getITelephony();
            if (telephony != null) {
@@ -2139,24 +2178,24 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
-   @UnsupportedAppUsage
-   public int getNetworkType(int subId) {
-       try {
-           ITelephony telephony = getITelephony();
-           if (telephony != null) {
-               return telephony.getNetworkTypeForSubscriber(subId, getOpPackageName());
-           } else {
-               // This can happen when the ITelephony interface is not up yet.
-               return NETWORK_TYPE_UNKNOWN;
-           }
-       } catch(RemoteException ex) {
-           // This shouldn't happen in the normal case
-           return NETWORK_TYPE_UNKNOWN;
-       } catch (NullPointerException ex) {
-           // This could happen before phone restarts due to crashing
-           return NETWORK_TYPE_UNKNOWN;
-       }
-   }
+    @UnsupportedAppUsage
+    public int getNetworkType(int subId) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.getNetworkTypeForSubscriber(subId, getOpPackageName());
+            } else {
+                // This can happen when the ITelephony interface is not up yet.
+                return NETWORK_TYPE_UNKNOWN;
+            }
+        } catch (RemoteException ex) {
+            // This shouldn't happen in the normal case
+            return NETWORK_TYPE_UNKNOWN;
+        } catch (NullPointerException ex) {
+            // This could happen before phone restarts due to crashing
+            return NETWORK_TYPE_UNKNOWN;
+        }
+    }
 
     /**
      * Returns a constant indicating the radio technology (network type)
@@ -2189,7 +2228,7 @@
      */
     @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
-    public int getDataNetworkType() {
+    public @NetworkType int getDataNetworkType() {
         return getDataNetworkType(getSubId(SubscriptionManager.getDefaultDataSubscriptionId()));
     }
 
@@ -2229,7 +2268,7 @@
      */
     @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
-    public int getVoiceNetworkType() {
+    public @NetworkType int getVoiceNetworkType() {
         return getVoiceNetworkType(getSubId());
     }
 
@@ -4108,11 +4147,16 @@
     }
 
     /**
-     * Returns the IMS home network domain name that was loaded from the ISIM.
-     * @return the IMS domain name, or null if not present or not loaded
+     * Returns the IMS home network domain name that was loaded from the ISIM {@see #APPTYPE_ISIM}.
+     * @return the IMS domain name. Returns {@code null} if ISIM hasn't been loaded or IMS domain
+     * hasn't been loaded or isn't present on the ISIM.
+     *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public String getIsimDomain() {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -4340,7 +4384,7 @@
     * @hide
     */
     private ITelecomService getTelecomService() {
-        return ITelecomService.Stub.asInterface(ServiceManager.getService(Context.TELECOM_SERVICE));
+        return ITelecomService.Stub.asInterface(ServiceManager.getService(TELECOM_SERVICE));
     }
 
     private ITelephonyRegistry getTelephonyRegistry() {
@@ -5370,7 +5414,19 @@
         }
     }
 
-    // ICC SIM Application Types
+    /**
+     * UICC SIM Application Types
+     * @hide
+     */
+    @IntDef(prefix = { "APPTYPE_" }, value = {
+            APPTYPE_SIM,
+            APPTYPE_USIM,
+            APPTYPE_RUIM,
+            APPTYPE_CSIM,
+            APPTYPE_ISIM
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface UiccAppType{}
     /** UICC application type is SIM */
     public static final int APPTYPE_SIM = PhoneConstants.APPTYPE_SIM;
     /** UICC application type is USIM */
@@ -5381,6 +5437,7 @@
     public static final int APPTYPE_CSIM = PhoneConstants.APPTYPE_CSIM;
     /** UICC application type is ISIM */
     public static final int APPTYPE_ISIM = PhoneConstants.APPTYPE_ISIM;
+
     // authContext (parameter P2) when doing UICC challenge,
     // per 3GPP TS 31.102 (Section 7.1.2)
     /** Authentication type for UICC challenge is EAP SIM. See RFC 4186 for details. */
@@ -5647,6 +5704,202 @@
         }
     }
 
+    /** @hide */
+    @IntDef(prefix = { "NETWORK_MODE_" }, value = {
+            NETWORK_MODE_WCDMA_PREF,
+            NETWORK_MODE_GSM_ONLY,
+            NETWORK_MODE_WCDMA_ONLY,
+            NETWORK_MODE_GSM_UMTS,
+            NETWORK_MODE_CDMA_EVDO,
+            NETWORK_MODE_CDMA_NO_EVDO,
+            NETWORK_MODE_EVDO_NO_CDMA,
+            NETWORK_MODE_GLOBAL,
+            NETWORK_MODE_LTE_CDMA_EVDO,
+            NETWORK_MODE_LTE_GSM_WCDMA,
+            NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA,
+            NETWORK_MODE_LTE_ONLY,
+            NETWORK_MODE_LTE_WCDMA,
+            NETWORK_MODE_TDSCDMA_ONLY,
+            NETWORK_MODE_TDSCDMA_WCDMA,
+            NETWORK_MODE_LTE_TDSCDMA,
+            NETWORK_MODE_TDSCDMA_GSM,
+            NETWORK_MODE_LTE_TDSCDMA_GSM,
+            NETWORK_MODE_TDSCDMA_GSM_WCDMA,
+            NETWORK_MODE_LTE_TDSCDMA_WCDMA,
+            NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA,
+            NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA,
+            NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface PrefNetworkMode{}
+
+    /**
+     * preferred network mode is GSM/WCDMA (WCDMA preferred).
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_MODE_WCDMA_PREF = RILConstants.NETWORK_MODE_WCDMA_PREF;
+
+    /**
+     * preferred network mode is GSM only.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_MODE_GSM_ONLY = RILConstants.NETWORK_MODE_GSM_ONLY;
+
+    /**
+     * preferred network mode is WCDMA only.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_MODE_WCDMA_ONLY = RILConstants.NETWORK_MODE_WCDMA_ONLY;
+
+    /**
+     * preferred network mode is GSM/WCDMA (auto mode, according to PRL).
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_MODE_GSM_UMTS = RILConstants.NETWORK_MODE_GSM_UMTS;
+
+    /**
+     * preferred network mode is CDMA and EvDo (auto mode, according to PRL).
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_MODE_CDMA_EVDO = RILConstants.NETWORK_MODE_CDMA;
+
+    /**
+     * preferred network mode is CDMA only.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_MODE_CDMA_NO_EVDO = RILConstants.NETWORK_MODE_CDMA_NO_EVDO;
+
+    /**
+     * preferred network mode is EvDo only.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_MODE_EVDO_NO_CDMA = RILConstants.NETWORK_MODE_EVDO_NO_CDMA;
+
+    /**
+     * preferred network mode is GSM/WCDMA, CDMA, and EvDo (auto mode, according to PRL).
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_MODE_GLOBAL = RILConstants.NETWORK_MODE_GLOBAL;
+
+    /**
+     * preferred network mode is LTE, CDMA and EvDo.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_MODE_LTE_CDMA_EVDO = RILConstants.NETWORK_MODE_LTE_CDMA_EVDO;
+
+    /**
+     * preferred network mode is LTE, GSM/WCDMA.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_MODE_LTE_GSM_WCDMA = RILConstants.NETWORK_MODE_LTE_GSM_WCDMA;
+
+    /**
+     * preferred network mode is LTE, CDMA, EvDo, GSM/WCDMA.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA =
+            RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA;
+
+    /**
+     * preferred network mode is LTE Only.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_MODE_LTE_ONLY = RILConstants.NETWORK_MODE_LTE_ONLY;
+
+    /**
+     * preferred network mode is LTE/WCDMA.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_MODE_LTE_WCDMA = RILConstants.NETWORK_MODE_LTE_WCDMA;
+
+    /**
+     * preferred network mode is TD-SCDMA only.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_MODE_TDSCDMA_ONLY = RILConstants.NETWORK_MODE_TDSCDMA_ONLY;
+
+    /**
+     * preferred network mode is TD-SCDMA and WCDMA.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_MODE_TDSCDMA_WCDMA = RILConstants.NETWORK_MODE_TDSCDMA_WCDMA;
+
+    /**
+     * preferred network mode is TD-SCDMA and LTE.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_MODE_LTE_TDSCDMA = RILConstants.NETWORK_MODE_LTE_TDSCDMA;
+
+    /**
+     * preferred network mode is TD-SCDMA and GSM.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_MODE_TDSCDMA_GSM = RILConstants.NETWORK_MODE_TDSCDMA_GSM;
+
+    /**
+     * preferred network mode is TD-SCDMA,GSM and LTE.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_MODE_LTE_TDSCDMA_GSM =
+            RILConstants.NETWORK_MODE_LTE_TDSCDMA_GSM;
+
+    /**
+     * preferred network mode is TD-SCDMA, GSM/WCDMA.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_MODE_TDSCDMA_GSM_WCDMA =
+            RILConstants.NETWORK_MODE_TDSCDMA_GSM_WCDMA;
+
+    /**
+     * preferred network mode is TD-SCDMA, WCDMA and LTE.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_MODE_LTE_TDSCDMA_WCDMA =
+            RILConstants.NETWORK_MODE_LTE_TDSCDMA_WCDMA;
+
+    /**
+     * preferred network mode is TD-SCDMA, GSM/WCDMA and LTE.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA =
+            RILConstants.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA;
+
+    /**
+     * preferred network mode is TD-SCDMA,EvDo,CDMA,GSM/WCDMA.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA =
+            RILConstants.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA;
+    /**
+     * preferred network mode is TD-SCDMA/LTE/GSM/WCDMA, CDMA, and EvDo.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA =
+            RILConstants.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA;
+
     /**
      * Get the preferred network type.
      * Used for device configuration by some CDMA operators.
@@ -5655,11 +5908,12 @@
      * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
      * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
-     * @return the preferred network type, defined in RILConstants.java.
+     * @return the preferred network type.
      * @hide
      */
-    @UnsupportedAppUsage
-    public int getPreferredNetworkType(int subId) {
+    @RequiresPermission((android.Manifest.permission.MODIFY_PHONE_STATE))
+    @SystemApi
+    public @PrefNetworkMode int getPreferredNetworkType(int subId) {
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null)
@@ -6241,7 +6495,7 @@
     }
 
     /**
-     * @deprecated Use {@link android.telecom.TelecomManager#endCall()} instead.
+     * @removed Use {@link android.telecom.TelecomManager#endCall()} instead.
      * @hide
      * @removed
      */
@@ -6253,7 +6507,7 @@
     }
 
     /**
-     * @deprecated Use {@link android.telecom.TelecomManager#acceptRingingCall} instead
+     * @removed Use {@link android.telecom.TelecomManager#acceptRingingCall} instead
      * @hide
      * @removed
      */
@@ -6261,26 +6515,22 @@
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void answerRingingCall() {
-
+        // No-op
     }
 
     /**
-     * @deprecated Use {@link android.telecom.TelecomManager#silenceRinger} instead
+     * @removed Use {@link android.telecom.TelecomManager#silenceRinger} instead
      * @hide
      */
     @Deprecated
     @SystemApi
     @SuppressLint("Doclava125")
     public void silenceRinger() {
-        try {
-            getTelecomService().silenceRinger(getOpPackageName());
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error calling ITelecomService#silenceRinger", e);
-        }
+        // No-op
     }
 
     /**
-     * @deprecated Use {@link android.telecom.TelecomManager#isInCall} instead
+     * @removed Use {@link android.telecom.TelecomManager#isInCall} instead
      * @hide
      */
     @Deprecated
@@ -6290,18 +6540,11 @@
             android.Manifest.permission.READ_PHONE_STATE
     })
     public boolean isOffhook() {
-        try {
-            ITelephony telephony = getITelephony();
-            if (telephony != null)
-                return telephony.isOffhook(getOpPackageName());
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error calling ITelephony#isOffhook", e);
-        }
         return false;
     }
 
     /**
-     * @deprecated Use {@link android.telecom.TelecomManager#isRinging} instead
+     * @removed Use {@link android.telecom.TelecomManager#isRinging} instead
      * @hide
      */
     @Deprecated
@@ -6311,18 +6554,11 @@
             android.Manifest.permission.READ_PHONE_STATE
     })
     public boolean isRinging() {
-        try {
-            ITelephony telephony = getITelephony();
-            if (telephony != null)
-                return telephony.isRinging(getOpPackageName());
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error calling ITelephony#isRinging", e);
-        }
         return false;
     }
 
     /**
-     * @deprecated Use {@link android.telecom.TelecomManager#isInCall} instead
+     * @removed Use {@link android.telecom.TelecomManager#isInCall} instead
      * @hide
      */
     @Deprecated
@@ -6332,13 +6568,6 @@
             android.Manifest.permission.READ_PHONE_STATE
     })
     public boolean isIdle() {
-        try {
-            ITelephony telephony = getITelephony();
-            if (telephony != null)
-                return telephony.isIdle(getOpPackageName());
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error calling ITelephony#isIdle", e);
-        }
         return true;
     }
 
@@ -7824,26 +8053,23 @@
     }
 
     /**
-     * Return the application ID for the app type like {@link APPTYPE_CSIM}.
+     * 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:
+     *   {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE}
      *
-     * Requires that the calling app has READ_PRIVILEGED_PHONE_STATE permission
-     *
-     * @param appType the uicc app type like {@link APPTYPE_CSIM}
-     * @return Application ID for specificied app type or null if no uicc or error.
+     * @param appType the uicc app type.
+     * @return Application ID for specified app type or {@code null} if no uicc or error.
      * @hide
      */
-    public String getAidForAppType(int appType) {
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public String getAidForAppType(@UiccAppType int appType) {
         return getAidForAppType(getSubId(), appType);
     }
 
     /**
-     * Return the application ID for the app type like {@link APPTYPE_CSIM}.
-     *
-     * Requires that the calling app has READ_PRIVILEGED_PHONE_STATE permission
-     *
-     * @param subId the subscription ID that this request applies to.
-     * @param appType the uicc app type, like {@link APPTYPE_CSIM}
-     * @return Application ID for specificied app type or null if no uicc or error.
+     * same as {@link #getAidForAppType(int)}
      * @hide
      */
     public String getAidForAppType(int subId, int appType) {
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index df7bd3e..5d6a8c1 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -118,7 +118,9 @@
      */
     public static final String EXTRA_CONFERENCE = "conference";
     /**
-     * @hide
+     * Boolean extra property set on an {@link ImsCallProfile} to indicate that this call is an
+     * emergency call.  The {@link ImsService} sets this on a call to indicate that the network has
+     * identified the call as an emergency call.
      */
     public static final String EXTRA_E_CALL = "e_call";
     /**
diff --git a/telephony/java/android/telephony/mbms/GroupCall.java b/telephony/java/android/telephony/mbms/GroupCall.java
new file mode 100644
index 0000000..9aca18e
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/GroupCall.java
@@ -0,0 +1,176 @@
+/*
+ * 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.mbms;
+
+import android.annotation.IntDef;
+import android.os.RemoteException;
+import android.telephony.MbmsGroupCallSession;
+import android.telephony.mbms.vendor.IMbmsGroupCallService;
+import android.util.Log;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Class used to represent a single MBMS group call. After a call has been started with
+ * {@link MbmsGroupCallSession#startGroupCall},
+ * this class is used to hold information about the call and control it.
+ */
+public class GroupCall implements AutoCloseable {
+    private static final String LOG_TAG = "MbmsGroupCall";
+
+    /**
+     * The state of a group call, reported via
+     * {@link GroupCallCallback#onGroupCallStateChanged(int, int)}
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "STATE_" }, value = {STATE_STOPPED, STATE_STARTED, STATE_STALLED})
+    public @interface GroupCallState {}
+    public static final int STATE_STOPPED = 1;
+    public static final int STATE_STARTED = 2;
+    public static final int STATE_STALLED = 3;
+
+    /**
+     * The reason for a call state change, reported via
+     * {@link GroupCallCallback#onGroupCallStateChanged(int, int)}
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "REASON_" },
+            value = {REASON_BY_USER_REQUEST, REASON_FREQUENCY_CONFLICT,
+                    REASON_OUT_OF_MEMORY, REASON_NOT_CONNECTED_TO_HOMECARRIER_LTE,
+                    REASON_LEFT_MBMS_BROADCAST_AREA, REASON_NONE})
+    public @interface GroupCallStateChangeReason {}
+
+    /**
+     * Indicates that the middleware does not have a reason to provide for the state change.
+     */
+    public static final int REASON_NONE = 0;
+
+    /**
+     * State changed due to a call to {@link #close()} or
+     * {@link MbmsGroupCallSession#startGroupCall}
+     */
+    public static final int REASON_BY_USER_REQUEST = 1;
+
+    // 2 is unused to match up with streaming.
+
+    /**
+     * State changed due to a frequency conflict with another requested call.
+     */
+    public static final int REASON_FREQUENCY_CONFLICT = 3;
+
+    /**
+     * State changed due to the middleware running out of memory
+     */
+    public static final int REASON_OUT_OF_MEMORY = 4;
+
+    /**
+     * State changed due to the device leaving the home carrier's LTE network.
+     */
+    public static final int REASON_NOT_CONNECTED_TO_HOMECARRIER_LTE = 5;
+
+    /**
+     * State changed due to the device leaving the area where this call is being broadcast.
+     */
+    public static final int REASON_LEFT_MBMS_BROADCAST_AREA = 6;
+
+    private final int mSubscriptionId;
+    private final long mTmgi;
+    private final MbmsGroupCallSession mParentSession;
+    private final InternalGroupCallCallback mCallback;
+    private IMbmsGroupCallService mService;
+
+    /**
+     * @hide
+     */
+    public GroupCall(int subscriptionId,
+            IMbmsGroupCallService service,
+            MbmsGroupCallSession session,
+            long tmgi,
+            InternalGroupCallCallback callback) {
+        mSubscriptionId = subscriptionId;
+        mParentSession = session;
+        mService = service;
+        mTmgi = tmgi;
+        mCallback = callback;
+    }
+
+    /**
+     * Retrieve the TMGI (Temporary Mobile Group Identity) corresponding to this call.
+     */
+    public long getTmgi() {
+        return mTmgi;
+    }
+
+    /**
+     * Send an update to the middleware when the SAI (Service Area Identifier) list and frequency
+     * information of the group call has * changed. Callers must obtain this information from the
+     * wireless carrier independently.
+     * @param saiArray New array of SAIs that the call is available on.
+     * @param frequencyArray New array of frequencies that the call is available on.
+     */
+    public void updateGroupCall(int[] saiArray, int[] frequencyArray) {
+        if (mService == null) {
+            throw new IllegalStateException("No group call service attached");
+        }
+
+        try {
+            mService.updateGroupCall(mSubscriptionId, mTmgi, saiArray, frequencyArray);
+        } catch (RemoteException e) {
+            Log.w(LOG_TAG, "Remote process died");
+            mService = null;
+            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
+        } finally {
+            mParentSession.onGroupCallStopped(this);
+        }
+    }
+
+    /**
+     * Stop this group call. Further operations on this object will fail with an
+     * {@link IllegalStateException}.
+     *
+     * May throw an {@link IllegalStateException}
+     */
+    @Override
+    public void close() {
+        if (mService == null) {
+            throw new IllegalStateException("No group call service attached");
+        }
+
+        try {
+            mService.stopGroupCall(mSubscriptionId, mTmgi);
+        } catch (RemoteException e) {
+            Log.w(LOG_TAG, "Remote process died");
+            mService = null;
+            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
+        } finally {
+            mParentSession.onGroupCallStopped(this);
+        }
+    }
+
+    /** @hide */
+    public InternalGroupCallCallback getCallback() {
+        return mCallback;
+    }
+
+    private void sendErrorToApp(int errorCode, String message) {
+        mCallback.onError(errorCode, message);
+    }
+}
+
diff --git a/telephony/java/android/telephony/mbms/GroupCallCallback.java b/telephony/java/android/telephony/mbms/GroupCallCallback.java
new file mode 100644
index 0000000..001bb02
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/GroupCallCallback.java
@@ -0,0 +1,87 @@
+/*
+ * 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.mbms;
+
+import android.annotation.IntDef;
+import android.annotation.Nullable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * A callback class for use when the application is in a group call. The middleware
+ * will provide updates on the status of the call via this callback.
+ */
+public class GroupCallCallback {
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(value = {
+            MbmsErrors.ERROR_NO_UNIQUE_MIDDLEWARE,
+            MbmsErrors.ERROR_MIDDLEWARE_LOST,
+            MbmsErrors.ERROR_MIDDLEWARE_NOT_BOUND,
+            MbmsErrors.GeneralErrors.ERROR_MIDDLEWARE_NOT_YET_READY,
+            MbmsErrors.GeneralErrors.ERROR_OUT_OF_MEMORY,
+            MbmsErrors.GeneralErrors.ERROR_MIDDLEWARE_TEMPORARILY_UNAVAILABLE,
+            MbmsErrors.GeneralErrors.ERROR_IN_E911,
+            MbmsErrors.GeneralErrors.ERROR_NOT_CONNECTED_TO_HOME_CARRIER_LTE,
+            MbmsErrors.GeneralErrors.ERROR_UNABLE_TO_READ_SIM,
+            MbmsErrors.GeneralErrors.ERROR_CARRIER_CHANGE_NOT_ALLOWED}, prefix = { "ERROR_" })
+    private @interface GroupCallError{}
+
+    /**
+     * Indicates broadcast signal strength is not available for this call.
+     *
+     * This may be due to the call no longer being available due to geography
+     * or timing (end of service)
+     */
+    public static final int SIGNAL_STRENGTH_UNAVAILABLE = -1;
+
+    /**
+     * Called by the middleware when it has detected an error condition in this group call. The
+     * possible error codes are listed in {@link MbmsErrors}.
+     * @param errorCode The error code.
+     * @param message A human-readable message generated by the middleware for debugging purposes.
+     */
+    public void onError(@GroupCallError int errorCode, @Nullable String message) {
+        // default implementation empty
+    }
+
+    /**
+     * Called to indicate this call has changed state.
+     *
+     * See {@link GroupCall#STATE_STOPPED}, {@link GroupCall#STATE_STARTED}
+     * and {@link GroupCall#STATE_STALLED}.
+     */
+    public void onGroupCallStateChanged(@GroupCall.GroupCallState int state,
+            @GroupCall.GroupCallStateChangeReason int reason) {
+        // default implementation empty
+    }
+
+    /**
+     * Broadcast Signal Strength updated.
+     *
+     * This signal strength is the BROADCAST signal strength which,
+     * depending on technology in play and it's deployment, may be
+     * stronger or weaker than the traditional UNICAST signal
+     * strength.  It a simple int from 0-4 for valid levels or
+     * {@link #SIGNAL_STRENGTH_UNAVAILABLE} if broadcast is not available
+     * for this call due to timing, geography or popularity.
+     */
+    public void onBroadcastSignalStrengthUpdated(int signalStrength) {
+        // default implementation empty
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/events/StartedDragingEvent.java b/telephony/java/android/telephony/mbms/IGroupCallCallback.aidl
old mode 100644
new mode 100755
similarity index 61%
rename from packages/SystemUI/src/com/android/systemui/stackdivider/events/StartedDragingEvent.java
rename to telephony/java/android/telephony/mbms/IGroupCallCallback.aidl
index 5d19851..844b634
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/events/StartedDragingEvent.java
+++ b/telephony/java/android/telephony/mbms/IGroupCallCallback.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 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.
@@ -11,15 +11,16 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
  */
 
-package com.android.systemui.stackdivider.events;
-
-import com.android.systemui.recents.events.EventBus;
+package android.telephony.mbms;
 
 /**
- * Sent when the divider is being draged either manually or by an animation.
+ * @hide
  */
-public class StartedDragingEvent extends EventBus.Event {
+oneway interface IGroupCallCallback {
+    void onError(int errorCode, String message);
+    void onGroupCallStateChanged(int state, int reason);
+    void onBroadcastSignalStrengthUpdated(int signalStrength);
 }
diff --git a/telephony/java/android/telephony/mbms/IMbmsGroupCallSessionCallback.aidl b/telephony/java/android/telephony/mbms/IMbmsGroupCallSessionCallback.aidl
new file mode 100755
index 0000000..1a1c7f8
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/IMbmsGroupCallSessionCallback.aidl
@@ -0,0 +1,33 @@
+/*
+** 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.mbms;
+
+import java.util.List;
+
+/**
+ * @hide
+ */
+oneway interface IMbmsGroupCallSessionCallback
+{
+    void onError(int errorCode, String message);
+
+    void onAvailableSaisUpdated(in List currentSai, in List availableSais);
+
+    void onServiceInterfaceAvailable(String interfaceName, int index);
+
+    void onMiddlewareReady();
+}
diff --git a/telephony/java/android/telephony/mbms/InternalGroupCallCallback.java b/telephony/java/android/telephony/mbms/InternalGroupCallCallback.java
new file mode 100644
index 0000000..2910bb3
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/InternalGroupCallCallback.java
@@ -0,0 +1,96 @@
+/*
+ * 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.mbms;
+
+import android.os.Binder;
+
+import java.util.concurrent.Executor;
+
+/** @hide */
+public class InternalGroupCallCallback extends IGroupCallCallback.Stub {
+    private final GroupCallCallback mAppCallback;
+    private final Executor mExecutor;
+    private volatile boolean mIsStopped = false;
+
+    public InternalGroupCallCallback(GroupCallCallback appCallback,
+            Executor executor) {
+        mAppCallback = appCallback;
+        mExecutor = executor;
+    }
+
+    @Override
+    public void onError(final int errorCode, final String message) {
+        if (mIsStopped) {
+            return;
+        }
+
+        mExecutor.execute(new Runnable() {
+            @Override
+            public void run() {
+                long token = Binder.clearCallingIdentity();
+                try {
+                    mAppCallback.onError(errorCode, message);
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                }
+            }
+        });
+    }
+
+    @Override
+    public void onGroupCallStateChanged(final int state, final int reason) {
+        if (mIsStopped) {
+            return;
+        }
+
+        mExecutor.execute(new Runnable() {
+            @Override
+            public void run() {
+                long token = Binder.clearCallingIdentity();
+                try {
+                    mAppCallback.onGroupCallStateChanged(state, reason);
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                }
+            }
+        });
+    }
+
+    @Override
+    public void onBroadcastSignalStrengthUpdated(final int signalStrength) {
+        if (mIsStopped) {
+            return;
+        }
+
+        mExecutor.execute(new Runnable() {
+            @Override
+            public void run() {
+                long token = Binder.clearCallingIdentity();
+                try {
+                    mAppCallback.onBroadcastSignalStrengthUpdated(signalStrength);
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                }
+            }
+        });
+    }
+
+    /** Prevents this callback from calling the app */
+    public void stop() {
+        mIsStopped = true;
+    }
+}
diff --git a/telephony/java/android/telephony/mbms/InternalGroupCallSessionCallback.java b/telephony/java/android/telephony/mbms/InternalGroupCallSessionCallback.java
new file mode 100644
index 0000000..4c9cf4d
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/InternalGroupCallSessionCallback.java
@@ -0,0 +1,116 @@
+/*
+ * 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.mbms;
+
+import android.os.Binder;
+
+import java.util.List;
+import java.util.concurrent.Executor;
+
+/** @hide */
+public class InternalGroupCallSessionCallback extends IMbmsGroupCallSessionCallback.Stub {
+    private final Executor mExecutor;
+    private final MbmsGroupCallSessionCallback mAppCallback;
+    private volatile boolean mIsStopped = false;
+
+    public InternalGroupCallSessionCallback(MbmsGroupCallSessionCallback appCallback,
+            Executor executor) {
+        mAppCallback = appCallback;
+        mExecutor = executor;
+    }
+
+    @Override
+    public void onError(final int errorCode, final String message) {
+        if (mIsStopped) {
+            return;
+        }
+
+        mExecutor.execute(new Runnable() {
+            @Override
+            public void run() {
+                long token = Binder.clearCallingIdentity();
+                try {
+                    mAppCallback.onError(errorCode, message);
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                }
+            }
+        });
+    }
+
+    @Override
+    public void onAvailableSaisUpdated(final List currentSais, final List availableSais) {
+        if (mIsStopped) {
+            return;
+        }
+
+        mExecutor.execute(new Runnable() {
+            @Override
+            public void run() {
+                long token = Binder.clearCallingIdentity();
+                try {
+                    mAppCallback.onAvailableSaisUpdated(currentSais, availableSais);
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                }
+            }
+        });
+    }
+
+    @Override
+    public void onServiceInterfaceAvailable(final String interfaceName, final int index) {
+        if (mIsStopped) {
+            return;
+        }
+
+        mExecutor.execute(new Runnable() {
+            @Override
+            public void run() {
+                long token = Binder.clearCallingIdentity();
+                try {
+                    mAppCallback.onServiceInterfaceAvailable(interfaceName, index);
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                }
+            }
+        });
+    }
+
+    @Override
+    public void onMiddlewareReady() {
+        if (mIsStopped) {
+            return;
+        }
+
+        mExecutor.execute(new Runnable() {
+            @Override
+            public void run() {
+                long token = Binder.clearCallingIdentity();
+                try {
+                    mAppCallback.onMiddlewareReady();
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                }
+            }
+        });
+    }
+
+    /** Prevents this callback from calling the app */
+    public void stop() {
+        mIsStopped = true;
+    }
+}
diff --git a/telephony/java/android/telephony/mbms/MbmsGroupCallSessionCallback.java b/telephony/java/android/telephony/mbms/MbmsGroupCallSessionCallback.java
new file mode 100644
index 0000000..7da734e
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/MbmsGroupCallSessionCallback.java
@@ -0,0 +1,99 @@
+/*
+ * 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.mbms;
+
+import android.annotation.IntDef;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.telephony.MbmsGroupCallSession;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+import java.util.concurrent.Executor;
+
+/**
+ * A callback class that is used to receive information from the middleware on MBMS group-call
+ * services. An instance of this object should be passed into
+ * {@link MbmsGroupCallSession#create(Context, Executor, int, MbmsGroupCallSessionCallback)}.
+ */
+public class MbmsGroupCallSessionCallback {
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(value = {
+            MbmsErrors.ERROR_NO_UNIQUE_MIDDLEWARE,
+            MbmsErrors.ERROR_MIDDLEWARE_LOST,
+            MbmsErrors.ERROR_MIDDLEWARE_NOT_BOUND,
+            MbmsErrors.InitializationErrors.ERROR_APP_PERMISSIONS_NOT_GRANTED,
+            MbmsErrors.InitializationErrors.ERROR_DUPLICATE_INITIALIZE,
+            MbmsErrors.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE,
+            MbmsErrors.GeneralErrors.ERROR_MIDDLEWARE_NOT_YET_READY,
+            MbmsErrors.GeneralErrors.ERROR_OUT_OF_MEMORY,
+            MbmsErrors.GeneralErrors.ERROR_MIDDLEWARE_TEMPORARILY_UNAVAILABLE,
+            MbmsErrors.GeneralErrors.ERROR_IN_E911,
+            MbmsErrors.GeneralErrors.ERROR_NOT_CONNECTED_TO_HOME_CARRIER_LTE,
+            MbmsErrors.GeneralErrors.ERROR_UNABLE_TO_READ_SIM,
+            MbmsErrors.GeneralErrors.ERROR_CARRIER_CHANGE_NOT_ALLOWED}, prefix = { "ERROR_" })
+    private @interface GroupCallError{}
+
+    /**
+     * Called by the middleware when it has detected an error condition. The possible error codes
+     * are listed in {@link MbmsErrors}.
+     * @param errorCode The error code.
+     * @param message A human-readable message generated by the middleware for debugging purposes.
+     */
+    public void onError(@GroupCallError int errorCode, @Nullable String message) {
+    }
+
+    /**
+     * Indicates that the list of currently available SAIs has been updated. The app may use this
+     * information to filter the list of group calls when displaying available group calls to
+     * the user by matching the SAIs with a list of group calls separately negotiated with the
+     * carrier. The app may also report the aggregate list of SAIs to the group call application
+     * server so that a network entity can determine when, and where to activate the broadcast of
+     * particular group calls.
+     * @param currentSais The available SAIs on the current cell.
+     * @param availableSais A list of lists of available SAIS in neighboring cells, where each list
+     *                      contains the available SAIs in an individual cell.
+     */
+    public void onAvailableSaisUpdated(List<Integer> currentSais,
+            List<List<Integer>> availableSais) {
+    }
+
+    /**
+     * Called soon after the app calls {@link MbmsGroupCallSession#create}. The information supplied
+     * via this callback may be used to establish a data-link interface with the modem before the
+     * middleware is ready.
+     * Note that this method may be called before {@link #onMiddlewareReady()}.
+     *
+     * @param interfaceName The interface name for the data link.
+     * @param index The index for the data link.
+     */
+    public void onServiceInterfaceAvailable(String interfaceName, int index) {
+    }
+
+    /**
+     * Called to indicate that the middleware has been initialized and is ready.
+     *
+     * Before this method is called, calling any method on an instance of
+     * {@link MbmsGroupCallSession} will result in an {@link IllegalStateException} or an error
+     * delivered via {@link #onError(int, String)} with error code
+     * {@link MbmsErrors.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY}.
+     */
+    public void onMiddlewareReady() {
+    }
+}
diff --git a/telephony/java/android/telephony/mbms/MbmsUtils.java b/telephony/java/android/telephony/mbms/MbmsUtils.java
index 06b2120..95b4d37 100644
--- a/telephony/java/android/telephony/mbms/MbmsUtils.java
+++ b/telephony/java/android/telephony/mbms/MbmsUtils.java
@@ -23,6 +23,7 @@
 import android.content.pm.*;
 import android.content.pm.ServiceInfo;
 import android.telephony.MbmsDownloadSession;
+import android.telephony.MbmsGroupCallSession;
 import android.telephony.MbmsStreamingSession;
 import android.util.Log;
 
@@ -59,6 +60,9 @@
             case MbmsStreamingSession.MBMS_STREAMING_SERVICE_ACTION:
                 metaDataKey = MbmsStreamingSession.MBMS_STREAMING_SERVICE_OVERRIDE_METADATA;
                 break;
+            case MbmsGroupCallSession.MBMS_GROUP_CALL_SERVICE_ACTION:
+                metaDataKey = MbmsGroupCallSession.MBMS_GROUP_CALL_SERVICE_OVERRIDE_METADATA;
+                break;
         }
         if (metaDataKey == null) {
             return null;
diff --git a/telephony/java/android/telephony/mbms/vendor/IMbmsGroupCallService.aidl b/telephony/java/android/telephony/mbms/vendor/IMbmsGroupCallService.aidl
new file mode 100755
index 0000000..721256a
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/vendor/IMbmsGroupCallService.aidl
@@ -0,0 +1,39 @@
+/*
+** 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.telephony.mbms.vendor;
+
+import android.net.Uri;
+import android.telephony.mbms.IMbmsGroupCallSessionCallback;
+import android.telephony.mbms.IGroupCallCallback;
+
+/**
+ * @hide
+ */
+interface IMbmsGroupCallService
+{
+    int initialize(IMbmsGroupCallSessionCallback callback, int subId);
+
+    void stopGroupCall(int subId, long tmgi);
+
+    void updateGroupCall(int subscriptionId, long tmgi, in int[] saiArray,
+        in int[] frequencyArray);
+
+    int startGroupCall(int subscriptionId, long tmgi, in int[] saiArray,
+        in int[] frequencyArray, IGroupCallCallback callback);
+
+    void dispose(int subId);
+}
diff --git a/telephony/java/android/telephony/mbms/vendor/MbmsGroupCallServiceBase.java b/telephony/java/android/telephony/mbms/vendor/MbmsGroupCallServiceBase.java
new file mode 100644
index 0000000..3734ca7
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/vendor/MbmsGroupCallServiceBase.java
@@ -0,0 +1,275 @@
+/*
+ * 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.mbms.vendor;
+
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.telephony.mbms.GroupCallCallback;
+import android.telephony.mbms.IGroupCallCallback;
+import android.telephony.mbms.IMbmsGroupCallSessionCallback;
+import android.telephony.mbms.MbmsErrors;
+import android.telephony.mbms.MbmsGroupCallSessionCallback;
+import android.telephony.mbms.vendor.IMbmsGroupCallService.Stub;
+
+import java.util.List;
+
+/**
+ * Base class for MBMS group-call services. The middleware should override this class to implement
+ * its {@link Service} for group calls
+ * Subclasses should call this class's {@link #onBind} method to obtain an {@link IBinder} if they
+ * override {@link #onBind}.
+ * @hide
+ */
+@SystemApi
+@TestApi
+public class MbmsGroupCallServiceBase extends Service {
+    private final IBinder mInterface = new Stub() {
+        @Override
+        public int initialize(final IMbmsGroupCallSessionCallback callback,
+                final int subscriptionId) throws RemoteException {
+            if (callback == null) {
+                throw new NullPointerException("Callback must not be null");
+            }
+
+            final int uid = Binder.getCallingUid();
+
+            int result = MbmsGroupCallServiceBase.this.initialize(
+                    new MbmsGroupCallSessionCallback() {
+                        @Override
+                        public void onError(final int errorCode, final String message) {
+                            try {
+                                if (errorCode == MbmsErrors.UNKNOWN) {
+                                    throw new IllegalArgumentException(
+                                            "Middleware cannot send an unknown error.");
+                                }
+                                callback.onError(errorCode, message);
+                            } catch (RemoteException e) {
+                                onAppCallbackDied(uid, subscriptionId);
+                            }
+                        }
+
+                        @Override
+                        public void onAvailableSaisUpdated(final List currentSais,
+                                final List availableSais) {
+                            try {
+                                callback.onAvailableSaisUpdated(currentSais, availableSais);
+                            } catch (RemoteException e) {
+                                onAppCallbackDied(uid, subscriptionId);
+                            }
+                        }
+
+                        @Override
+                        public void onServiceInterfaceAvailable(final String interfaceName,
+                                final int index) {
+                            try {
+                                callback.onServiceInterfaceAvailable(interfaceName, index);
+                            } catch (RemoteException e) {
+                                onAppCallbackDied(uid, subscriptionId);
+                            }
+                        }
+
+                        @Override
+                        public void onMiddlewareReady() {
+                            try {
+                                callback.onMiddlewareReady();
+                            } catch (RemoteException e) {
+                                onAppCallbackDied(uid, subscriptionId);
+                            }
+                        }
+                    }, subscriptionId);
+
+            if (result == MbmsErrors.SUCCESS) {
+                callback.asBinder().linkToDeath(new DeathRecipient() {
+                    @Override
+                    public void binderDied() {
+                        onAppCallbackDied(uid, subscriptionId);
+                    }
+                }, 0);
+            }
+
+            return result;
+        }
+
+        @Override
+        public void stopGroupCall(int subId, long tmgi) {
+            MbmsGroupCallServiceBase.this.stopGroupCall(subId, tmgi);
+        }
+
+        @Override
+        public void updateGroupCall(int subscriptionId, long tmgi, int[] saiArray,
+                int[] frequencyArray) {
+            MbmsGroupCallServiceBase.this.updateGroupCall(
+                    subscriptionId, tmgi, saiArray, frequencyArray);
+        }
+
+        @Override
+        public int startGroupCall(final int subscriptionId, final long tmgi, final int[] saiArray,
+                final int[] frequencyArray, final IGroupCallCallback callback)
+                throws RemoteException {
+            if (callback == null) {
+                throw new NullPointerException("Callback must not be null");
+            }
+
+            final int uid = Binder.getCallingUid();
+
+            int result = MbmsGroupCallServiceBase.this.startGroupCall(
+                    subscriptionId, tmgi, saiArray, frequencyArray, new GroupCallCallback() {
+                        @Override
+                        public void onError(final int errorCode, final String message) {
+                            try {
+                                if (errorCode == MbmsErrors.UNKNOWN) {
+                                    throw new IllegalArgumentException(
+                                            "Middleware cannot send an unknown error.");
+                                }
+                                callback.onError(errorCode, message);
+                            } catch (RemoteException e) {
+                                onAppCallbackDied(uid, subscriptionId);
+                            }
+                        }
+
+                        public void onGroupCallStateChanged(int state, int reason) {
+                            try {
+                                callback.onGroupCallStateChanged(state, reason);
+                            } catch (RemoteException e) {
+                                onAppCallbackDied(uid, subscriptionId);
+                            }
+                        }
+
+                        public void onBroadcastSignalStrengthUpdated(int signalStrength) {
+                            try {
+                                callback.onBroadcastSignalStrengthUpdated(signalStrength);
+                            } catch (RemoteException e) {
+                                onAppCallbackDied(uid, subscriptionId);
+                            }
+                        }
+                    });
+
+            if (result == MbmsErrors.SUCCESS) {
+                callback.asBinder().linkToDeath(new DeathRecipient() {
+                    @Override
+                    public void binderDied() {
+                        onAppCallbackDied(uid, subscriptionId);
+                    }
+                }, 0);
+            }
+
+            return result;
+        }
+
+        @Override
+        public void dispose(int subId) throws RemoteException {
+            MbmsGroupCallServiceBase.this.dispose(subId);
+        }
+    };
+
+    /**
+     * Initialize the group call service for this app and subscription ID, registering the callback.
+     *
+     * May throw an {@link IllegalArgumentException} or a {@link SecurityException}, which
+     * will be intercepted and passed to the app as
+     * {@link MbmsErrors.InitializationErrors#ERROR_UNABLE_TO_INITIALIZE}
+     *
+     * May return any value from {@link MbmsErrors.InitializationErrors}
+     * or {@link MbmsErrors#SUCCESS}. Non-successful error codes will be passed to the app via
+     * {@link IMbmsGroupCallSessionCallback#onError(int, String)}.
+     *
+     * @param callback The callback to use to communicate with the app.
+     * @param subscriptionId The subscription ID to use.
+     */
+    public int initialize(MbmsGroupCallSessionCallback callback, int subscriptionId)
+            throws RemoteException {
+        throw new UnsupportedOperationException("Not implemented");
+    }
+
+    /**
+     * Starts a particular group call. This method may perform asynchronous work. When
+     * the call is ready for consumption, the middleware should inform the app via
+     * {@link IGroupCallCallback#onGroupCallStateChanged(int, int)}.
+     *
+     * May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
+     *
+     * @param subscriptionId The subscription id to use.
+     * @param tmgi The TMGI, an identifier for the group call.
+     * @param saiArray An array of SAIs for the group call.
+     * @param frequencyArray An array of frequencies for the group call.
+     * @param callback The callback object on which the app wishes to receive updates.
+     * @return Any error in {@link MbmsErrors.GeneralErrors}
+     */
+    public int startGroupCall(int subscriptionId, long tmgi, int[] saiArray, int[] frequencyArray,
+            GroupCallCallback callback) {
+        throw new UnsupportedOperationException("Not implemented");
+    }
+
+    /**
+     * Stop the group call identified by {@code tmgi}.
+     *
+     * The callback provided via {@link #startGroupCall} should no longer be
+     * used after this method has called by the app.
+     *
+     * May throw an {@link IllegalStateException}
+     *
+     * @param subscriptionId The subscription id to use.
+     * @param tmgi The TMGI for the call to stop.
+     */
+    public void stopGroupCall(int subscriptionId, long tmgi) {
+        throw new UnsupportedOperationException("Not implemented");
+    }
+
+    /**
+     * Called when the app receives new SAI and frequency information for the group call identified
+     * by {@code tmgi}.
+     * @param saiArray New array of SAIs that the call is available on.
+     * @param frequencyArray New array of frequencies that the call is available on.
+     */
+    public void updateGroupCall(int subscriptionId, long tmgi, int[] saiArray,
+            int[] frequencyArray) {
+        throw new UnsupportedOperationException("Not implemented");
+    }
+
+    /**
+     * Signals that the app wishes to dispose of the session identified by the
+     * {@code subscriptionId} argument and the caller's uid. No notification back to the
+     * app is required for this operation, and the corresponding callback provided via
+     * {@link #initialize} should no longer be used
+     * after this method has been called by the app.
+     *
+     * May throw an {@link IllegalStateException}
+     *
+     * @param subscriptionId The subscription id to use.
+     */
+    public void dispose(int subscriptionId) throws RemoteException {
+        throw new UnsupportedOperationException("Not implemented");
+    }
+
+    /**
+     * Indicates that the app identified by the given UID and subscription ID has died.
+     * @param uid the UID of the app, as returned by {@link Binder#getCallingUid()}.
+     * @param subscriptionId The subscription ID the app is using.
+     */
+    public void onAppCallbackDied(int uid, int subscriptionId) {
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return mInterface;
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
index 1ebb697..38a1bc7 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -52,5 +52,6 @@
     void onCarrierNetworkChange(in boolean active);
     void onUserMobileDataStateChanged(in boolean enabled);
     void onPhoneCapabilityChanged(in PhoneCapability capability);
+    void onPreferredDataSubIdChanged(in int subId);
 }
 
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 6521f0b..0ccd748 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -232,5 +232,5 @@
      */
     int getSimStateForSlotIndex(int slotIndex);
 
-    boolean isActiveSubId(int subId);
+    boolean isActiveSubId(int subId, String callingPackage);
 }
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index e1c770c..ca2bcff 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -75,116 +75,6 @@
     void call(String callingPackage, String number);
 
     /**
-     * End call if there is a call in progress, otherwise does nothing.
-     *
-     * @return whether it hung up
-     */
-    boolean endCall();
-
-    /**
-     * End call on particular subId or go to the Home screen
-     * @param subId user preferred subId.
-     * @return whether it hung up
-     */
-    boolean endCallForSubscriber(int subId);
-
-    /**
-     * Answer the currently-ringing call.
-     *
-     * If there's already a current active call, that call will be
-     * automatically put on hold.  If both lines are currently in use, the
-     * current active call will be ended.
-     *
-     * TODO: provide a flag to let the caller specify what policy to use
-     * if both lines are in use.  (The current behavior is hardwired to
-     * "answer incoming, end ongoing", which is how the CALL button
-     * is specced to behave.)
-     *
-     * TODO: this should be a oneway call (especially since it's called
-     * directly from the key queue thread).
-     */
-    void answerRingingCall();
-
-    /**
-     * Answer the currently-ringing call on particular subId .
-     *
-     * If there's already a current active call, that call will be
-     * automatically put on hold.  If both lines are currently in use, the
-     * current active call will be ended.
-     *
-     * TODO: provide a flag to let the caller specify what policy to use
-     * if both lines are in use.  (The current behavior is hardwired to
-     * "answer incoming, end ongoing", which is how the CALL button
-     * is specced to behave.)
-     *
-     * TODO: this should be a oneway call (especially since it's called
-     * directly from the key queue thread).
-     */
-    void answerRingingCallForSubscriber(int subId);
-
-    /**
-     * Silence the ringer if an incoming call is currently ringing.
-     * (If vibrating, stop the vibrator also.)
-     *
-     * It's safe to call this if the ringer has already been silenced, or
-     * even if there's no incoming call.  (If so, this method will do nothing.)
-     *
-     * TODO: this should be a oneway call too (see above).
-     *       (Actually *all* the methods here that return void can
-     *       probably be oneway.)
-     */
-    void silenceRinger();
-
-    /**
-     * Check if we are in either an active or holding call
-     * @param callingPackage the name of the package making the call.
-     * @return true if the phone state is OFFHOOK.
-     */
-    boolean isOffhook(String callingPackage);
-
-    /**
-     * Check if a particular subId has an active or holding call
-     *
-     * @param subId user preferred subId.
-     * @param callingPackage the name of the package making the call.
-     * @return true if the phone state is OFFHOOK.
-     */
-    boolean isOffhookForSubscriber(int subId, String callingPackage);
-
-    /**
-     * Check if an incoming phone call is ringing or call waiting
-     * on a particular subId.
-     *
-     * @param subId user preferred subId.
-     * @param callingPackage the name of the package making the call.
-     * @return true if the phone state is RINGING.
-     */
-    boolean isRingingForSubscriber(int subId, String callingPackage);
-
-    /**
-     * Check if an incoming phone call is ringing or call waiting.
-     * @param callingPackage the name of the package making the call.
-     * @return true if the phone state is RINGING.
-     */
-    boolean isRinging(String callingPackage);
-
-    /**
-     * Check if the phone is idle.
-     * @param callingPackage the name of the package making the call.
-     * @return true if the phone state is IDLE.
-     */
-    boolean isIdle(String callingPackage);
-
-    /**
-     * Check if the phone is idle on a particular subId.
-     *
-     * @param subId user preferred subId.
-     * @param callingPackage the name of the package making the call.
-     * @return true if the phone state is IDLE.
-     */
-    boolean isIdleForSubscriber(int subId, String callingPackage);
-
-    /**
      * Check to see if the radio is on or not.
      * @param callingPackage the name of the package making the call.
      * @return returns true if the radio is on.
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 43d56b3..c03065c 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -79,4 +79,5 @@
     void notifyCarrierNetworkChange(in boolean active);
     void notifyUserMobileDataStateChangedForPhoneId(in int phoneId, in int subId, in boolean state);
     void notifyPhoneCapabilityChanged(in PhoneCapability capability);
+    void notifyPreferredDataSubIdChanged(int preferredSubId);
 }
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index f9de776..21f3b92 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -176,6 +176,10 @@
 
     // FIXME: This is used to pass a subId via intents, we need to look at its usage, which is
     // FIXME: extensive, and see if this should be an array of all active subId's or ...?
+    /**
+     * @Deprecated use {@link android.telephony.SubscriptionManager#EXTRA_SUBSCRIPTION_INDEX}
+     * instead.
+     */
     public static final String SUBSCRIPTION_KEY  = "subscription";
 
     public static final String SUB_SETTING  = "subSettings";
diff --git a/test-base/Android.bp b/test-base/Android.bp
index 0b8a02a..4d765d3 100644
--- a/test-base/Android.bp
+++ b/test-base/Android.bp
@@ -37,7 +37,8 @@
         "junit.framework",
     ],
 
-    droiddoc_options: ["stubsourceonly"],
+    droiddoc_options: ["-stubsourceonly"],
+    metalava_enabled: false,
     compile_dex: true,
 }
 
diff --git a/test-mock/Android.bp b/test-mock/Android.bp
index 5eba017..37158e5 100644
--- a/test-mock/Android.bp
+++ b/test-mock/Android.bp
@@ -26,5 +26,6 @@
     ],
 
     srcs_lib_whitelist_pkgs: ["android"],
+    metalava_enabled: false,
     compile_dex: true,
 }
diff --git a/test-runner/Android.bp b/test-runner/Android.bp
index ea615b9..0a0d50c 100644
--- a/test-runner/Android.bp
+++ b/test-runner/Android.bp
@@ -40,7 +40,8 @@
         "junit.textui",
     ],
 
-    droiddoc_options: ["stubsourceonly"],
+    droiddoc_options: ["-stubsourceonly"],
+    metalava_enabled: false,
     compile_dex: true
 }
 
diff --git a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
index 4a6fe49..1f60b71 100644
--- a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
+++ b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
@@ -247,8 +247,14 @@
                     mIterationCycle = false;
                     // In the "applaunch.txt" file, trail launches is referenced using
                     // "TRIAL_LAUNCH"
-                    String appPkgName = mNameToIntent.get(launch.getApp())
-                        .getComponent().getPackageName();
+                    Intent startIntent = mNameToIntent.get(launch.getApp());
+                    if (startIntent == null) {
+                        Log.w(TAG, "App does not exist: " + launch.getApp());
+                        mResult.putString(mNameToResultKey.get(launch.getApp()),
+                            "App does not exist");
+                        continue;
+                    }
+                    String appPkgName = startIntent.getComponent().getPackageName();
                     if (SPEED_PROFILE_FILTER.equals(launch.getCompilerFilter())) {
                         assertTrue(String.format("Not able to compile the app : %s", appPkgName),
                               compileApp(VERIFY_FILTER, appPkgName));
diff --git a/tests/DexLoggerIntegrationTests/AndroidManifest.xml b/tests/DexLoggerIntegrationTests/AndroidManifest.xml
index a847e8f..a9f01ed 100644
--- a/tests/DexLoggerIntegrationTests/AndroidManifest.xml
+++ b/tests/DexLoggerIntegrationTests/AndroidManifest.xml
@@ -17,10 +17,10 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.android.frameworks.dexloggertest">
 
-    <!-- Tests feature introduced in P (27) -->
+    <!-- Tests feature introduced in P (28) -->
     <uses-sdk
-        android:minSdkVersion="27"
-        android:targetSdkVersion="27" />
+        android:minSdkVersion="28"
+        android:targetSdkVersion="28" />
 
     <uses-permission android:name="android.permission.READ_LOGS" />
 
diff --git a/tests/NativeProcessesMemoryTest/Android.bp b/tests/NativeProcessesMemoryTest/Android.bp
new file mode 100644
index 0000000..f2625bf
--- /dev/null
+++ b/tests/NativeProcessesMemoryTest/Android.bp
@@ -0,0 +1,21 @@
+// 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.
+
+java_test_host {
+    name: "native-processes-memory-test",
+    srcs: ["src/**/*.java"],
+
+    libs: ["tradefed"],
+    test_suites: ["general-tests"],
+}
diff --git a/media/lib/remotedisplay/com.android.media.remotedisplay.xml b/tests/NativeProcessesMemoryTest/AndroidTest.xml
similarity index 60%
rename from media/lib/remotedisplay/com.android.media.remotedisplay.xml
rename to tests/NativeProcessesMemoryTest/AndroidTest.xml
index 77a91d2..0f326fd 100644
--- a/media/lib/remotedisplay/com.android.media.remotedisplay.xml
+++ b/tests/NativeProcessesMemoryTest/AndroidTest.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 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.
@@ -13,8 +13,9 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
-<permissions>
-    <library name="com.android.media.remotedisplay"
-            file="/system/framework/com.android.media.remotedisplay.jar" />
-</permissions>
+<configuration description="Runs the native processes memory tests">
+    <option name="test-suite-tag" value="native-processes-memory-test" />
+    <test class="com.android.tradefed.testtype.HostTest" >
+        <option name="class" value="com.android.tests.nativeprocesses.NativeProcessesMemoryTest" />
+    </test>
+</configuration>
diff --git a/tests/NativeProcessesMemoryTest/src/com/android/tests/nativeprocesses/NativeProcessesMemoryTest.java b/tests/NativeProcessesMemoryTest/src/com/android/tests/nativeprocesses/NativeProcessesMemoryTest.java
new file mode 100644
index 0000000..c86f06e
--- /dev/null
+++ b/tests/NativeProcessesMemoryTest/src/com/android/tests/nativeprocesses/NativeProcessesMemoryTest.java
@@ -0,0 +1,239 @@
+/*
+ * 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.nativeprocesses;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.result.ByteArrayInputStreamSource;
+import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.result.LogDataType;
+import com.android.tradefed.result.TestDescription;
+import com.android.tradefed.testtype.IDeviceTest;
+import com.android.tradefed.testtype.IRemoteTest;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.InputMismatchException;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Scanner;
+
+/**
+ * Test to gather native processes count and memory usage.
+ *
+ * Native processes are parsed from dumpsys meminfo --oom -c
+ *
+ * <pre>
+ * time,35857009,35857009
+ * oom,native,331721,N/A
+ * proc,native,init,1,2715,N/A,e
+ * proc,native,init,445,1492,N/A,e
+ * ...
+ * </pre>
+ *
+ * For each native process we also look at its showmap output, and gather the PSS, VSS, and RSS.
+ * The showmap output is also saved to test logs.
+ *
+ * The metrics reported are:
+ *
+ * <pre>
+ *   - number of native processes
+ *   - total memory use of native processes
+ *   - memory usage of each native process (one measurement for each process)
+ * </pre>
+ */
+public class NativeProcessesMemoryTest implements IDeviceTest, IRemoteTest {
+    // the dumpsys process comes and go as we run this test, changing pids, so ignore it
+    private static final List<String> PROCESSES_TO_IGNORE = Arrays.asList("dumpsys");
+
+    // -c gives us a compact output which is comma separated
+    private static final String DUMPSYS_MEMINFO_OOM_CMD = "dumpsys meminfo --oom -c";
+
+    private static final String SEPARATOR = ",";
+    private static final String LINE_SEPARATOR = "\\n";
+
+    // name of this test run, used for reporting
+    private static final String RUN_NAME = "NativeProcessesTest";
+    // key used to report the number of native processes
+    private static final String NUM_NATIVE_PROCESSES_KEY = "Num_native_processes";
+
+    private final Map<String, String> mNativeProcessToMemory = new HashMap<String, String>();
+    // identity for summing over MemoryMetric
+    private final MemoryMetric mZero = new MemoryMetric(0, 0, 0);
+
+    private ITestDevice mTestDevice;
+    private ITestInvocationListener mListener;
+
+    public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
+        mListener = listener;
+        // showmap requires root, we enable it here for the rest of the test
+        mTestDevice.enableAdbRoot();
+
+        listener.testRunStarted(RUN_NAME, 1 /* testCount */);
+
+        TestDescription testDescription = new TestDescription(getClass().getName(), "run");
+        listener.testStarted(testDescription);
+
+        // process name -> list of pids with that name
+        Map<String, List<String>> nativeProcesses = collectNativeProcesses();
+        sampleAndLogAllProcesses(nativeProcesses);
+
+        // want to also record the number of native processes
+        mNativeProcessToMemory.put(
+                NUM_NATIVE_PROCESSES_KEY, Integer.toString(nativeProcesses.size()));
+
+        listener.testEnded(testDescription, mNativeProcessToMemory);
+        listener.testRunEnded(0, new HashMap<String, String>());
+    }
+
+    /** Samples memory of all processes and logs the memory use. */
+    private void sampleAndLogAllProcesses(Map<String, List<String>> nativeProcesses)
+            throws DeviceNotAvailableException {
+        for (Map.Entry<String, List<String>> entry : nativeProcesses.entrySet()) {
+            String processName = entry.getKey();
+            if (PROCESSES_TO_IGNORE.contains(processName)) {
+                continue;
+            }
+
+            // for all pids associated with this process name, record their memory usage
+            List<MemoryMetric> allMemsForProcess = new ArrayList<>();
+            for (String pid : entry.getValue()) {
+                Optional<MemoryMetric> mem = snapMemoryUsage(processName, pid);
+                if (mem.isPresent()) {
+                    allMemsForProcess.add(mem.get());
+                }
+            }
+
+            // if for some reason a process does not have any MemoryMetric, don't log it
+            if (allMemsForProcess.isEmpty()) {
+                continue;
+            }
+
+            // combine all the memory metrics of process with the same name
+            MemoryMetric combined = allMemsForProcess.stream().reduce(mZero, MemoryMetric::sum);
+            logMemoryMetric(processName, combined);
+        }
+    }
+
+    @Override
+    public void setDevice(ITestDevice device) {
+        mTestDevice = device;
+    }
+
+    @Override
+    public ITestDevice getDevice() {
+        return mTestDevice;
+    }
+
+    /**
+     * Query system for a list of native process.
+     *
+     * @return a map from process name to a list of pids that share the same name
+     */
+    private Map<String, List<String>> collectNativeProcesses() throws DeviceNotAvailableException {
+        HashMap<String, List<String>> nativeProcesses = new HashMap<>();
+        String memInfo = mTestDevice.executeShellCommand(DUMPSYS_MEMINFO_OOM_CMD);
+
+        for (String line : memInfo.split(LINE_SEPARATOR)) {
+            String[] splits = line.split(SEPARATOR);
+            // ignore lines that don't list a native process
+            if (splits.length < 4 || !splits[0].equals("proc") || !splits[1].equals("native")) {
+                continue;
+            }
+
+            String processName = splits[2];
+            String pid = splits[3];
+            if (nativeProcesses.containsKey(processName)) {
+                nativeProcesses.get(processName).add(pid);
+            } else {
+                nativeProcesses.put(processName, new ArrayList<>(Arrays.asList(pid)));
+            }
+        }
+        return nativeProcesses;
+    }
+
+    /** Logs an entire showmap output to the test logs. */
+    private void logShowmap(String label, String showmap) {
+        try (ByteArrayInputStreamSource source =
+                new ByteArrayInputStreamSource(showmap.getBytes())) {
+            mListener.testLog(label + "_showmap", LogDataType.TEXT, source);
+        }
+    }
+
+    /**
+     * Extract VSS, PSS, and RSS from showmap of a process.
+     * The showmap output is also added to test logs.
+     */
+    private Optional<MemoryMetric> snapMemoryUsage(String processName, String pid)
+            throws DeviceNotAvailableException {
+        // TODO(zhin): copied from com.android.tests.sysmem.host.Metrics#sample(), extract?
+        String showmap = mTestDevice.executeShellCommand("showmap " + pid);
+        logShowmap(processName + "_" + pid, showmap);
+
+        // CHECKSTYLE:OFF Generated code
+        // The last lines of the showmap output looks like:
+        // ------- -------- -------- -------- -------- -------- -------- -------- -------- ---- ------------------------------
+        // virtual                     shared   shared  private  private
+        //    size      RSS      PSS    clean    dirty    clean    dirty     swap  swapPSS   # object
+        // -------- -------- -------- -------- -------- -------- -------- -------- -------- ---- ------------------------------
+        //   12848     4240     1543     2852       64       36     1288        0        0  171 TOTAL
+        // CHECKSTYLE:ON Generated code
+        try {
+            int pos = showmap.lastIndexOf("----");
+            Scanner sc = new Scanner(showmap.substring(pos));
+            sc.next();
+            long vss = sc.nextLong();
+            long rss = sc.nextLong();
+            long pss = sc.nextLong();
+            return Optional.of(new MemoryMetric(pss, rss, vss));
+        } catch (InputMismatchException e) {
+            // this might occur if we have transient processes, it was collected earlier,
+            // but by the time we look at showmap the process is gone
+            CLog.e("Unable to parse MemoryMetric from showmap of pid: " + pid + " processName: "
+                    + processName);
+            CLog.e(showmap);
+            return Optional.empty();
+        }
+    }
+
+    /** Logs a MemoryMetric of a process. */
+    private void logMemoryMetric(String processName, MemoryMetric memoryMetric) {
+        mNativeProcessToMemory.put(processName + "_pss", Long.toString(memoryMetric.pss));
+        mNativeProcessToMemory.put(processName + "_rss", Long.toString(memoryMetric.rss));
+        mNativeProcessToMemory.put(processName + "_vss", Long.toString(memoryMetric.vss));
+    }
+
+    /** Container of memory numbers we want to log. */
+    private final class MemoryMetric {
+        final long pss;
+        final long rss;
+        final long vss;
+
+        MemoryMetric(long pss, long rss, long vss) {
+            this.pss = pss;
+            this.rss = rss;
+            this.vss = vss;
+        }
+
+        MemoryMetric sum(MemoryMetric other) {
+            return new MemoryMetric(
+                    pss + other.pss, rss + other.rss, vss + other.vss);
+        }
+    }
+}
diff --git a/tests/RemoteDisplayProvider/Android.mk b/tests/RemoteDisplayProvider/Android.mk
index e827ec2..43bf024 100644
--- a/tests/RemoteDisplayProvider/Android.mk
+++ b/tests/RemoteDisplayProvider/Android.mk
@@ -18,9 +18,9 @@
 include $(CLEAR_VARS)
 LOCAL_PACKAGE_NAME := RemoteDisplayProviderTest
 LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := system_current
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_RESOURCE_DIR = $(LOCAL_PATH)/res
-LOCAL_JAVA_LIBRARIES := com.android.media.remotedisplay.stubs
+LOCAL_JAVA_LIBRARIES := com.android.media.remotedisplay
 LOCAL_CERTIFICATE := platform
 include $(BUILD_PACKAGE)
diff --git a/tests/net/java/android/net/netlink/InetDiagSocketTest.java b/tests/net/java/android/net/netlink/InetDiagSocketTest.java
index 39ecb7e5a..122edba 100644
--- a/tests/net/java/android/net/netlink/InetDiagSocketTest.java
+++ b/tests/net/java/android/net/netlink/InetDiagSocketTest.java
@@ -69,17 +69,12 @@
     private ConnectivityManager mCm;
     private Context mContext;
     private final static int SOCKET_TIMEOUT_MS = 100;
-    private boolean mInetDiagUdpEnabled;
 
     @Before
     public void setUp() throws Exception {
         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
         mContext = instrumentation.getTargetContext();
         mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
-        int expectedUid = Process.myUid();
-        UdpConnection udp = new UdpConnection("127.0.0.1", "127.0.0.2");
-        int uid = mCm.getConnectionOwnerUid(udp.protocol, udp.local, udp.remote);
-        mInetDiagUdpEnabled = (uid == expectedUid);
     }
 
     private class Connection {
@@ -188,11 +183,6 @@
         tcp.close();
 
         /**
-         * TODO: STOPSHIP: Always test for UDP, do not allow opt-out.
-         */
-        if (!mInetDiagUdpEnabled) return;
-
-        /**
          * For UDP connections, either a complete match {protocol, local, remote} or a
          * partial match {protocol, local} should return a valid UID.
          */
diff --git a/tests/net/java/android/net/util/SharedLogTest.java b/tests/net/java/android/net/util/SharedLogTest.java
index d46facf..8604860 100644
--- a/tests/net/java/android/net/util/SharedLogTest.java
+++ b/tests/net/java/android/net/util/SharedLogTest.java
@@ -44,6 +44,8 @@
         final SharedLog logLevel2a = logTop.forSubComponent("twoA");
         final SharedLog logLevel2b = logTop.forSubComponent("twoB");
         logLevel2b.e("2b or not 2b");
+        logLevel2b.e("No exception", null);
+        logLevel2b.e("Wait, here's one", new Exception("Test"));
         logLevel2a.w("second post?");
 
         final SharedLog logLevel3 = logLevel2a.forSubComponent("three");
@@ -54,6 +56,9 @@
         final String[] expected = {
             " - MARK first post!",
             " - [twoB] ERROR 2b or not 2b",
+            " - [twoB] ERROR No exception",
+            // No stacktrace in shared log, only in logcat
+            " - [twoB] ERROR Wait, here's one: Test",
             " - [twoA] WARN second post?",
             " - still logging",
             " - [twoA.three] 3 >> 2",
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index e3db7e8..1a05305 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -79,6 +79,7 @@
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
+import android.content.ContentProvider;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -248,7 +249,7 @@
         @Spy private Resources mResources;
         private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
 
-        MockContext(Context base) {
+        MockContext(Context base, ContentProvider settingsProvider) {
             super(base);
 
             mResources = spy(base.getResources());
@@ -260,7 +261,7 @@
                     });
 
             mContentResolver = new MockContentResolver();
-            mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
+            mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
         }
 
         @Override
@@ -1048,7 +1049,9 @@
             Looper.prepare();
         }
 
-        mServiceContext = new MockContext(InstrumentationRegistry.getContext());
+        FakeSettingsProvider.clearSettingsProvider();
+        mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
+                new FakeSettingsProvider());
         LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
         LocalServices.addService(
                 NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
@@ -1086,6 +1089,7 @@
             mEthernetNetworkAgent.disconnect();
             mEthernetNetworkAgent = null;
         }
+        FakeSettingsProvider.clearSettingsProvider();
     }
 
     private static int transportToLegacyType(int transport) {
@@ -4532,4 +4536,78 @@
         mCellNetworkAgent.disconnect();
         mCm.unregisterNetworkCallback(networkCallback);
     }
+
+    @Test
+    public void testDataActivityTracking() throws RemoteException {
+        final TestNetworkCallback networkCallback = new TestNetworkCallback();
+        final NetworkRequest networkRequest = new NetworkRequest.Builder()
+                .addCapability(NET_CAPABILITY_INTERNET)
+                .build();
+        mCm.registerNetworkCallback(networkRequest, networkCallback);
+
+        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+        final LinkProperties cellLp = new LinkProperties();
+        cellLp.setInterfaceName(MOBILE_IFNAME);
+        mCellNetworkAgent.sendLinkProperties(cellLp);
+        reset(mNetworkManagementService);
+        mCellNetworkAgent.connect(true);
+        networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
+                eq(ConnectivityManager.TYPE_MOBILE));
+
+        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+        final LinkProperties wifiLp = new LinkProperties();
+        wifiLp.setInterfaceName(WIFI_IFNAME);
+        mWiFiNetworkAgent.sendLinkProperties(wifiLp);
+
+        // Network switch
+        reset(mNetworkManagementService);
+        mWiFiNetworkAgent.connect(true);
+        networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        networkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+        networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+        verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(),
+                eq(ConnectivityManager.TYPE_WIFI));
+        verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(MOBILE_IFNAME));
+
+        // Disconnect wifi and switch back to cell
+        reset(mNetworkManagementService);
+        mWiFiNetworkAgent.disconnect();
+        networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+        assertNoCallbacks(networkCallback);
+        verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
+        verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
+                eq(ConnectivityManager.TYPE_MOBILE));
+
+        // reconnect wifi
+        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+        wifiLp.setInterfaceName(WIFI_IFNAME);
+        mWiFiNetworkAgent.sendLinkProperties(wifiLp);
+        mWiFiNetworkAgent.connect(true);
+        networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        networkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+        networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+
+        // Disconnect cell
+        reset(mNetworkManagementService);
+        mCellNetworkAgent.disconnect();
+        networkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
+        // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
+        // sent as network being switched. Ensure rule removal for cell will not be triggered
+        // unexpectedly before network being removed.
+        waitForIdle();
+        verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME));
+        verify(mNetworkManagementService, times(1)).removeNetwork(
+                eq(mCellNetworkAgent.getNetwork().netId));
+
+        // Disconnect wifi
+        ConditionVariable cv = waitForConnectivityBroadcasts(1);
+        reset(mNetworkManagementService);
+        mWiFiNetworkAgent.disconnect();
+        waitFor(cv);
+        verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
+
+        // Clean up
+        mCm.unregisterNetworkCallback(networkCallback);
+    }
 }
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index 40d5544..a6ed9f2 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -33,6 +33,7 @@
 import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
 import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
 import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
+import static android.provider.Settings.Global.TETHER_ENABLE_LEGACY_DHCP_SERVER;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -75,6 +76,8 @@
 import android.net.NetworkState;
 import android.net.NetworkUtils;
 import android.net.RouteInfo;
+import android.net.dhcp.DhcpServer;
+import android.net.dhcp.DhcpServingParams;
 import android.net.ip.IpServer;
 import android.net.ip.RouterAdvertisementDaemon;
 import android.net.util.InterfaceParams;
@@ -85,6 +88,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.INetworkManagementService;
+import android.os.Looper;
 import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.os.test.TestLooper;
@@ -146,6 +150,7 @@
     @Mock private UpstreamNetworkMonitor mUpstreamNetworkMonitor;
     @Mock private IPv6TetheringCoordinator mIPv6TetheringCoordinator;
     @Mock private RouterAdvertisementDaemon mRouterAdvertisementDaemon;
+    @Mock private DhcpServer mDhcpServer;
     @Mock private INetd mNetd;
 
     private final MockTetheringDependencies mTetheringDependencies =
@@ -240,6 +245,12 @@
                 public INetd getNetdService() {
                     return mNetd;
                 }
+
+                @Override
+                public DhcpServer makeDhcpServer(Looper looper, InterfaceParams iface,
+                        DhcpServingParams params, SharedLog log) {
+                    return mDhcpServer;
+                }
             };
         }
 
@@ -333,6 +344,7 @@
         mServiceContext = new MockContext(mContext);
         mContentResolver = new MockContentResolver(mServiceContext);
         mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
+        Settings.Global.putInt(mContentResolver, TETHER_ENABLE_LEGACY_DHCP_SERVER, 0);
         mIntents = new Vector<>();
         mBroadcastReceiver = new BroadcastReceiver() {
             @Override
@@ -343,12 +355,16 @@
         mServiceContext.registerReceiver(mBroadcastReceiver,
                 new IntentFilter(ACTION_TETHER_STATE_CHANGED));
         mTetheringDependencies.reset();
-        mTethering = new Tethering(mServiceContext, mNMService, mStatsService, mPolicyManager,
-                                   mLooper.getLooper(), mSystemProperties,
-                                   mTetheringDependencies);
+        mTethering = makeTethering();
         verify(mNMService).registerTetheringStatsProvider(any(), anyString());
     }
 
+    private Tethering makeTethering() {
+        return new Tethering(mServiceContext, mNMService, mStatsService, mPolicyManager,
+                mLooper.getLooper(), mSystemProperties,
+                mTetheringDependencies);
+    }
+
     @After
     public void tearDown() {
         mServiceContext.unregisterReceiver(mBroadcastReceiver);
@@ -597,6 +613,18 @@
 
         sendIPv6TetherUpdates(upstreamState);
         verify(mRouterAdvertisementDaemon, never()).buildNewRa(any(), notNull());
+        verify(mDhcpServer, times(1)).start();
+    }
+
+    @Test
+    public void workingMobileUsbTethering_IPv4LegacyDhcp() {
+        Settings.Global.putInt(mContentResolver, TETHER_ENABLE_LEGACY_DHCP_SERVER, 1);
+        mTethering = makeTethering();
+        final NetworkState upstreamState = buildMobileIPv4UpstreamState();
+        runUsbTethering(upstreamState);
+        sendIPv6TetherUpdates(upstreamState);
+
+        verify(mDhcpServer, never()).start();
     }
 
     @Test
@@ -620,6 +648,7 @@
         verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
         verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
         verify(mRouterAdvertisementDaemon, times(1)).start();
+        verify(mDhcpServer, times(1)).start();
 
         sendIPv6TetherUpdates(upstreamState);
         verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
@@ -633,6 +662,7 @@
 
         verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
         verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
+        verify(mDhcpServer, times(1)).start();
         verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
         verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME,
                 TEST_XLAT_MOBILE_IFNAME);
@@ -649,6 +679,7 @@
         runUsbTethering(upstreamState);
 
         verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
+        verify(mDhcpServer, times(1)).start();
         verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
 
         // Then 464xlat comes up
@@ -671,6 +702,8 @@
         // Forwarding was not re-added for v6 (still times(1))
         verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
         verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
+        // DHCP not restarted on downstream (still times(1))
+        verify(mDhcpServer, times(1)).start();
     }
 
     @Test
diff --git a/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java b/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
index bb31230..5217784 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
@@ -225,13 +225,4 @@
         final TetheringConfiguration cfg = new TetheringConfiguration(mMockContext, mLog);
         assertFalse(cfg.enableLegacyDhcpServer);
     }
-
-    @Test
-    public void testNewDhcpServerDefault() {
-        Settings.Global.putString(mContentResolver, TETHER_ENABLE_LEGACY_DHCP_SERVER, null);
-
-        final TetheringConfiguration cfg = new TetheringConfiguration(mMockContext, mLog);
-        // TODO: change to false when new server is promoted to default
-        assertTrue(cfg.enableLegacyDhcpServer);
-    }
 }
diff --git a/tools/aapt2/ConfigDescription.h b/tools/aapt2/ConfigDescription.h
index f719552..b46a503 100644
--- a/tools/aapt2/ConfigDescription.h
+++ b/tools/aapt2/ConfigDescription.h
@@ -53,11 +53,11 @@
   ConfigDescription();
   ConfigDescription(const android::ResTable_config& o);  // NOLINT(implicit)
   ConfigDescription(const ConfigDescription& o);
-  ConfigDescription(ConfigDescription&& o);
+  ConfigDescription(ConfigDescription&& o) noexcept;
 
   ConfigDescription& operator=(const android::ResTable_config& o);
   ConfigDescription& operator=(const ConfigDescription& o);
-  ConfigDescription& operator=(ConfigDescription&& o);
+  ConfigDescription& operator=(ConfigDescription&& o) noexcept;
 
   ConfigDescription CopyWithoutSdkVersion() const;
 
@@ -124,7 +124,7 @@
   *static_cast<android::ResTable_config*>(this) = o;
 }
 
-inline ConfigDescription::ConfigDescription(ConfigDescription&& o) {
+inline ConfigDescription::ConfigDescription(ConfigDescription&& o) noexcept {
   *this = o;
 }
 
@@ -141,7 +141,7 @@
   return *this;
 }
 
-inline ConfigDescription& ConfigDescription::operator=(ConfigDescription&& o) {
+inline ConfigDescription& ConfigDescription::operator=(ConfigDescription&& o) noexcept {
   *this = o;
   return *this;
 }
diff --git a/tools/aapt2/io/FileStream_test.cpp b/tools/aapt2/io/FileStream_test.cpp
index c0eaa8e..7872738 100644
--- a/tools/aapt2/io/FileStream_test.cpp
+++ b/tools/aapt2/io/FileStream_test.cpp
@@ -41,46 +41,46 @@
   ASSERT_FALSE(in.HadError());
   EXPECT_THAT(in.ByteCount(), Eq(0u));
 
-  const char* buffer;
+  const void* buffer;
   size_t size;
-  ASSERT_TRUE(in.Next(reinterpret_cast<const void**>(&buffer), &size)) << in.GetError();
+  ASSERT_TRUE(in.Next(&buffer, &size)) << in.GetError();
   ASSERT_THAT(size, Eq(10u));
   ASSERT_THAT(buffer, NotNull());
   EXPECT_THAT(in.ByteCount(), Eq(10u));
-  EXPECT_THAT(StringPiece(buffer, size), Eq("this is a "));
+  EXPECT_THAT(StringPiece(reinterpret_cast<const char*>(buffer), size), Eq("this is a "));
 
-  ASSERT_TRUE(in.Next(reinterpret_cast<const void**>(&buffer), &size));
+  ASSERT_TRUE(in.Next(&buffer, &size));
   ASSERT_THAT(size, Eq(10u));
   ASSERT_THAT(buffer, NotNull());
   EXPECT_THAT(in.ByteCount(), Eq(20u));
-  EXPECT_THAT(StringPiece(buffer, size), Eq("cool strin"));
+  EXPECT_THAT(StringPiece(reinterpret_cast<const char*>(buffer), size), Eq("cool strin"));
 
   in.BackUp(5u);
   EXPECT_THAT(in.ByteCount(), Eq(15u));
 
-  ASSERT_TRUE(in.Next(reinterpret_cast<const void**>(&buffer), &size));
+  ASSERT_TRUE(in.Next(&buffer, &size));
   ASSERT_THAT(size, Eq(5u));
   ASSERT_THAT(buffer, NotNull());
   ASSERT_THAT(in.ByteCount(), Eq(20u));
-  EXPECT_THAT(StringPiece(buffer, size), Eq("strin"));
+  EXPECT_THAT(StringPiece(reinterpret_cast<const char*>(buffer), size), Eq("strin"));
 
   // Backup 1 more than possible. Should clamp.
   in.BackUp(11u);
   EXPECT_THAT(in.ByteCount(), Eq(10u));
 
-  ASSERT_TRUE(in.Next(reinterpret_cast<const void**>(&buffer), &size));
+  ASSERT_TRUE(in.Next(&buffer, &size));
   ASSERT_THAT(size, Eq(10u));
   ASSERT_THAT(buffer, NotNull());
   ASSERT_THAT(in.ByteCount(), Eq(20u));
-  EXPECT_THAT(StringPiece(buffer, size), Eq("cool strin"));
+  EXPECT_THAT(StringPiece(reinterpret_cast<const char*>(buffer), size), Eq("cool strin"));
 
-  ASSERT_TRUE(in.Next(reinterpret_cast<const void**>(&buffer), &size));
+  ASSERT_TRUE(in.Next(&buffer, &size));
   ASSERT_THAT(size, Eq(1u));
   ASSERT_THAT(buffer, NotNull());
   ASSERT_THAT(in.ByteCount(), Eq(21u));
-  EXPECT_THAT(StringPiece(buffer, size), Eq("g"));
+  EXPECT_THAT(StringPiece(reinterpret_cast<const char*>(buffer), size), Eq("g"));
 
-  EXPECT_FALSE(in.Next(reinterpret_cast<const void**>(&buffer), &size));
+  EXPECT_FALSE(in.Next(&buffer, &size));
   EXPECT_FALSE(in.HadError());
 }
 
@@ -93,25 +93,25 @@
   ASSERT_FALSE(out.HadError());
   EXPECT_THAT(out.ByteCount(), Eq(0u));
 
-  char* buffer;
+  void* buffer;
   size_t size;
-  ASSERT_TRUE(out.Next(reinterpret_cast<void**>(&buffer), &size));
+  ASSERT_TRUE(out.Next(&buffer, &size));
   ASSERT_THAT(size, Eq(10u));
   ASSERT_THAT(buffer, NotNull());
   EXPECT_THAT(out.ByteCount(), Eq(10u));
-  memcpy(buffer, input.c_str(), size);
+  memcpy(reinterpret_cast<char*>(buffer), input.c_str(), size);
 
-  ASSERT_TRUE(out.Next(reinterpret_cast<void**>(&buffer), &size));
+  ASSERT_TRUE(out.Next(&buffer, &size));
   ASSERT_THAT(size, Eq(10u));
   ASSERT_THAT(buffer, NotNull());
   EXPECT_THAT(out.ByteCount(), Eq(20u));
-  memcpy(buffer, input.c_str() + 10u, size);
+  memcpy(reinterpret_cast<char*>(buffer), input.c_str() + 10u, size);
 
-  ASSERT_TRUE(out.Next(reinterpret_cast<void**>(&buffer), &size));
+  ASSERT_TRUE(out.Next(&buffer, &size));
   ASSERT_THAT(size, Eq(10u));
   ASSERT_THAT(buffer, NotNull());
   EXPECT_THAT(out.ByteCount(), Eq(30u));
-  buffer[0] = input[20u];
+  reinterpret_cast<char*>(buffer)[0] = input[20u];
   out.BackUp(size - 1);
   EXPECT_THAT(out.ByteCount(), Eq(21u));
 
diff --git a/tools/aapt2/java/ManifestClassGenerator.cpp b/tools/aapt2/java/ManifestClassGenerator.cpp
index be67c9c..10e504e 100644
--- a/tools/aapt2/java/ManifestClassGenerator.cpp
+++ b/tools/aapt2/java/ManifestClassGenerator.cpp
@@ -26,21 +26,20 @@
 #include "util/Maybe.h"
 #include "xml/XmlDom.h"
 
-using ::android::StringPiece;
 using ::aapt::text::IsJavaIdentifier;
 
 namespace aapt {
 
-static Maybe<StringPiece> ExtractJavaIdentifier(IDiagnostics* diag, const Source& source,
+static Maybe<std::string> ExtractJavaIdentifier(IDiagnostics* diag, const Source& source,
                                                 const std::string& value) {
-  StringPiece result = value;
+  std::string result = value;
   size_t pos = value.rfind('.');
   if (pos != std::string::npos) {
     result = result.substr(pos + 1);
   }
 
   // Normalize only the java identifier, leave the original value unchanged.
-  if (result.contains("-")) {
+  if (result.find("-") != std::string::npos) {
     result = JavaClassGenerator::TransformToFieldName(result);
   }
 
@@ -64,7 +63,7 @@
     return false;
   }
 
-  Maybe<StringPiece> result =
+  Maybe<std::string> result =
       ExtractJavaIdentifier(diag, source.WithLine(el->line_number), attr->value);
   if (!result) {
     return false;
diff --git a/tools/aapt2/util/BigBuffer.h b/tools/aapt2/util/BigBuffer.h
index 3045255..d4b3abc 100644
--- a/tools/aapt2/util/BigBuffer.h
+++ b/tools/aapt2/util/BigBuffer.h
@@ -68,7 +68,7 @@
    */
   explicit BigBuffer(size_t block_size);
 
-  BigBuffer(BigBuffer&& rhs);
+  BigBuffer(BigBuffer&& rhs) noexcept;
 
   /**
    * Number of occupied bytes in all the allocated blocks.
@@ -136,7 +136,7 @@
 inline BigBuffer::BigBuffer(size_t block_size)
     : block_size_(block_size), size_(0) {}
 
-inline BigBuffer::BigBuffer(BigBuffer&& rhs)
+inline BigBuffer::BigBuffer(BigBuffer&& rhs) noexcept
     : block_size_(rhs.block_size_),
       size_(rhs.size_),
       blocks_(std::move(rhs.blocks_)) {}
diff --git a/tools/aapt2/util/ImmutableMap.h b/tools/aapt2/util/ImmutableMap.h
index 59858e4..1727b18 100644
--- a/tools/aapt2/util/ImmutableMap.h
+++ b/tools/aapt2/util/ImmutableMap.h
@@ -32,8 +32,8 @@
   using const_iterator =
       typename std::vector<std::pair<TKey, TValue>>::const_iterator;
 
-  ImmutableMap(ImmutableMap&&) = default;
-  ImmutableMap& operator=(ImmutableMap&&) = default;
+  ImmutableMap(ImmutableMap&&) noexcept = default;
+  ImmutableMap& operator=(ImmutableMap&&) noexcept = default;
 
   static ImmutableMap<TKey, TValue> CreatePreSorted(
       std::initializer_list<std::pair<TKey, TValue>> list) {
diff --git a/tools/aapt2/util/Maybe.h b/tools/aapt2/util/Maybe.h
index 9a82418..031276c 100644
--- a/tools/aapt2/util/Maybe.h
+++ b/tools/aapt2/util/Maybe.h
@@ -46,7 +46,7 @@
   template <typename U>
   Maybe(const Maybe<U>& rhs);  // NOLINT(implicit)
 
-  Maybe(Maybe&& rhs);
+  Maybe(Maybe&& rhs) noexcept;
 
   template <typename U>
   Maybe(Maybe<U>&& rhs);  // NOLINT(implicit)
@@ -56,7 +56,7 @@
   template <typename U>
   Maybe& operator=(const Maybe<U>& rhs);
 
-  Maybe& operator=(Maybe&& rhs);
+  Maybe& operator=(Maybe&& rhs) noexcept;
 
   template <typename U>
   Maybe& operator=(Maybe<U>&& rhs);
@@ -134,7 +134,7 @@
 }
 
 template <typename T>
-Maybe<T>::Maybe(Maybe&& rhs) : nothing_(rhs.nothing_) {
+Maybe<T>::Maybe(Maybe&& rhs) noexcept : nothing_(rhs.nothing_) {
   if (!rhs.nothing_) {
     rhs.nothing_ = true;
 
@@ -192,7 +192,7 @@
 }
 
 template <typename T>
-inline Maybe<T>& Maybe<T>::operator=(Maybe&& rhs) {
+inline Maybe<T>& Maybe<T>::operator=(Maybe&& rhs) noexcept {
   // Delegate to the actual assignment.
   return move(std::forward<Maybe<T>>(rhs));
 }
diff --git a/tools/apilint/apilint.py b/tools/apilint/apilint.py
index 934847f..91cd1cb 100644
--- a/tools/apilint/apilint.py
+++ b/tools/apilint/apilint.py
@@ -492,6 +492,7 @@
 def verify_protected(clazz):
     """Verify that no protected methods or fields are allowed."""
     for m in clazz.methods:
+        if m.name == "finalize": continue
         if "protected" in m.split:
             error(clazz, m, "M7", "Protected methods not allowed; must be public")
     for f in clazz.fields:
@@ -1025,6 +1026,10 @@
     # Resources defined by files are foo_bar_baz
     if clazz.name in ["anim","animator","color","dimen","drawable","interpolator","layout","transition","menu","mipmap","string","plurals","raw","xml"]:
         for f in clazz.fields:
+            if re.match("config_[a-z][a-zA-Z1-9]*$", f.name): continue
+            if f.name.startswith("config_"):
+                error(clazz, f, None, "Expected config name to be config_fooBarBaz style")
+
             if re.match("[a-z1-9_]+$", f.name): continue
             error(clazz, f, None, "Expected resource name in this class to be foo_bar_baz style")
 
@@ -1361,6 +1366,60 @@
             error(clazz, m, None, "Provide an explicit copy constructor instead of implementing clone()")
 
 
+def verify_pfd(clazz):
+    """Verify that android APIs use PFD over FD."""
+    examine = clazz.ctors + clazz.methods
+    for m in examine:
+        if m.typ == "java.io.FileDescriptor":
+            error(clazz, m, "FW11", "Must use ParcelFileDescriptor")
+        if m.typ == "int":
+            if "Fd" in m.name or "FD" in m.name or "FileDescriptor" in m.name:
+                error(clazz, m, "FW11", "Must use ParcelFileDescriptor")
+        for arg in m.args:
+            if arg == "java.io.FileDescriptor":
+                error(clazz, m, "FW11", "Must use ParcelFileDescriptor")
+
+    for f in clazz.fields:
+        if f.typ == "java.io.FileDescriptor":
+            error(clazz, f, "FW11", "Must use ParcelFileDescriptor")
+
+
+def verify_numbers(clazz):
+    """Discourage small numbers types like short and byte."""
+
+    discouraged = ["short","byte"]
+
+    for c in clazz.ctors:
+        for arg in c.args:
+            if arg in discouraged:
+                warn(clazz, c, "FW12", "Should avoid odd sized primitives; use int instead")
+
+    for f in clazz.fields:
+        if f.typ in discouraged:
+            warn(clazz, f, "FW12", "Should avoid odd sized primitives; use int instead")
+
+    for m in clazz.methods:
+        if m.typ in discouraged:
+            warn(clazz, m, "FW12", "Should avoid odd sized primitives; use int instead")
+        for arg in m.args:
+            if arg in discouraged:
+                warn(clazz, m, "FW12", "Should avoid odd sized primitives; use int instead")
+
+
+def verify_singleton(clazz):
+    """Catch singleton objects with constructors."""
+
+    singleton = False
+    for m in clazz.methods:
+        if m.name.startswith("get") and m.name.endswith("Instance") and " static " in m.raw:
+            singleton = True
+
+    if singleton:
+        for c in clazz.ctors:
+            error(clazz, c, None, "Singleton classes should use getInstance() methods")
+
+
+
 def is_interesting(clazz):
     """Test if given class is interesting from an Android PoV."""
 
@@ -1431,6 +1490,9 @@
     verify_tense(clazz)
     verify_icu(clazz)
     verify_clone(clazz)
+    verify_pfd(clazz)
+    verify_numbers(clazz)
+    verify_singleton(clazz)
 
 
 def examine_stream(stream):
diff --git a/tools/fonts/add_additional_fonts.py b/tools/fonts/add_additional_fonts.py
deleted file mode 100644
index bf4af2b..0000000
--- a/tools/fonts/add_additional_fonts.py
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/env python
-#
-# 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.
-#
-
-import sys
-
-def main(argv):
-    original_file = 'frameworks/base/data/fonts/fonts.xml'
-
-    if len(argv) == 3:
-        output_file_path = argv[1]
-        override_file_path = argv[2]
-    else:
-        raise ValueError("Wrong number of arguments %s" % len(argv))
-
-    fallbackPlaceholderFound = False
-    with open(original_file, 'r') as input_file:
-        with open(output_file_path, 'w') as output_file:
-            for line in input_file:
-                # If we've found the spot to add additional fonts, add them.
-                if line.strip() == '<!-- fallback fonts -->':
-                    fallbackPlaceholderFound = True
-                    with open(override_file_path) as override_file:
-                        for override_line in override_file:
-                            output_file.write(override_line)
-                output_file.write(line)
-    if not fallbackPlaceholderFound:
-        raise ValueError('<!-- fallback fonts --> not found in source file: %s' % original_file)
-
-if __name__ == '__main__':
-    main(sys.argv)
diff --git a/tools/incident_section_gen/main.cpp b/tools/incident_section_gen/main.cpp
index 639f980..0cf1046 100644
--- a/tools/incident_section_gen/main.cpp
+++ b/tools/incident_section_gen/main.cpp
@@ -138,7 +138,7 @@
     size_t base = 0;
     size_t found;
     while (true) {
-        found = args.find_first_of(" ", base);
+        found = args.find_first_of(' ', base);
         if (found != base) {
             string arg = args.substr(base, found - base);
             printf(" \"%s\",", arg.c_str());
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index 9915479..56c8428 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -234,9 +234,11 @@
                     }
                 }
             } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
-                fprintf(out, ", const std::map<int, int64_t>& arg%d_1, "
-                             "const std::map<int, char const*>& arg%d_2, "
-                             "const std::map<int, float>& arg%d_3", argIndex, argIndex, argIndex);
+                fprintf(out, ", const std::map<int, int32_t>& arg%d_1, "
+                             "const std::map<int, int64_t>& arg%d_2, "
+                             "const std::map<int, char const*>& arg%d_3, "
+                             "const std::map<int, float>& arg%d_4",
+                             argIndex, argIndex, argIndex, argIndex);
             } else {
                 fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
             }
@@ -302,6 +304,13 @@
                     fprintf(out, "         event.end();\n");
                     fprintf(out, "    }\n");
 
+                    fprintf(out, "    for (const auto& it : arg%d_4) {\n", argIndex);
+                    fprintf(out, "         event.begin();\n");
+                    fprintf(out, "         event << it.first;\n");
+                    fprintf(out, "         event << it.second;\n");
+                    fprintf(out, "         event.end();\n");
+                    fprintf(out, "    }\n");
+
                     fprintf(out, "    event.end();\n\n");
             } else {
                 if (*arg == JAVA_TYPE_STRING) {
@@ -344,9 +353,11 @@
                    }
                }
            } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
-                fprintf(out, ", const std::map<int, int64_t>& arg%d_1, "
-                             "const std::map<int, char const*>& arg%d_2, "
-                             "const std::map<int, float>& arg%d_3", argIndex, argIndex, argIndex);
+                fprintf(out, ", const std::map<int, int32_t>& arg%d_1, "
+                             "const std::map<int, int64_t>& arg%d_2, "
+                             "const std::map<int, char const*>& arg%d_3, "
+                             "const std::map<int, float>& arg%d_4",
+                             argIndex, argIndex, argIndex, argIndex);
            } else {
                fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
            }
@@ -374,7 +385,8 @@
                    }
                }
            } else  if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
-                fprintf(out, ", arg%d_1, arg%d_2, arg%d_3", argIndex, argIndex, argIndex);
+                fprintf(out, ", arg%d_1, arg%d_2, arg%d_3, arg%d_4",
+                        argIndex, argIndex, argIndex, argIndex);
            } else {
                fprintf(out, ", arg%d", argIndex);
            }
@@ -529,10 +541,14 @@
                 }
             }
         } else if (field->javaType == JAVA_TYPE_KEY_VALUE_PAIR) {
-            fprintf(out, ", const std::map<int, int64_t>& %s_int"
+            fprintf(out, ", const std::map<int, int32_t>& %s_int"
+                         ", const std::map<int, int64_t>& %s_long"
                          ", const std::map<int, char const*>& %s_str"
                          ", const std::map<int, float>& %s_float",
-                         field->name.c_str(), field->name.c_str(), field->name.c_str());
+                         field->name.c_str(),
+                         field->name.c_str(),
+                         field->name.c_str(),
+                         field->name.c_str());
         } else {
             fprintf(out, ", %s %s", cpp_type_name(field->javaType), field->name.c_str());
         }
@@ -561,9 +577,11 @@
                     }
                 }
             } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
-                fprintf(out, ", const std::map<int, int64_t>& arg%d_1, "
-                             "const std::map<int, char const*>& arg%d_2, "
-                             "const std::map<int, float>& arg%d_3", argIndex, argIndex, argIndex);
+                fprintf(out, ", const std::map<int, int32_t>& arg%d_1, "
+                             "const std::map<int, int64_t>& arg%d_2, "
+                             "const std::map<int, char const*>& arg%d_3, "
+                             "const std::map<int, float>& arg%d_4",
+                             argIndex, argIndex, argIndex, argIndex);
             } else {
                 fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
             }
@@ -976,6 +994,7 @@
 }
 
 static void write_key_value_map_jni(FILE* out) {
+   fprintf(out, "    std::map<int, int32_t> int32_t_map;\n");
    fprintf(out, "    std::map<int, int64_t> int64_t_map;\n");
    fprintf(out, "    std::map<int, float> float_map;\n");
    fprintf(out, "    std::map<int, char const*> string_map;\n\n");
@@ -989,9 +1008,11 @@
 
    fprintf(out, "    std::vector<std::unique_ptr<ScopedUtfChars>> scoped_ufs;\n\n");
 
+   fprintf(out, "    jclass jint_class = env->FindClass(\"java/lang/Integer\");\n");
    fprintf(out, "    jclass jlong_class = env->FindClass(\"java/lang/Long\");\n");
    fprintf(out, "    jclass jfloat_class = env->FindClass(\"java/lang/Float\");\n");
    fprintf(out, "    jclass jstring_class = env->FindClass(\"java/lang/String\");\n");
+   fprintf(out, "    jmethodID jget_int_method = env->GetMethodID(jint_class, \"intValue\", \"()I\");\n");
    fprintf(out, "    jmethodID jget_long_method = env->GetMethodID(jlong_class, \"longValue\", \"()J\");\n");
    fprintf(out, "    jmethodID jget_float_method = env->GetMethodID(jfloat_class, \"floatValue\", \"()F\");\n\n");
 
@@ -1000,7 +1021,9 @@
    fprintf(out, "        jint key = env->CallIntMethod(value_map, jget_key_method, i);\n");
    fprintf(out, "        jobject jvalue_obj = env->CallObjectMethod(value_map, jget_value_method, i);\n");
    fprintf(out, "        if (jvalue_obj == NULL) { continue; }\n");
-   fprintf(out, "        if (env->IsInstanceOf(jvalue_obj, jlong_class)) {\n");
+   fprintf(out, "        if (env->IsInstanceOf(jvalue_obj, jint_class)) {\n");
+   fprintf(out, "            int32_t_map[key] = env->CallIntMethod(jvalue_obj, jget_int_method);\n");
+   fprintf(out, "        } else if (env->IsInstanceOf(jvalue_obj, jlong_class)) {\n");
    fprintf(out, "            int64_t_map[key] = env->CallLongMethod(jvalue_obj, jget_long_method);\n");
    fprintf(out, "        } else if (env->IsInstanceOf(jvalue_obj, jfloat_class)) {\n");
    fprintf(out, "            float_map[key] = env->CallFloatMethod(jvalue_obj, jget_float_method);\n");
@@ -1129,7 +1152,7 @@
                     }
                 }
             } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
-                fprintf(out, ", int64_t_map, string_map, float_map");
+                fprintf(out, ", int32_t_map, int64_t_map, string_map, float_map");
             } else {
                 const char *argName = (*arg == JAVA_TYPE_STRING) ? "str" : "arg";
                 fprintf(out, ", (%s)%s%d", cpp_type_name(*arg), argName, argIndex);
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index ce8d71d..58c1300 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -332,9 +332,10 @@
     public String preSharedKey;
 
     /**
-     * Up to four WEP keys. Either an ASCII string enclosed in double
-     * quotation marks (e.g., {@code "abcdef"}) or a string
-     * of hex digits (e.g., {@code 0102030405}).
+     * Four WEP keys. For each of the four values, provide either an ASCII
+     * string enclosed in double quotation marks (e.g., {@code "abcdef"}),
+     * a string of hex digits (e.g., {@code 0102030405}), or an empty string
+     * (e.g., {@code ""}).
      * <p/>
      * When the value of one of these keys is read, the actual key is
      * not returned, just a "*" if the key has a value, or the null
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 7a91347..59ba8e7 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1698,9 +1698,7 @@
      * @return the list of access points found in the most recent scan. An app must hold
      * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission
-     * in order to get valid results.  If there is a remote exception (e.g., either a communication
-     * problem with the system service or an exception within the framework) an empty list will be
-     * returned.
+     * in order to get valid results.
      */
     public List<ScanResult> getScanResults() {
         try {