Merge "Fix oom_adj range"
diff --git a/api/current.txt b/api/current.txt
index 8147ad5..6c4bd1b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11461,7 +11461,7 @@
     method public int getSessionId();
     method public long getSize();
     method public int getStagedSessionErrorCode();
-    method public String getStagedSessionErrorMessage();
+    method @NonNull public String getStagedSessionErrorMessage();
     method public android.os.UserHandle getUser();
     method public boolean isActive();
     method public boolean isMultiPackage();
@@ -23492,7 +23492,7 @@
   public static final class AudioRecord.MetricsConstants {
     field public static final String CHANNELS = "android.media.audiorecord.channels";
     field public static final String ENCODING = "android.media.audiorecord.encoding";
-    field public static final String LATENCY = "android.media.audiorecord.latency";
+    field @Deprecated public static final String LATENCY = "android.media.audiorecord.latency";
     field public static final String SAMPLERATE = "android.media.audiorecord.samplerate";
     field public static final String SOURCE = "android.media.audiorecord.source";
   }
@@ -23656,9 +23656,9 @@
   }
 
   public static final class AudioTrack.MetricsConstants {
-    field public static final String CHANNELMASK = "android.media.audiorecord.channelmask";
+    field @Deprecated public static final String CHANNELMASK = "android.media.audiorecord.channelmask";
     field public static final String CONTENTTYPE = "android.media.audiotrack.type";
-    field public static final String SAMPLERATE = "android.media.audiorecord.samplerate";
+    field @Deprecated public static final String SAMPLERATE = "android.media.audiorecord.samplerate";
     field public static final String STREAMTYPE = "android.media.audiotrack.streamtype";
     field public static final String USAGE = "android.media.audiotrack.usage";
   }
@@ -30806,7 +30806,6 @@
   }
 
   public final class NfcAdapter {
-    method public boolean deviceSupportsNfcSecure();
     method public void disableForegroundDispatch(android.app.Activity);
     method @Deprecated public void disableForegroundNdefPush(android.app.Activity);
     method public void disableReaderMode(android.app.Activity);
@@ -30819,7 +30818,8 @@
     method @Deprecated public boolean invokeBeam(android.app.Activity);
     method public boolean isEnabled();
     method @Deprecated public boolean isNdefPushEnabled();
-    method public boolean isNfcSecureEnabled();
+    method public boolean isSecureNfcEnabled();
+    method public boolean isSecureNfcSupported();
     method @Deprecated public void setBeamPushUris(android.net.Uri[], android.app.Activity);
     method @Deprecated public void setBeamPushUrisCallback(android.nfc.NfcAdapter.CreateBeamUrisCallback, android.app.Activity);
     method @Deprecated public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, android.app.Activity...);
@@ -35118,6 +35118,8 @@
   }
 
   public final class PowerManager {
+    method public void addThermalStatusListener(@NonNull android.os.PowerManager.OnThermalStatusChangedListener);
+    method public void addThermalStatusListener(@NonNull java.util.concurrent.Executor, @NonNull android.os.PowerManager.OnThermalStatusChangedListener);
     method public int getCurrentThermalStatus();
     method public int getLocationPowerSaveMode();
     method public boolean isDeviceIdleMode();
@@ -35129,8 +35131,7 @@
     method public boolean isWakeLockLevelSupported(int);
     method public android.os.PowerManager.WakeLock newWakeLock(int, String);
     method public void reboot(String);
-    method public void registerThermalStatusCallback(@NonNull android.os.PowerManager.ThermalStatusCallback, @NonNull java.util.concurrent.Executor);
-    method public void unregisterThermalStatusCallback(@NonNull android.os.PowerManager.ThermalStatusCallback);
+    method public void removeThermalStatusListener(@NonNull android.os.PowerManager.OnThermalStatusChangedListener);
     field public static final int ACQUIRE_CAUSES_WAKEUP = 268435456; // 0x10000000
     field public static final String ACTION_DEVICE_IDLE_MODE_CHANGED = "android.os.action.DEVICE_IDLE_MODE_CHANGED";
     field public static final String ACTION_POWER_SAVE_MODE_CHANGED = "android.os.action.POWER_SAVE_MODE_CHANGED";
@@ -35155,9 +35156,8 @@
     field public static final int THERMAL_STATUS_SHUTDOWN = 6; // 0x6
   }
 
-  public abstract static class PowerManager.ThermalStatusCallback {
-    ctor public PowerManager.ThermalStatusCallback();
-    method public void onStatusChange(int);
+  public static interface PowerManager.OnThermalStatusChangedListener {
+    method public void onThermalStatusChanged(int);
   }
 
   public final class PowerManager.WakeLock {
diff --git a/api/removed.txt b/api/removed.txt
index 7a06803..93d06928 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -335,11 +335,17 @@
 package android.net {
 
   public class ConnectivityManager {
+    method @Deprecated public void getLatestTetheringEntitlementValue(int, boolean, @NonNull android.net.ConnectivityManager.TetheringEntitlementValueListener, @Nullable android.os.Handler);
     method @Deprecated public boolean requestRouteToHost(int, int);
     method @Deprecated public int startUsingNetworkFeature(int, String);
     method @Deprecated public int stopUsingNetworkFeature(int, String);
   }
 
+  @Deprecated public abstract static class ConnectivityManager.TetheringEntitlementValueListener {
+    ctor public ConnectivityManager.TetheringEntitlementValueListener();
+    method public void onEntitlementResult(int);
+  }
+
   @Deprecated public class NetworkBadging {
     method @NonNull public static android.graphics.drawable.Drawable getWifiIcon(@IntRange(from=0, to=4) int, int, @Nullable android.content.res.Resources.Theme);
     field public static final int BADGING_4K = 30; // 0x1e
diff --git a/api/system-current.txt b/api/system-current.txt
index 42486b8..805bfb5 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4034,7 +4034,7 @@
     method @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createSocketKeepalive(@NonNull android.net.Network, @NonNull java.net.Socket, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback);
     method public boolean getAvoidBadWifi();
     method @RequiresPermission(android.Manifest.permission.LOCAL_MAC_ADDRESS) public String getCaptivePortalServerUrl();
-    method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void getLatestTetheringEntitlementValue(int, boolean, @NonNull android.net.ConnectivityManager.TetheringEntitlementValueListener, @Nullable android.os.Handler);
+    method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void getLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEntitlementResultListener);
     method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public boolean isTetheringSupported();
     method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void setAirplaneMode(boolean);
     method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(android.net.Network, android.os.Bundle);
@@ -4057,8 +4057,7 @@
     method public void onTetheringStarted();
   }
 
-  public abstract static class ConnectivityManager.TetheringEntitlementValueListener {
-    ctor public ConnectivityManager.TetheringEntitlementValueListener();
+  public static interface ConnectivityManager.OnTetheringEntitlementResultListener {
     method public void onEntitlementResult(int);
   }
 
@@ -5085,9 +5084,9 @@
     method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disableNdefPush();
     method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enable();
     method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableNdefPush();
+    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableSecureNfc(boolean);
     method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean removeNfcUnlockHandler(android.nfc.NfcAdapter.NfcUnlockHandler);
     method public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, int);
-    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean setNfcSecure(boolean);
     field public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 1; // 0x1
   }
 
@@ -6447,7 +6446,6 @@
     method public void onDestroyContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureSessionId);
     method public void onDisconnected();
     method public void onUserDataRemovalRequest(@NonNull android.view.contentcapture.UserDataRemovalRequest);
-    method @Deprecated public final void setContentCaptureWhitelist(@Nullable java.util.List<java.lang.String>, @Nullable java.util.List<android.content.ComponentName>);
     method public final void setContentCaptureWhitelist(@Nullable java.util.Set<java.lang.String>, @Nullable java.util.Set<android.content.ComponentName>);
     field public static final String SERVICE_INTERFACE = "android.service.contentcapture.ContentCaptureService";
   }
@@ -9501,7 +9499,6 @@
 package android.view.autofill {
 
   public final class AutofillManager {
-    method @Deprecated public void setAugmentedAutofillWhitelist(@Nullable java.util.List<java.lang.String>, @Nullable java.util.List<android.content.ComponentName>);
     method public void setAugmentedAutofillWhitelist(@Nullable java.util.Set<java.lang.String>, @Nullable java.util.Set<android.content.ComponentName>);
   }
 
diff --git a/api/test-current.txt b/api/test-current.txt
index 3b02954..26c21d3 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -2307,7 +2307,6 @@
     method public void onDestroyContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureSessionId);
     method public void onDisconnected();
     method public void onUserDataRemovalRequest(@NonNull android.view.contentcapture.UserDataRemovalRequest);
-    method @Deprecated public final void setContentCaptureWhitelist(@Nullable java.util.List<java.lang.String>, @Nullable java.util.List<android.content.ComponentName>);
     method public final void setContentCaptureWhitelist(@Nullable java.util.Set<java.lang.String>, @Nullable java.util.Set<android.content.ComponentName>);
     field public static final String SERVICE_INTERFACE = "android.service.contentcapture.ContentCaptureService";
   }
@@ -2935,7 +2934,6 @@
   }
 
   public final class AutofillManager {
-    method @Deprecated public void setAugmentedAutofillWhitelist(@Nullable java.util.List<java.lang.String>, @Nullable java.util.List<android.content.ComponentName>);
     method public void setAugmentedAutofillWhitelist(@Nullable java.util.Set<java.lang.String>, @Nullable java.util.Set<android.content.ComponentName>);
     field public static final String DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES = "smart_suggestion_supported_modes";
     field public static final int FLAG_SMART_SUGGESTION_OFF = 0; // 0x0
diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp
index a1341fb..f4c3e9c 100644
--- a/cmds/idmap2/libidmap2/Idmap.cpp
+++ b/cmds/idmap2/libidmap2/Idmap.cpp
@@ -287,11 +287,20 @@
 bool CheckOverlayable(const LoadedPackage& target_package,
                       const utils::OverlayManifestInfo& overlay_info,
                       const PolicyBitmask& fulfilled_policies, const ResourceId& resid) {
+  static constexpr const PolicyBitmask sDefaultPolicies =
+      PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_VENDOR_PARTITION |
+      PolicyFlags::POLICY_PRODUCT_PARTITION | PolicyFlags::POLICY_SIGNATURE;
+
+  // If the resource does not have an overlayable definition, allow the resource to be overlaid if
+  // the overlay is preinstalled or signed with the same signature as the target.
+  if (!target_package.DefinesOverlayable()) {
+    return (sDefaultPolicies & fulfilled_policies) != 0;
+  }
+
   const OverlayableInfo* overlayable_info = target_package.GetOverlayableInfo(resid);
   if (overlayable_info == nullptr) {
-    // If the resource does not have an overlayable definition, allow the resource to be overlaid.
-    // Once overlayable enforcement is turned on, this check will return false.
-    return !target_package.DefinesOverlayable();
+    // Do not allow non-overlayable resources to be overlaid.
+    return false;
   }
 
   if (overlay_info.target_name != overlayable_info->name) {
@@ -427,6 +436,12 @@
     matching_resources.Add(target_resid, overlay_resid);
   }
 
+  if (matching_resources.Map().empty()) {
+    out_error << "overlay \"" << overlay_apk_path << "\" does not successfully overlay any resource"
+              << std::endl;
+    return nullptr;
+  }
+
   // encode idmap data
   std::unique_ptr<IdmapData> data(new IdmapData());
   const auto types_end = matching_resources.Map().cend();
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
index bbfbad9..8d65428 100644
--- a/cmds/idmap2/tests/IdmapTests.cpp
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -173,20 +173,27 @@
   ASSERT_THAT(idmap, IsNull());
 }
 
-TEST(IdmapTests, CreateIdmapFromApkAssets) {
-  const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
-  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+void CreateIdmap(const StringPiece& target_apk_path, const StringPiece& overlay_apk_path,
+                 const PolicyBitmask& fulfilled_policies, bool enforce_overlayable,
+                 std::unique_ptr<const Idmap>* out_idmap) {
+  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path.to_string());
   ASSERT_THAT(target_apk, NotNull());
 
-  const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay.apk");
-  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path.to_string());
   ASSERT_THAT(overlay_apk, NotNull());
 
   std::stringstream error;
-  std::unique_ptr<const Idmap> idmap =
-      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
-                           PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
-  ASSERT_THAT(idmap, NotNull());
+  *out_idmap =
+      Idmap::FromApkAssets(target_apk_path.to_string(), *target_apk, overlay_apk_path.to_string(),
+                           *overlay_apk, fulfilled_policies, enforce_overlayable, error);
+}
+
+TEST(IdmapTests, CreateIdmapFromApkAssets) {
+  std::unique_ptr<const Idmap> idmap;
+  std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
+  std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay.apk";
+  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PUBLIC,
+              /* enforce_overlayable */ true, &idmap);
 
   ASSERT_THAT(idmap->GetHeader(), NotNull());
   ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
@@ -226,19 +233,12 @@
 
 // Overlays should abide by all overlayable restrictions if enforcement of overlayable is enabled.
 TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublic) {
-  const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
-  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
-  ASSERT_THAT(target_apk, NotNull());
-
-  const std::string overlay_apk_path(GetTestDataPath() + "/system-overlay/system-overlay.apk");
-  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
-  ASSERT_THAT(overlay_apk, NotNull());
-
-  std::stringstream error;
-  std::unique_ptr<const Idmap> idmap =
-      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
-                           PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
-                           /* enforce_overlayable */ true, error);
+  std::unique_ptr<const Idmap> idmap;
+  std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
+  std::string overlay_apk_path = GetTestDataPath() + "/system-overlay/system-overlay.apk";
+  CreateIdmap(target_apk_path, overlay_apk_path,
+              PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
+              /* enforce_overlayable */ true, &idmap);
   ASSERT_THAT(idmap, NotNull());
 
   const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
@@ -263,21 +263,12 @@
 }
 
 TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySignature) {
-  const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
-  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
-  ASSERT_THAT(target_apk, NotNull());
-
-  const std::string overlay_apk_path(GetTestDataPath() +
-                                     "/signature-overlay/signature-overlay.apk");
-  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
-  ASSERT_THAT(overlay_apk, NotNull());
-
-  uint32_t policy_flags = PolicyFlags::POLICY_PUBLIC | PolicyFlags::POLICY_SIGNATURE;
-
-  std::stringstream error;
-  std::unique_ptr<const Idmap> idmap =
-      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
-                           policy_flags, /* enforce_overlayable */ true, error);
+  std::unique_ptr<const Idmap> idmap;
+  std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
+  std::string overlay_apk_path = GetTestDataPath() + "/signature-overlay/signature-overlay.apk";
+  CreateIdmap(target_apk_path, overlay_apk_path,
+              PolicyFlags::POLICY_PUBLIC | PolicyFlags::POLICY_SIGNATURE,
+              /* enforce_overlayable */ true, &idmap);
   ASSERT_THAT(idmap, NotNull());
 
   const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
@@ -298,52 +289,15 @@
   ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);  // string/policy_signature
 }
 
-TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySignatureNotFulfilled) {
-  const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
-  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
-  ASSERT_THAT(target_apk, NotNull());
-
-  const std::string overlay_apk_path(GetTestDataPath() +
-                                     "/signature-overlay/signature-overlay.apk");
-  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
-  ASSERT_THAT(overlay_apk, NotNull());
-
-  uint32_t policy_flags = PolicyFlags::POLICY_PUBLIC;
-
-  std::stringstream error;
-  std::unique_ptr<const Idmap> idmap =
-      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
-                           policy_flags, /* enforce_overlayable */ true, error);
-  ASSERT_THAT(idmap, NotNull());
-
-  const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
-  ASSERT_EQ(dataBlocks.size(), 1U);
-
-  const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
-
-  ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
-  ASSERT_EQ(data->GetHeader()->GetTypeCount(), 0U);
-
-  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
-  ASSERT_EQ(types.size(), 0U);  // can't overlay, so contains nothing
-}
-
 // Overlays should abide by all overlayable restrictions if enforcement of overlayable is enabled.
 TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) {
-  const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
-  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
-  ASSERT_THAT(target_apk, NotNull());
-
-  const std::string overlay_apk_path(GetTestDataPath() +
-                                     "/system-overlay-invalid/system-overlay-invalid.apk");
-  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
-  ASSERT_THAT(overlay_apk, NotNull());
-
-  std::stringstream error;
-  std::unique_ptr<const Idmap> idmap =
-      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
-                           PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
-                           /* enforce_overlayable */ true, error);
+  std::unique_ptr<const Idmap> idmap;
+  std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
+  std::string overlay_apk_path =
+      GetTestDataPath() + "/system-overlay-invalid/system-overlay-invalid.apk";
+  CreateIdmap(target_apk_path, overlay_apk_path,
+              PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
+              /* enforce_overlayable */ true, &idmap);
   ASSERT_THAT(idmap, NotNull());
 
   const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
@@ -369,20 +323,13 @@
 
 // Overlays should ignore all overlayable restrictions if enforcement of overlayable is disabled.
 TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalidIgnoreOverlayable) {
-  const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
-  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
-  ASSERT_THAT(target_apk, NotNull());
-
-  const std::string overlay_apk_path(GetTestDataPath() +
-                                     "/system-overlay-invalid/system-overlay-invalid.apk");
-  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
-  ASSERT_THAT(overlay_apk, NotNull());
-
-  std::stringstream error;
-  std::unique_ptr<const Idmap> idmap =
-      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
-                           PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
-                           /* enforce_overlayable */ false, error);
+  std::unique_ptr<const Idmap> idmap;
+  std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
+  std::string overlay_apk_path =
+      GetTestDataPath() + "/system-overlay-invalid/system-overlay-invalid.apk";
+  CreateIdmap(target_apk_path, overlay_apk_path,
+              PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
+              /* enforce_overlayable */ false, &idmap);
   ASSERT_THAT(idmap, NotNull());
 
   const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
@@ -409,63 +356,13 @@
   ASSERT_EQ(types[0]->GetEntry(6), 0x0006U);  // string/policy_system_vendor
 }
 
-// The resources of APKs that do not include an overlayable declaration should not restrict what
-// resources can be overlaid.
-TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsNoDefinedOverlayable) {
-  const std::string target_apk_path(GetTestDataPath() + "/target/target-no-overlayable.apk");
-  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
-  ASSERT_THAT(target_apk, NotNull());
-
-  const std::string overlay_apk_path(GetTestDataPath() +
-                                     "/system-overlay-invalid/system-overlay-invalid.apk");
-  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
-  ASSERT_THAT(overlay_apk, NotNull());
-
-  std::stringstream error;
-  std::unique_ptr<const Idmap> idmap =
-      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
-                           PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
-  ASSERT_THAT(idmap, NotNull());
-
-  const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
-  ASSERT_EQ(dataBlocks.size(), 1U);
-
-  const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
-
-  ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
-  ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
-
-  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
-  ASSERT_EQ(types.size(), 1U);
-
-  ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
-  ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
-  ASSERT_EQ(types[0]->GetEntryCount(), 7U);
-  ASSERT_EQ(types[0]->GetEntryOffset(), 3U);
-  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);  // string/not_overlayable
-  ASSERT_EQ(types[0]->GetEntry(1), 0x0001U);  // string/other
-  ASSERT_EQ(types[0]->GetEntry(2), 0x0002U);  // string/policy_product
-  ASSERT_EQ(types[0]->GetEntry(3), 0x0003U);  // string/policy_public
-  ASSERT_EQ(types[0]->GetEntry(4), 0x0004U);  // string/string/policy_signature
-  ASSERT_EQ(types[0]->GetEntry(5), 0x0005U);  // string/policy_system
-  ASSERT_EQ(types[0]->GetEntry(6), 0x0006U);  // string/policy_system_vendor
-}
-
-// The resources of APKs that do not include an overlayable declaration should not restrict what
-// resources can be overlaid.
+// Overlays that do not specify a target <overlayable> can overlay resources defined as overlayable.
 TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsNoDefinedOverlayableAndNoTargetName) {
-  const std::string target_apk_path(GetTestDataPath() + "/target/target-no-overlayable.apk");
-  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
-  ASSERT_THAT(target_apk, NotNull());
-
-  const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay-no-name.apk");
-  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
-  ASSERT_THAT(overlay_apk, NotNull());
-
-  std::stringstream error;
-  std::unique_ptr<const Idmap> idmap =
-      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
-                           PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
+  std::unique_ptr<const Idmap> idmap;
+  std::string target_apk_path = GetTestDataPath() + "/target/target-no-overlayable.apk";
+  std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay-no-name.apk";
+  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PUBLIC,
+              /* enforce_overlayable */ false, &idmap);
   ASSERT_THAT(idmap, NotNull());
 
   const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
@@ -483,16 +380,81 @@
   ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
   ASSERT_EQ(types[0]->GetEntryCount(), 1U);
   ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
-  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);
+  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);  // string/int1
 
   ASSERT_EQ(types[1]->GetTargetTypeId(), 0x02U);
   ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x02U);
   ASSERT_EQ(types[1]->GetEntryCount(), 4U);
   ASSERT_EQ(types[1]->GetEntryOffset(), 10U);
-  ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);
-  ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
-  ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);
-  ASSERT_EQ(types[1]->GetEntry(3), 0x0002U);
+  ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);   // string/str1
+  ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);  // string/str2
+  ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);   // string/str3
+  ASSERT_EQ(types[1]->GetEntry(3), 0x0002U);   // string/str4
+}
+
+// Overlays that are not pre-installed and are not signed with the same signature as the target
+// cannot overlay packages that have not defined overlayable resources.
+TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsDefaultPoliciesPublicFail) {
+  std::unique_ptr<const Idmap> idmap;
+  std::string target_apk_path = GetTestDataPath() + "/target/target-no-overlayable.apk";
+  std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay-no-name.apk";
+  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PUBLIC,
+              /* enforce_overlayable */ true, &idmap);
+  ASSERT_THAT(idmap, IsNull());
+}
+
+// Overlays that are pre-installed or are signed with the same signature as the target can overlay
+// packages that have not defined overlayable resources.
+TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsDefaultPolicies) {
+  std::unique_ptr<const Idmap> idmap;
+  std::string target_apk_path = GetTestDataPath() + "/target/target-no-overlayable.apk";
+  std::string overlay_apk_path =
+      GetTestDataPath() + "/system-overlay-invalid/system-overlay-invalid.apk";
+
+  auto CheckEntries = [&]() -> void {
+    const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
+    ASSERT_EQ(dataBlocks.size(), 1U);
+
+    const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
+
+    ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
+    ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
+
+    const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
+    ASSERT_EQ(types.size(), 1U);
+
+    ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
+    ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
+    ASSERT_EQ(types[0]->GetEntryCount(), 7U);
+    ASSERT_EQ(types[0]->GetEntryOffset(), 3U);
+    ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);  // string/not_overlayable
+    ASSERT_EQ(types[0]->GetEntry(1), 0x0001U);  // string/other
+    ASSERT_EQ(types[0]->GetEntry(2), 0x0002U);  // string/policy_product
+    ASSERT_EQ(types[0]->GetEntry(3), 0x0003U);  // string/policy_public
+    ASSERT_EQ(types[0]->GetEntry(4), 0x0004U);  // string/string/policy_signature
+    ASSERT_EQ(types[0]->GetEntry(5), 0x0005U);  // string/policy_system
+    ASSERT_EQ(types[0]->GetEntry(6), 0x0006U);  // string/policy_system_vendor
+  };
+
+  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_SIGNATURE,
+              /* enforce_overlayable */ true, &idmap);
+  ASSERT_THAT(idmap, NotNull());
+  CheckEntries();
+
+  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PRODUCT_PARTITION,
+              /* enforce_overlayable */ true, &idmap);
+  ASSERT_THAT(idmap, NotNull());
+  CheckEntries();
+
+  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_SYSTEM_PARTITION,
+              /* enforce_overlayable */ true, &idmap);
+  ASSERT_THAT(idmap, NotNull());
+  CheckEntries();
+
+  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_VENDOR_PARTITION,
+              /* enforce_overlayable */ true, &idmap);
+  ASSERT_THAT(idmap, NotNull());
+  CheckEntries();
 }
 
 TEST(IdmapTests, FailToCreateIdmapFromApkAssetsIfPathTooLong) {
diff --git a/cmds/idmap2/tests/data/overlay/build b/cmds/idmap2/tests/data/overlay/build
index e879f44..68b9f50 100755
--- a/cmds/idmap2/tests/data/overlay/build
+++ b/cmds/idmap2/tests/data/overlay/build
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-FRAMEWORK_RES_APK="${ANDROID_BUILD_TOP}/out/target/common/obj/APPS/framework-res_intermediates/package-export.apk"
+FRAMEWORK_RES_APK=${ANDROID_BUILD_TOP}/prebuilts/sdk/current/public/android.jar
 
 aapt2 compile --dir res -o compiled.flata
 
diff --git a/cmds/idmap2/tests/data/overlay/overlay-no-name.apk b/cmds/idmap2/tests/data/overlay/overlay-no-name.apk
index 7d23c09..6425190 100644
--- a/cmds/idmap2/tests/data/overlay/overlay-no-name.apk
+++ b/cmds/idmap2/tests/data/overlay/overlay-no-name.apk
Binary files differ
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index b20cce9..7de8105 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -2130,7 +2130,7 @@
          * Text description of the error code returned by {@code getStagedSessionErrorCode}, or
          * empty string if no error was encountered.
          */
-        public String getStagedSessionErrorMessage() {
+        public @NonNull String getStagedSessionErrorMessage() {
             checkSessionIsStaged();
             return mStagedSessionErrorMessage;
         }
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 1312f18..0497f8c 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -2681,12 +2681,39 @@
         }
     }
 
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(value = {
+            TETHER_ERROR_NO_ERROR,
+            TETHER_ERROR_PROVISION_FAILED,
+            TETHER_ERROR_ENTITLEMENT_UNKONWN,
+    })
+    public @interface EntitlementResultCode {
+    }
+
     /**
-     * Callback for use with {@link #getLatestTetheringEntitlementValue} to find out whether
+     * Callback for use with {@link #getLatestTetheringEntitlementResult} to find out whether
      * entitlement succeeded.
      * @hide
      */
     @SystemApi
+    public interface OnTetheringEntitlementResultListener  {
+        /**
+         * Called to notify entitlement result.
+         *
+         * @param resultCode an int value of entitlement result. It may be one of
+         *         {@link #TETHER_ERROR_NO_ERROR},
+         *         {@link #TETHER_ERROR_PROVISION_FAILED}, or
+         *         {@link #TETHER_ERROR_ENTITLEMENT_UNKONWN}.
+         */
+        void onEntitlementResult(@EntitlementResultCode int resultCode);
+    }
+
+    /**
+     * @removed
+     * @deprecated This API would be removed when all of caller has been updated.
+     * */
+    @Deprecated
     public abstract static class TetheringEntitlementValueListener  {
         /**
          * Called to notify entitlement result.
@@ -2712,14 +2739,43 @@
      *         {@link #TETHERING_USB}, or
      *         {@link #TETHERING_BLUETOOTH}.
      * @param showEntitlementUi a boolean indicating whether to run UI-based entitlement check.
-     * @param listener an {@link TetheringEntitlementValueListener} which will be called to notify
-     *         the caller of the result of entitlement check. The listener may be called zero or
-     *         one time.
-     * @param handler {@link Handler} to specify the thread upon which the listener will be invoked.
+     * @param executor the executor on which callback will be invoked.
+     * @param listener an {@link OnTetheringEntitlementResultListener} which will be called to
+     *         notify the caller of the result of entitlement check. The listener may be called zero
+     *         or one time.
      * {@hide}
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
+    public void getLatestTetheringEntitlementResult(int type, boolean showEntitlementUi,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull final OnTetheringEntitlementResultListener listener) {
+        Preconditions.checkNotNull(listener, "TetheringEntitlementResultListener cannot be null.");
+        ResultReceiver wrappedListener = new ResultReceiver(null) {
+            @Override
+            protected void onReceiveResult(int resultCode, Bundle resultData) {
+                Binder.withCleanCallingIdentity(() ->
+                            executor.execute(() -> {
+                                listener.onEntitlementResult(resultCode);
+                            }));
+            }
+        };
+
+        try {
+            String pkgName = mContext.getOpPackageName();
+            Log.i(TAG, "getLatestTetheringEntitlementResult:" + pkgName);
+            mService.getLatestTetheringEntitlementResult(type, wrappedListener,
+                    showEntitlementUi, pkgName);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * @removed
+     * @deprecated This API would be removed when all of caller has been updated.
+     * */
+    @Deprecated
     public void getLatestTetheringEntitlementValue(int type, boolean showEntitlementUi,
             @NonNull final TetheringEntitlementValueListener listener, @Nullable Handler handler) {
         Preconditions.checkNotNull(listener, "TetheringEntitlementValueListener cannot be null.");
@@ -2733,7 +2789,7 @@
         try {
             String pkgName = mContext.getOpPackageName();
             Log.i(TAG, "getLatestTetheringEntitlementValue:" + pkgName);
-            mService.getLatestTetheringEntitlementValue(type, wrappedListener,
+            mService.getLatestTetheringEntitlementResult(type, wrappedListener,
                     showEntitlementUi, pkgName);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 6728712..fd44fc8 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -212,6 +212,6 @@
     boolean isCallerCurrentAlwaysOnVpnApp();
     boolean isCallerCurrentAlwaysOnVpnLockdownApp();
 
-    void getLatestTetheringEntitlementValue(int type, in ResultReceiver receiver,
+    void getLatestTetheringEntitlementResult(int type, in ResultReceiver receiver,
             boolean showEntitlementUi, String callerPkg);
 }
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index a7d2ee9..8970c62 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -1704,11 +1704,12 @@
     /**
      * Sets Secure NFC feature.
      * <p>This API is for the Settings application.
+     * @return True if successful
      * @hide
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public boolean setNfcSecure(boolean enable) {
+    public boolean enableSecureNfc(boolean enable) {
         if (!sHasNfcFeature) {
             throw new UnsupportedOperationException();
         }
@@ -1726,7 +1727,7 @@
      * @return True if device supports Secure NFC, false otherwise
      * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
      */
-    public boolean deviceSupportsNfcSecure() {
+    public boolean isSecureNfcSupported() {
         if (!sHasNfcFeature) {
             throw new UnsupportedOperationException();
         }
@@ -1741,12 +1742,12 @@
     /**
      * Checks Secure NFC feature is enabled.
      *
-     * @return True if device supports Secure NFC is enabled, false otherwise
+     * @return True if Secure NFC is enabled, false otherwise
      * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
      * @throws UnsupportedOperationException if device doesn't support
-     *         Secure NFC functionality. {@link #deviceSupportsNfcSecure}
+     *         Secure NFC functionality. {@link #isSecureNfcSupported}
      */
-    public boolean isNfcSecureEnabled() {
+    public boolean isSecureNfcEnabled() {
         if (!sHasNfcFeature) {
             throw new UnsupportedOperationException();
         }
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index c906d33..728b215 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -809,7 +809,8 @@
     final Handler mHandler;
 
     IThermalService mThermalService;
-    private ArrayMap<ThermalStatusCallback, IThermalStatusListener> mCallbackMap = new ArrayMap<>();
+    private final ArrayMap<OnThermalStatusChangedListener, IThermalStatusListener>
+            mListenerMap = new ArrayMap<>();
 
     IDeviceIdleController mIDeviceIdleController;
 
@@ -1769,51 +1770,73 @@
     }
 
     /**
-     * Callback passed to
-     * {@link PowerManager#registerThermalStatusCallback} and
-     * {@link PowerManager#unregisterThermalStatusCallback}
-     * to notify caller of thermal status.
+     * Listener passed to
+     * {@link PowerManager#addThermalStatusListener} and
+     * {@link PowerManager#removeThermalStatusListener}
+     * to notify caller of thermal status has changed.
      */
-    public abstract static class ThermalStatusCallback {
+    public interface OnThermalStatusChangedListener {
 
         /**
          * Called when overall thermal throttling status changed.
          * @param status defined in {@link android.os.Temperature}.
          */
-        public void onStatusChange(@ThermalStatus int status) {}
+        void onThermalStatusChanged(@ThermalStatus int status);
     }
 
+
     /**
-     * This function registers a callback for thermal status change.
+     * This function adds a listener for thermal status change, listen call back will be
+     * enqueued tasks on the main thread
      *
-     * @param callback callback to be registered.
-     * @param executor {@link Executor} to handle the callbacks.
+     * @param listener listener to be added,
      */
-    public void registerThermalStatusCallback(
-            @NonNull ThermalStatusCallback callback, @NonNull @CallbackExecutor Executor executor) {
-        Preconditions.checkNotNull(callback, "callback cannnot be null");
-        Preconditions.checkNotNull(executor, "executor cannnot be null");
+    public void addThermalStatusListener(@NonNull OnThermalStatusChangedListener listener) {
+        Preconditions.checkNotNull(listener, "listener cannot be null");
         synchronized (this) {
             if (mThermalService == null) {
                 mThermalService = IThermalService.Stub.asInterface(
                         ServiceManager.getService(Context.THERMAL_SERVICE));
             }
-            try {
-                if (mCallbackMap.containsKey(callback)) {
-                    throw new IllegalArgumentException("ThermalStatusCallback already registered");
-                }
-                IThermalStatusListener listener = new IThermalStatusListener.Stub() {
-                    @Override
-                    public void onStatusChange(int status) {
+            this.addThermalStatusListener(mContext.getMainExecutor(), listener);
+        }
+    }
+
+    /**
+     * This function adds a listener for thermal status change.
+     *
+     * @param executor {@link Executor} to handle listener callback.
+     * @param listener listener to be added.
+     */
+    public void addThermalStatusListener(@NonNull @CallbackExecutor Executor executor,
+            @NonNull OnThermalStatusChangedListener listener) {
+        Preconditions.checkNotNull(listener, "listener cannot be null");
+        Preconditions.checkNotNull(executor, "executor cannot be null");
+        synchronized (this) {
+            if (mThermalService == null) {
+                mThermalService = IThermalService.Stub.asInterface(
+                        ServiceManager.getService(Context.THERMAL_SERVICE));
+            }
+            Preconditions.checkArgument(!mListenerMap.containsKey(listener),
+                    "Listener already registered: " + listener);
+            IThermalStatusListener internalListener = new IThermalStatusListener.Stub() {
+                @Override
+                public void onStatusChange(int status) {
+                    final long token = Binder.clearCallingIdentity();
+                    try {
                         executor.execute(() -> {
-                            callback.onStatusChange(status);
+                            listener.onThermalStatusChanged(status);
                         });
+                    } finally {
+                        Binder.restoreCallingIdentity(token);
                     }
-                };
-                if (mThermalService.registerThermalStatusListener(listener)) {
-                    mCallbackMap.put(callback, listener);
+                }
+            };
+            try {
+                if (mThermalService.registerThermalStatusListener(internalListener)) {
+                    mListenerMap.put(listener, internalListener);
                 } else {
-                    throw new RuntimeException("ThermalStatusCallback failed to register");
+                    throw new RuntimeException("Listener failed to set");
                 }
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
@@ -1822,28 +1845,24 @@
     }
 
     /**
-     * This function unregisters a callback for thermal status change.
+     * This function removes a listener for thermal status change
      *
-     * @param callback to be unregistered.
-     *
-     * see {@link #registerThermalStatusCallback}
+     * @param listener listener to be removed
      */
-    public void unregisterThermalStatusCallback(@NonNull ThermalStatusCallback callback) {
-        Preconditions.checkNotNull(callback, "callback cannnot be null");
+    public void removeThermalStatusListener(@NonNull OnThermalStatusChangedListener listener) {
+        Preconditions.checkNotNull(listener, "listener cannot be null");
         synchronized (this) {
             if (mThermalService == null) {
                 mThermalService = IThermalService.Stub.asInterface(
                         ServiceManager.getService(Context.THERMAL_SERVICE));
             }
+            IThermalStatusListener internalListener = mListenerMap.get(listener);
+            Preconditions.checkArgument(internalListener != null, "Listener was not added");
             try {
-                IThermalStatusListener listener = mCallbackMap.get(callback);
-                if (listener == null) {
-                    throw new IllegalArgumentException("ThermalStatusCallback not registered");
-                }
-                if (mThermalService.unregisterThermalStatusListener(listener)) {
-                    mCallbackMap.remove(callback);
+                if (mThermalService.unregisterThermalStatusListener(internalListener)) {
+                    mListenerMap.remove(listener);
                 } else {
-                    throw new RuntimeException("ThermalStatusCallback failed to unregister");
+                    throw new RuntimeException("Listener failed to remove");
                 }
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 3a2564a..f8dfc58 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5758,7 +5758,11 @@
                 "autofill_user_data_min_value_length";
 
         /**
-         * Defines whether Content Capture is enabled  for the user.
+         * Defines whether Content Capture is enabled for the user.
+         *
+         * <p>Type: {@code int} ({@code 0} for disabled, {@code 1} for enabled).
+         * <p>Default: enabled
+         *
          * @hide
          */
         @TestApi
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index 9c4669f..4afd204 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -37,7 +37,6 @@
 import android.os.RemoteException;
 import android.service.autofill.AutofillService;
 import android.util.ArrayMap;
-import android.util.ArraySet;
 import android.util.Log;
 import android.util.Slog;
 import android.view.contentcapture.ContentCaptureContext;
@@ -168,19 +167,6 @@
     }
 
     /**
-     * @deprecated use {@link #setContentCaptureWhitelist(Set, Set)} instead
-     */
-    @Deprecated
-    public final void setContentCaptureWhitelist(@Nullable List<String> packages,
-            @Nullable List<ComponentName> activities) {
-        setContentCaptureWhitelist(toSet(packages), toSet(activities));
-    }
-
-    private <T> ArraySet<T> toSet(@Nullable List<T> set) {
-        return set == null ? null : new ArraySet<T>(set);
-    }
-
-    /**
      * Explicitly limits content capture to the given packages and activities.
      *
      * <p>To reset the whitelist, call it passing {@code null} to both arguments.
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index f13cb5a..2e27737 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -714,7 +714,8 @@
                 ie.setStackTrace(EMPTY_STACK_TRACE);
                 throw ie;
             } catch (Exception e) {
-                final InflateException ie = new InflateException(parser.getPositionDescription()
+                final InflateException ie = new InflateException(
+                        getParserStateDescription(inflaterContext, attrs)
                         + ": " + e.getMessage(), e);
                 ie.setStackTrace(EMPTY_STACK_TRACE);
                 throw ie;
@@ -730,6 +731,16 @@
         }
     }
 
+    private static String getParserStateDescription(Context context, AttributeSet attrs) {
+        int sourceResId = Resources.getAttributeSetSourceResId(attrs);
+        if (sourceResId == Resources.ID_NULL) {
+            return attrs.getPositionDescription();
+        } else {
+            return attrs.getPositionDescription() + " in "
+                    + context.getResources().getResourceName(sourceResId);
+        }
+    }
+
     private static final ClassLoader BOOT_CLASS_LOADER = LayoutInflater.class.getClassLoader();
 
     private final boolean verifyClassLoader(Constructor<? extends View> constructor) {
@@ -818,7 +829,7 @@
                 if (mFilter != null && clazz != null) {
                     boolean allowed = mFilter.onLoadClass(clazz);
                     if (!allowed) {
-                        failNotAllowed(name, prefix, attrs);
+                        failNotAllowed(name, prefix, viewContext, attrs);
                     }
                 }
                 constructor = clazz.getConstructor(mConstructorSignature);
@@ -837,10 +848,10 @@
                         boolean allowed = clazz != null && mFilter.onLoadClass(clazz);
                         mFilterMap.put(name, allowed);
                         if (!allowed) {
-                            failNotAllowed(name, prefix, attrs);
+                            failNotAllowed(name, prefix, viewContext, attrs);
                         }
                     } else if (allowedState.equals(Boolean.FALSE)) {
-                        failNotAllowed(name, prefix, attrs);
+                        failNotAllowed(name, prefix, viewContext, attrs);
                     }
                 }
             }
@@ -862,14 +873,16 @@
                 mConstructorArgs[0] = lastContext;
             }
         } catch (NoSuchMethodException e) {
-            final InflateException ie = new InflateException(attrs.getPositionDescription()
+            final InflateException ie = new InflateException(
+                    getParserStateDescription(viewContext, attrs)
                     + ": Error inflating class " + (prefix != null ? (prefix + name) : name), e);
             ie.setStackTrace(EMPTY_STACK_TRACE);
             throw ie;
 
         } catch (ClassCastException e) {
             // If loaded class is not a View subclass
-            final InflateException ie = new InflateException(attrs.getPositionDescription()
+            final InflateException ie = new InflateException(
+                    getParserStateDescription(viewContext, attrs)
                     + ": Class is not a View " + (prefix != null ? (prefix + name) : name), e);
             ie.setStackTrace(EMPTY_STACK_TRACE);
             throw ie;
@@ -878,7 +891,7 @@
             throw e;
         } catch (Exception e) {
             final InflateException ie = new InflateException(
-                    attrs.getPositionDescription() + ": Error inflating class "
+                    getParserStateDescription(viewContext, attrs) + ": Error inflating class "
                             + (clazz == null ? "<unknown>" : clazz.getName()), e);
             ie.setStackTrace(EMPTY_STACK_TRACE);
             throw ie;
@@ -890,8 +903,8 @@
     /**
      * Throw an exception because the specified class is not allowed to be inflated.
      */
-    private void failNotAllowed(String name, String prefix, AttributeSet attrs) {
-        throw new InflateException(attrs.getPositionDescription()
+    private void failNotAllowed(String name, String prefix, Context context, AttributeSet attrs) {
+        throw new InflateException(getParserStateDescription(context, attrs)
                 + ": Class not allowed to be inflated "+ (prefix != null ? (prefix + name) : name));
     }
 
@@ -1013,13 +1026,15 @@
             throw e;
 
         } catch (ClassNotFoundException e) {
-            final InflateException ie = new InflateException(attrs.getPositionDescription()
+            final InflateException ie = new InflateException(
+                    getParserStateDescription(context, attrs)
                     + ": Error inflating class " + name, e);
             ie.setStackTrace(EMPTY_STACK_TRACE);
             throw ie;
 
         } catch (Exception e) {
-            final InflateException ie = new InflateException(attrs.getPositionDescription()
+            final InflateException ie = new InflateException(
+                    getParserStateDescription(context, attrs)
                     + ": Error inflating class " + name, e);
             ie.setStackTrace(EMPTY_STACK_TRACE);
             throw ie;
@@ -1215,8 +1230,8 @@
                 }
 
                 if (type != XmlPullParser.START_TAG) {
-                    throw new InflateException(childParser.getPositionDescription() +
-                        ": No start tag found!");
+                    throw new InflateException(getParserStateDescription(context, childAttrs)
+                            + ": No start tag found!");
                 }
 
                 final String childName = childParser.getName();
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index f8d5014..b2f3f5e 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -67,6 +67,7 @@
     private boolean mExpanded;
     private boolean mShowExpandButtonAtEnd;
     private boolean mShowWorkBadgeAtEnd;
+    private int mHeaderTextMarginEnd;
     private Drawable mBackground;
     private boolean mEntireHeaderClickable;
     private boolean mExpandOnlyOnButton;
@@ -133,7 +134,8 @@
                 MeasureSpec.AT_MOST);
         int wrapContentHeightSpec = MeasureSpec.makeMeasureSpec(givenHeight,
                 MeasureSpec.AT_MOST);
-        int totalWidth = getPaddingStart() + getPaddingEnd();
+        int totalWidth = getPaddingStart();
+        int iconWidth = getPaddingEnd();
         for (int i = 0; i < getChildCount(); i++) {
             final View child = getChildAt(i);
             if (child.getVisibility() == GONE) {
@@ -146,10 +148,19 @@
             int childHeightSpec = getChildMeasureSpec(wrapContentHeightSpec,
                     lp.topMargin + lp.bottomMargin, lp.height);
             child.measure(childWidthSpec, childHeightSpec);
-            totalWidth += lp.leftMargin + lp.rightMargin + child.getMeasuredWidth();
+            if ((child == mExpandButton && mShowExpandButtonAtEnd)
+                    || child == mProfileBadge
+                    || child == mAppOps) {
+                iconWidth += lp.leftMargin + lp.rightMargin + child.getMeasuredWidth();
+            } else {
+                totalWidth += lp.leftMargin + lp.rightMargin + child.getMeasuredWidth();
+            }
         }
-        if (totalWidth > givenWidth) {
-            int overFlow = totalWidth - givenWidth;
+
+        // Ensure that there is at least enough space for the icons
+        int endMargin = Math.max(mHeaderTextMarginEnd, iconWidth);
+        if (totalWidth > givenWidth - endMargin) {
+            int overFlow = totalWidth - givenWidth + endMargin;
             // We are overflowing, lets shrink the app name first
             overFlow = shrinkViewForOverflow(wrapContentHeightSpec, overFlow, mAppName,
                     mChildMinWidth);
@@ -161,6 +172,7 @@
             shrinkViewForOverflow(wrapContentHeightSpec, overFlow, mSecondaryHeaderText,
                     0);
         }
+        totalWidth += getPaddingEnd();
         mTotalWidth = Math.min(totalWidth, givenWidth);
         setMeasuredDimension(givenWidth, givenHeight);
     }
@@ -383,6 +395,26 @@
         return mIcon;
     }
 
+    /**
+     * Sets the margin end for the text portion of the header, excluding right-aligned elements
+     * @param headerTextMarginEnd margin size
+     */
+    @RemotableViewMethod
+    public void setHeaderTextMarginEnd(int headerTextMarginEnd) {
+        if (mHeaderTextMarginEnd != headerTextMarginEnd) {
+            mHeaderTextMarginEnd = headerTextMarginEnd;
+            requestLayout();
+        }
+    }
+
+    /**
+     * Get the current margin end value for the header text
+     * @return margin size
+     */
+    public int getHeaderTextMarginEnd() {
+        return mHeaderTextMarginEnd;
+    }
+
     public class HeaderTouchListener implements View.OnTouchListener {
 
         private final ArrayList<Rect> mTouchRects = new ArrayList<>();
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 287365f7..a9965b0 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -5803,6 +5803,11 @@
                         setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
                     }
                     break;
+                case R.styleable.View_importantForContentCapture:
+                    if (a.peekValue(attr) != null) {
+                        setImportantForContentCapture(a.getInt(attr,
+                                IMPORTANT_FOR_CONTENT_CAPTURE_AUTO));
+                    }
                 case R.styleable.View_defaultFocusHighlightEnabled:
                     if (a.peekValue(attr) != null) {
                         setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
diff --git a/core/java/android/view/accessibility/AccessibilityCache.java b/core/java/android/view/accessibility/AccessibilityCache.java
index 5d59e42..df8690d 100644
--- a/core/java/android/view/accessibility/AccessibilityCache.java
+++ b/core/java/android/view/accessibility/AccessibilityCache.java
@@ -360,7 +360,7 @@
             }
             clearWindowCache();
             final int nodesForWindowCount = mNodeCache.size();
-            for (int i = 0; i < nodesForWindowCount; i++) {
+            for (int i = nodesForWindowCount - 1; i >= 0; i--) {
                 final int windowId = mNodeCache.keyAt(i);
                 clearNodesForWindowLocked(windowId);
             }
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 70fe230..0c0a555 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -1827,22 +1827,6 @@
     }
 
     /**
-     * @deprecated use {@link #setAugmentedAutofillWhitelist(Set, Set)} instead.
-     * @hide
-     */
-    @SystemApi
-    @TestApi
-    @Deprecated
-    public void setAugmentedAutofillWhitelist(@Nullable List<String> packages,
-            @Nullable List<ComponentName> activities) {
-        setAugmentedAutofillWhitelist(toSet(packages), toSet(activities));
-    }
-
-    private <T> ArraySet<T> toSet(@Nullable List<T> set) {
-        return set == null ? null : new ArraySet<T>(set);
-    }
-
-    /**
      * Explicitly limits augmented autofill to the given packages and activities.
      *
      * <p>To reset the whitelist, call it passing {@code null} to both arguments.
diff --git a/core/java/com/android/internal/widget/MediaNotificationView.java b/core/java/com/android/internal/widget/MediaNotificationView.java
index 498bc5a..de86d92 100644
--- a/core/java/com/android/internal/widget/MediaNotificationView.java
+++ b/core/java/com/android/internal/widget/MediaNotificationView.java
@@ -19,6 +19,7 @@
 import android.annotation.Nullable;
 import android.content.Context;
 import android.util.AttributeSet;
+import android.view.NotificationHeaderView;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
@@ -37,7 +38,7 @@
     private final int mNotificationContentImageMarginEnd;
     private ImageView mRightIcon;
     private View mActions;
-    private View mHeader;
+    private NotificationHeaderView mHeader;
     private View mMainColumn;
     private View mMediaContent;
     private int mImagePushIn;
@@ -94,7 +95,14 @@
                 mMainColumn.setLayoutParams(params);
                 reMeasure = true;
             }
-            int headerMarginEnd = size + imageEndMargin;
+            // margin for the entire header line
+            int headerMarginEnd = imageEndMargin;
+            // margin for the header text (not including the expand button and other icons)
+            int headerTextMarginEnd = size + imageEndMargin;
+            if (headerTextMarginEnd != mHeader.getHeaderTextMarginEnd()) {
+                mHeader.setHeaderTextMarginEnd(headerTextMarginEnd);
+                reMeasure = true;
+            }
             params = (MarginLayoutParams) mHeader.getLayoutParams();
             if (params.getMarginEnd() != headerMarginEnd) {
                 params.setMarginEnd(headerMarginEnd);
diff --git a/core/res/res/anim/lock_scanning.xml b/core/res/res/anim/lock_scanning.xml
new file mode 100644
index 0000000..36d8f88
--- /dev/null
+++ b/core/res/res/anim/lock_scanning.xml
@@ -0,0 +1,371 @@
+<!--
+     Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+                 xmlns:aapt="http://schemas.android.com/aapt">
+    <aapt:attr name="android:drawable">
+        <vector android:height="32dp" android:width="32dp" android:viewportHeight="32"
+                android:viewportWidth="32">
+            <group android:name="_R_G">
+                <group android:name="_R_G_L_2_G_N_1_T_0" android:pivotX="16" android:pivotY="16"
+                       android:scaleX="1.5" android:scaleY="1.5">
+                    <group android:name="_R_G_L_2_G" android:translateX="7.75"
+                           android:translateY="10.670000000000002" android:pivotX="8.25"
+                           android:pivotY="7.25" android:scaleX="0.64" android:scaleY="0.64">
+                        <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="?attr/textColor"
+                              android:fillAlpha="1" android:fillType="nonZero"
+                              android:pathData=" M14.25 0.25 C14.25,0.25 12.75,0.25 12.75,0.25 C12.75,0.25 10.75,0.25 10.75,0.25 C10.75,0.25 5.75,0.25 5.75,0.25 C5.75,0.25 3.75,0.25 3.75,0.25 C3.75,0.25 2.25,0.25 2.25,0.25 C1.15,0.25 0.25,1.15 0.25,2.25 C0.25,2.25 0.25,12.25 0.25,12.25 C0.25,13.35 1.15,14.25 2.25,14.25 C2.25,14.25 14.25,14.25 14.25,14.25 C15.35,14.25 16.25,13.35 16.25,12.25 C16.25,12.25 16.25,2.25 16.25,2.25 C16.25,1.15 15.35,0.25 14.25,0.25c  M14.25 12.25 C14.25,12.25 2.25,12.25 2.25,12.25 C2.25,12.25 2.25,2.25 2.25,2.25 C2.25,2.25 3.75,2.25 3.75,2.25 C3.75,2.25 12.75,2.25 12.75,2.25 C12.75,2.25 14.25,2.25 14.25,2.25 C14.25,2.25 14.25,12.25 14.25,12.25c "/>
+                    </group>
+                </group>
+                <group android:name="_R_G_L_1_G_N_4_N_1_T_0" android:pivotX="16" android:pivotY="16"
+                       android:scaleX="1.5" android:scaleY="1.5">
+                    <group android:name="_R_G_L_1_G_N_4_T_0" android:translateX="7.75"
+                           android:translateY="10.670000000000002" android:pivotX="8.25"
+                           android:pivotY="7.25" android:scaleX="0.64" android:scaleY="0.64">
+                        <group android:name="_R_G_L_1_G" android:translateX="6"
+                               android:translateY="5" android:pivotX="2.25" android:pivotY="2.25"
+                               android:scaleX="1" android:scaleY="1">
+                            <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="?attr/textColor"
+                                  android:fillAlpha="1" android:fillType="nonZero"
+                                  android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c "/>
+                        </group>
+                    </group>
+                </group>
+                <group android:name="_R_G_L_0_G_N_4_N_1_T_0" android:pivotX="16" android:pivotY="16"
+                       android:scaleX="1.5" android:scaleY="1.5">
+                    <group android:name="_R_G_L_0_G_N_4_T_0" android:translateX="7.75"
+                           android:translateY="10.670000000000002" android:pivotX="8.25"
+                           android:pivotY="7.25" android:scaleX="0.64" android:scaleY="0.64">
+                        <group android:name="_R_G_L_0_G_T_1" android:translateX="8.25"
+                               android:translateY="1.121" android:scaleX="0.125"
+                               android:scaleY="0.125">
+                            <group android:name="_R_G_L_0_G" android:translateY="25.029">
+                                <path android:name="_R_G_L_0_G_D_0_P_0"
+                                      android:strokeColor="?attr/textColor" android:strokeLineCap="round"
+                                      android:strokeLineJoin="round" android:strokeWidth="16"
+                                      android:strokeAlpha="1"
+                                      android:pathData=" M-28.21 -25.03 C-28.21,-25.03 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.93,-26.15 27.93,-26.15 "/>
+                            </group>
+                        </group>
+                    </group>
+                </group>
+            </group>
+            <group android:name="time_group"/>
+        </vector>
+    </aapt:attr>
+    <target android:name="_R_G_L_2_G">
+        <aapt:attr name="android:animation">
+            <set android:ordering="together">
+                <objectAnimator android:propertyName="scaleX" android:duration="83"
+                                android:startOffset="0" android:valueFrom="0.64"
+                                android:valueTo="0.64" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="scaleY" android:duration="83"
+                                android:startOffset="0" android:valueFrom="0.64"
+                                android:valueTo="0.64" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="scaleX" android:duration="83"
+                                android:startOffset="83" android:valueFrom="0.64"
+                                android:valueTo="0.62" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="scaleY" android:duration="83"
+                                android:startOffset="83" android:valueFrom="0.64"
+                                android:valueTo="0.62" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="scaleX" android:duration="183"
+                                android:startOffset="167" android:valueFrom="0.62"
+                                android:valueTo="0.8" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="scaleY" android:duration="183"
+                                android:startOffset="167" android:valueFrom="0.62"
+                                android:valueTo="0.8" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="scaleX" android:duration="250"
+                                android:startOffset="350" android:valueFrom="0.8"
+                                android:valueTo="0.64" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="scaleY" android:duration="250"
+                                android:startOffset="350" android:valueFrom="0.8"
+                                android:valueTo="0.64" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+            </set>
+        </aapt:attr>
+    </target>
+    <target android:name="_R_G_L_1_G">
+        <aapt:attr name="android:animation">
+            <set android:ordering="together">
+                <objectAnimator android:propertyName="scaleX" android:duration="150"
+                                android:startOffset="0" android:valueFrom="1" android:valueTo="1"
+                                android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="scaleY" android:duration="150"
+                                android:startOffset="0" android:valueFrom="1" android:valueTo="1"
+                                android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="scaleX" android:duration="117"
+                                android:startOffset="150" android:valueFrom="1"
+                                android:valueTo="0.6" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="scaleY" android:duration="117"
+                                android:startOffset="150" android:valueFrom="1"
+                                android:valueTo="0.6" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="scaleX" android:duration="333"
+                                android:startOffset="267" android:valueFrom="0.6"
+                                android:valueTo="1" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="scaleY" android:duration="333"
+                                android:startOffset="267" android:valueFrom="0.6"
+                                android:valueTo="1" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+            </set>
+        </aapt:attr>
+    </target>
+    <target android:name="_R_G_L_1_G_N_4_T_0">
+        <aapt:attr name="android:animation">
+            <set android:ordering="together">
+                <objectAnimator android:propertyName="scaleX" android:duration="83"
+                                android:startOffset="0" android:valueFrom="0.64"
+                                android:valueTo="0.64" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="scaleY" android:duration="83"
+                                android:startOffset="0" android:valueFrom="0.64"
+                                android:valueTo="0.64" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="scaleX" android:duration="83"
+                                android:startOffset="83" android:valueFrom="0.64"
+                                android:valueTo="0.62" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="scaleY" android:duration="83"
+                                android:startOffset="83" android:valueFrom="0.64"
+                                android:valueTo="0.62" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="scaleX" android:duration="183"
+                                android:startOffset="167" android:valueFrom="0.62"
+                                android:valueTo="0.8" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="scaleY" android:duration="183"
+                                android:startOffset="167" android:valueFrom="0.62"
+                                android:valueTo="0.8" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="scaleX" android:duration="250"
+                                android:startOffset="350" android:valueFrom="0.8"
+                                android:valueTo="0.64" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="scaleY" android:duration="250"
+                                android:startOffset="350" android:valueFrom="0.8"
+                                android:valueTo="0.64" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+            </set>
+        </aapt:attr>
+    </target>
+    <target android:name="_R_G_L_0_G_D_0_P_0">
+        <aapt:attr name="android:animation">
+            <set android:ordering="together">
+                <objectAnimator android:propertyName="pathData" android:duration="83"
+                                android:startOffset="0"
+                                android:valueFrom="M-28.21 -25.03 C-28.21,-25.03 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.93,-26.15 27.93,-26.15 "
+                                android:valueTo="M-28.21 -25.03 C-28.21,-25.03 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.93,-26.15 27.93,-26.15 "
+                                android:valueType="pathType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="pathData" android:duration="150"
+                                android:startOffset="83"
+                                android:valueFrom="M-28.21 -25.03 C-28.21,-25.03 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.93,-26.15 27.93,-26.15 "
+                                android:valueTo="M-28.02 -43.42 C-28.02,-43.42 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.76,-43.67 27.76,-43.67 "
+                                android:valueType="pathType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="pathData" android:duration="117"
+                                android:startOffset="233"
+                                android:valueFrom="M-28.02 -43.42 C-28.02,-43.42 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.76,-43.67 27.76,-43.67 "
+                                android:valueTo="M-28.21 -25.03 C-28.21,-25.03 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.93,-26.15 27.93,-26.15 "
+                                android:valueType="pathType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+            </set>
+        </aapt:attr>
+    </target>
+    <target android:name="_R_G_L_0_G_T_1">
+        <aapt:attr name="android:animation">
+            <set android:ordering="together">
+                <objectAnimator android:propertyName="translateY" android:duration="83"
+                                android:startOffset="0" android:valueFrom="1.121"
+                                android:valueTo="1.121" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="translateY" android:duration="150"
+                                android:startOffset="83" android:valueFrom="1.121"
+                                android:valueTo="3.749" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="translateY" android:duration="117"
+                                android:startOffset="233" android:valueFrom="3.749"
+                                android:valueTo="1.121" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+            </set>
+        </aapt:attr>
+    </target>
+    <target android:name="_R_G_L_0_G_N_4_T_0">
+        <aapt:attr name="android:animation">
+            <set android:ordering="together">
+                <objectAnimator android:propertyName="scaleX" android:duration="83"
+                                android:startOffset="0" android:valueFrom="0.64"
+                                android:valueTo="0.64" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="scaleY" android:duration="83"
+                                android:startOffset="0" android:valueFrom="0.64"
+                                android:valueTo="0.64" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="scaleX" android:duration="83"
+                                android:startOffset="83" android:valueFrom="0.64"
+                                android:valueTo="0.62" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="scaleY" android:duration="83"
+                                android:startOffset="83" android:valueFrom="0.64"
+                                android:valueTo="0.62" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="scaleX" android:duration="183"
+                                android:startOffset="167" android:valueFrom="0.62"
+                                android:valueTo="0.8" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="scaleY" android:duration="183"
+                                android:startOffset="167" android:valueFrom="0.62"
+                                android:valueTo="0.8" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="scaleX" android:duration="250"
+                                android:startOffset="350" android:valueFrom="0.8"
+                                android:valueTo="0.64" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="scaleY" android:duration="250"
+                                android:startOffset="350" android:valueFrom="0.8"
+                                android:valueTo="0.64" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+            </set>
+        </aapt:attr>
+    </target>
+    <target android:name="time_group">
+        <aapt:attr name="android:animation">
+            <set android:ordering="together">
+                <objectAnimator android:propertyName="translateX" android:duration="1000"
+                                android:startOffset="0" android:valueFrom="0" android:valueTo="1"
+                                android:valueType="floatType"/>
+            </set>
+        </aapt:attr>
+    </target>
+</animated-vector>
\ No newline at end of file
diff --git a/core/res/res/anim/lock_to_error.xml b/core/res/res/anim/lock_to_error.xml
index 29b4964..4aad742 100755
--- a/core/res/res/anim/lock_to_error.xml
+++ b/core/res/res/anim/lock_to_error.xml
@@ -14,545 +14,174 @@
      limitations under the License.
 -->
 <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:aapt="http://schemas.android.com/aapt">
+                 xmlns:aapt="http://schemas.android.com/aapt">
     <aapt:attr name="android:drawable">
-        <vector
-            android:width="24dp"
-            android:height="24dp"
-            android:viewportWidth="24"
-            android:viewportHeight="24">
+        <vector android:height="32dp" android:width="32dp" android:viewportHeight="32"
+                android:viewportWidth="32">
             <group android:name="_R_G">
-                <group
-                    android:name="_R_G_L_3_G"
-                    android:pivotY="-32"
-                    android:scaleX="0.12762"
-                    android:scaleY="0.12762"
-                    android:translateX="12"
-                    android:translateY="39.871">
-                    <path
-                        android:name="_R_G_L_3_G_D_0_P_0"
-                        android:fillAlpha="0"
-                        android:fillColor="#ff0000"
-                        android:fillType="nonZero"
-                        android:pathData=" M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "
-                        android:trimPathStart="0"
-                        android:trimPathEnd="1"
-                        android:trimPathOffset="0" />
-                    <path
-                        android:name="_R_G_L_3_G_D_1_P_0"
-                        android:pathData=" M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "
-                        android:strokeWidth="16"
-                        android:strokeAlpha="1"
-                        android:strokeColor="?attr/textColor"
-                        android:trimPathStart="0"
-                        android:trimPathEnd="1"
-                        android:trimPathOffset="0" />
-                </group>
-                <group
-                    android:name="_R_G_L_2_G_T_1"
-                    android:rotation="45"
-                    android:scaleX="1"
-                    android:scaleY="1"
-                    android:translateX="12"
-                    android:translateY="15">
-                    <group
-                        android:name="_R_G_L_2_G"
-                        android:translateX="-2.25"
-                        android:translateY="-2.25">
-                        <path
-                            android:name="_R_G_L_2_G_D_0_P_0"
-                            android:fillAlpha="1"
-                            android:fillColor="?attr/textColor"
-                            android:fillType="nonZero"
-                            android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c " />
+                <group android:name="_R_G_L_2_G_N_1_T_0" android:pivotX="16" android:pivotY="16"
+                       android:scaleX="1.5" android:scaleY="1.5">
+                    <group android:name="_R_G_L_2_G" android:translateX="7.75"
+                           android:translateY="10.670000000000002" android:pivotX="8.25"
+                           android:pivotY="7.25" android:rotation="0" android:scaleX="0.64"
+                           android:scaleY="0.64">
+                        <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="?attr/textColor"
+                              android:fillAlpha="1" android:fillType="nonZero"
+                              android:pathData=" M14.25 0.25 C14.25,0.25 12.75,0.25 12.75,0.25 C12.75,0.25 10.75,0.25 10.75,0.25 C10.75,0.25 5.75,0.25 5.75,0.25 C5.75,0.25 3.75,0.25 3.75,0.25 C3.75,0.25 2.25,0.25 2.25,0.25 C1.15,0.25 0.25,1.15 0.25,2.25 C0.25,2.25 0.25,12.25 0.25,12.25 C0.25,13.35 1.15,14.25 2.25,14.25 C2.25,14.25 14.25,14.25 14.25,14.25 C15.35,14.25 16.25,13.35 16.25,12.25 C16.25,12.25 16.25,2.25 16.25,2.25 C16.25,1.15 15.35,0.25 14.25,0.25c  M14.25 12.25 C14.25,12.25 2.25,12.25 2.25,12.25 C2.25,12.25 2.25,2.25 2.25,2.25 C2.25,2.25 3.75,2.25 3.75,2.25 C3.75,2.25 12.75,2.25 12.75,2.25 C12.75,2.25 14.25,2.25 14.25,2.25 C14.25,2.25 14.25,12.25 14.25,12.25c "/>
                     </group>
                 </group>
-                <group
-                    android:name="_R_G_L_1_G_T_1"
-                    android:scaleX="0.125"
-                    android:scaleY="0.125"
-                    android:translateX="12.023"
-                    android:translateY="1.281">
-                    <group
-                        android:name="_R_G_L_1_G"
-                        android:translateX="0.317"
-                        android:translateY="45.25">
-                        <path
-                            android:name="_R_G_L_1_G_D_0_P_0"
-                            android:fillAlpha="0"
-                            android:fillColor="#EA4335"
-                            android:fillType="nonZero"
-                            android:pathData=" M4.21 -42.01 C4.21,-42.01 4.21,-32 4.21,-32 C4.21,-32 -5.25,-32 -5.25,-32 C-5.25,-32 -5.25,-42.01 -5.25,-42.01 C-5.25,-42.01 4.21,-42.01 4.21,-42.01c " />
+                <group android:name="_R_G_L_1_G_N_4_N_1_T_0" android:pivotX="16" android:pivotY="16"
+                       android:scaleX="1.5" android:scaleY="1.5">
+                    <group android:name="_R_G_L_1_G_N_4_T_0" android:translateX="7.75"
+                           android:translateY="10.670000000000002" android:pivotX="8.25"
+                           android:pivotY="7.25" android:rotation="0" android:scaleX="0.64"
+                           android:scaleY="0.64">
+                        <group android:name="_R_G_L_1_G" android:translateX="6"
+                               android:translateY="5">
+                            <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="?attr/textColor"
+                                  android:fillAlpha="1" android:fillType="nonZero"
+                                  android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c "/>
+                        </group>
                     </group>
                 </group>
-                <group
-                    android:name="_R_G_L_0_G"
-                    android:pivotY="21"
-                    android:scaleX="0.14286"
-                    android:scaleY="0.14286"
-                    android:translateX="12"
-                    android:translateY="-6">
-                    <path
-                        android:name="_R_G_L_0_G_D_0_P_0"
-                        android:fillAlpha="0"
-                        android:fillColor="#ffffff"
-                        android:fillType="nonZero"
-                        android:pathData=" M49.24 -12.32 C49.24,-12.32 49.24,52.91 49.24,52.91 C49.24,58.95 44.34,63.85 38.3,63.85 C38.3,63.85 -37.8,63.85 -37.8,63.85 C-43.84,63.85 -48.74,58.95 -48.74,52.91 C-48.74,52.91 -48.74,-12.32 -48.74,-12.32 C-48.74,-18.37 -43.84,-23.27 -37.8,-23.27 C-37.8,-23.27 38.3,-23.27 38.3,-23.27 C44.34,-23.27 49.24,-18.37 49.24,-12.32c " />
-                    <path
-                        android:name="_R_G_L_0_G_D_1_P_0"
-                        android:pathData=" M49.24 -12.32 C49.24,-12.32 49.24,52.91 49.24,52.91 C49.24,58.95 44.34,63.85 38.3,63.85 C38.3,63.85 -37.8,63.85 -37.8,63.85 C-43.84,63.85 -48.74,58.95 -48.74,52.91 C-48.74,52.91 -48.74,-12.32 -48.74,-12.32 C-48.74,-18.37 -43.84,-23.27 -37.8,-23.27 C-37.8,-23.27 38.3,-23.27 38.3,-23.27 C44.34,-23.27 49.24,-18.37 49.24,-12.32c "
-                        android:strokeWidth="14"
-                        android:strokeAlpha="1"
-                        android:strokeColor="?attr/textColor"
-                        android:strokeLineCap="round"
-                        android:strokeLineJoin="round" />
+                <group android:name="_R_G_L_0_G_N_4_N_1_T_0" android:pivotX="16" android:pivotY="16"
+                       android:scaleX="1.5" android:scaleY="1.5">
+                    <group android:name="_R_G_L_0_G_N_4_T_0" android:translateX="7.75"
+                           android:translateY="10.670000000000002" android:pivotX="8.25"
+                           android:pivotY="7.25" android:rotation="0" android:scaleX="0.64"
+                           android:scaleY="0.64">
+                        <group android:name="_R_G_L_0_G" android:translateX="-16.219"
+                               android:translateY="32.25" android:pivotX="27.965"
+                               android:pivotY="-32" android:scaleX="0.125" android:scaleY="0.125">
+                            <path android:name="_R_G_L_0_G_D_0_P_0" android:strokeColor="?attr/textColor"
+                                  android:strokeLineCap="round" android:strokeLineJoin="round"
+                                  android:strokeWidth="16" android:strokeAlpha="1"
+                                  android:pathData=" M-28.21 -25.03 C-28.21,-25.03 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.93,-26.15 27.93,-26.15 "/>
+                        </group>
+                    </group>
                 </group>
             </group>
-            <group android:name="time_group" />
+            <group android:name="time_group"/>
         </vector>
     </aapt:attr>
-    <target android:name="_R_G_L_3_G_D_0_P_0">
+    <target android:name="_R_G_L_2_G">
         <aapt:attr name="android:animation">
             <set android:ordering="together">
-                <objectAnimator
-                    android:duration="250"
-                    android:propertyName="trimPathStart"
-                    android:startOffset="0"
-                    android:valueFrom="0"
-                    android:valueTo="0.5"
-                    android:valueType="floatType">
+                <objectAnimator android:propertyName="rotation" android:duration="133"
+                                android:startOffset="0" android:valueFrom="0" android:valueTo="0"
+                                android:valueType="floatType">
                     <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.44,0 0.601,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="rotation" android:duration="120"
+                                android:startOffset="133" android:valueFrom="0"
+                                android:valueTo="-10" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.44,0 0.601,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="rotation" android:duration="97"
+                                android:startOffset="253" android:valueFrom="-10"
+                                android:valueTo="10" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.531,0 0.389,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="rotation" android:duration="100"
+                                android:startOffset="350" android:valueFrom="10"
+                                android:valueTo="-5" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.499,0 0.489,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="rotation" android:duration="167"
+                                android:startOffset="450" android:valueFrom="-5" android:valueTo="0"
+                                android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.293,0 0.689,1 1.0,1.0"/>
                     </aapt:attr>
                 </objectAnimator>
             </set>
         </aapt:attr>
     </target>
-    <target android:name="_R_G_L_3_G_D_0_P_0">
+    <target android:name="_R_G_L_1_G_N_4_T_0">
         <aapt:attr name="android:animation">
             <set android:ordering="together">
-                <objectAnimator
-                    android:duration="250"
-                    android:propertyName="trimPathEnd"
-                    android:startOffset="0"
-                    android:valueFrom="1"
-                    android:valueTo="0.5"
-                    android:valueType="floatType">
+                <objectAnimator android:propertyName="rotation" android:duration="133"
+                                android:startOffset="0" android:valueFrom="0" android:valueTo="0"
+                                android:valueType="floatType">
                     <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.44,0 0.601,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="rotation" android:duration="120"
+                                android:startOffset="133" android:valueFrom="0"
+                                android:valueTo="-10" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.44,0 0.601,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="rotation" android:duration="97"
+                                android:startOffset="253" android:valueFrom="-10"
+                                android:valueTo="10" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.531,0 0.389,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="rotation" android:duration="100"
+                                android:startOffset="350" android:valueFrom="10"
+                                android:valueTo="-5" android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.499,0 0.489,1 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+                <objectAnimator android:propertyName="rotation" android:duration="167"
+                                android:startOffset="450" android:valueFrom="-5" android:valueTo="0"
+                                android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.293,0 0.689,1 1.0,1.0"/>
                     </aapt:attr>
                 </objectAnimator>
             </set>
         </aapt:attr>
     </target>
-    <target android:name="_R_G_L_3_G_D_1_P_0">
+    <target android:name="_R_G_L_0_G_N_4_T_0">
         <aapt:attr name="android:animation">
             <set android:ordering="together">
-                <objectAnimator
-                    android:duration="117"
-                    android:propertyName="strokeColor"
-                    android:startOffset="0"
-                    android:valueFrom="#fff"
-                    android:valueTo="#fff"
-                    android:valueType="colorType">
+                <objectAnimator android:propertyName="rotation" android:duration="133"
+                                android:startOffset="0" android:valueFrom="0" android:valueTo="0"
+                                android:valueType="floatType">
                     <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.44,0 0.601,1 1.0,1.0"/>
                     </aapt:attr>
                 </objectAnimator>
-                <objectAnimator
-                    android:duration="17"
-                    android:propertyName="strokeColor"
-                    android:startOffset="117"
-                    android:valueFrom="#fff"
-                    android:valueTo="#EA4335"
-                    android:valueType="colorType">
+                <objectAnimator android:propertyName="rotation" android:duration="120"
+                                android:startOffset="133" android:valueFrom="0"
+                                android:valueTo="-10" android:valueType="floatType">
                     <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.44,0 0.601,1 1.0,1.0"/>
                     </aapt:attr>
                 </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_3_G_D_1_P_0">
-        <aapt:attr name="android:animation">
-            <set android:ordering="together">
-                <objectAnimator
-                    android:duration="133"
-                    android:propertyName="strokeWidth"
-                    android:startOffset="0"
-                    android:valueFrom="16"
-                    android:valueTo="8"
-                    android:valueType="floatType">
+                <objectAnimator android:propertyName="rotation" android:duration="97"
+                                android:startOffset="253" android:valueFrom="-10"
+                                android:valueTo="10" android:valueType="floatType">
                     <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.531,0 0.389,1 1.0,1.0"/>
                     </aapt:attr>
                 </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_3_G_D_1_P_0">
-        <aapt:attr name="android:animation">
-            <set android:ordering="together">
-                <objectAnimator
-                    android:duration="250"
-                    android:propertyName="trimPathStart"
-                    android:startOffset="0"
-                    android:valueFrom="0"
-                    android:valueTo="0.5"
-                    android:valueType="floatType">
+                <objectAnimator android:propertyName="rotation" android:duration="100"
+                                android:startOffset="350" android:valueFrom="10"
+                                android:valueTo="-5" android:valueType="floatType">
                     <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.499,0 0.489,1 1.0,1.0"/>
                     </aapt:attr>
                 </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_3_G_D_1_P_0">
-        <aapt:attr name="android:animation">
-            <set android:ordering="together">
-                <objectAnimator
-                    android:duration="250"
-                    android:propertyName="trimPathEnd"
-                    android:startOffset="0"
-                    android:valueFrom="1"
-                    android:valueTo="0.5"
-                    android:valueType="floatType">
+                <objectAnimator android:propertyName="rotation" android:duration="167"
+                                android:startOffset="450" android:valueFrom="-5" android:valueTo="0"
+                                android:valueType="floatType">
                     <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_3_G">
-        <aapt:attr name="android:animation">
-            <set android:ordering="together">
-                <objectAnimator
-                    android:duration="0"
-                    android:propertyName="scaleY"
-                    android:startOffset="183"
-                    android:valueFrom="0.12762"
-                    android:valueTo="0"
-                    android:valueType="floatType" />
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_2_G_D_0_P_0">
-        <aapt:attr name="android:animation">
-            <set android:ordering="together">
-                <objectAnimator
-                    android:duration="117"
-                    android:propertyName="fillColor"
-                    android:startOffset="0"
-                    android:valueFrom="#fff"
-                    android:valueTo="#fff"
-                    android:valueType="colorType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="17"
-                    android:propertyName="fillColor"
-                    android:startOffset="117"
-                    android:valueFrom="#fff"
-                    android:valueTo="#EA4335"
-                    android:valueType="colorType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_2_G_D_0_P_0">
-        <aapt:attr name="android:animation">
-            <set android:ordering="together">
-                <objectAnimator
-                    android:duration="133"
-                    android:propertyName="pathData"
-                    android:startOffset="0"
-                    android:valueFrom="M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c "
-                    android:valueTo="M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c "
-                    android:valueType="pathType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0 0.833,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="133"
-                    android:propertyName="pathData"
-                    android:startOffset="133"
-                    android:valueFrom="M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c "
-                    android:valueTo="M2.25 0.25 C2.25,0.25 4.25,2.25 4.25,2.25 C4.25,2.25 2.25,4.25 2.25,4.25 C2.25,4.25 0.25,2.25 0.25,2.25 C0.25,2.25 2.25,0.25 2.25,0.25c "
-                    android:valueType="pathType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_2_G_T_1">
-        <aapt:attr name="android:animation">
-            <set android:ordering="together">
-                <objectAnimator
-                    android:duration="17"
-                    android:pathData="M 12,15C 12,15.171875 12,14.828125 12,15"
-                    android:propertyName="translateXY"
-                    android:propertyXName="translateX"
-                    android:propertyYName="translateY"
-                    android:startOffset="0">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="333"
-                    android:pathData="M 12,15C 12,15.171875 12,15.859124999999999 12,16.031"
-                    android:propertyName="translateXY"
-                    android:propertyXName="translateX"
-                    android:propertyYName="translateY"
-                    android:startOffset="17">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_2_G_T_1">
-        <aapt:attr name="android:animation">
-            <set android:ordering="together">
-                <objectAnimator
-                    android:duration="17"
-                    android:propertyName="scaleX"
-                    android:startOffset="0"
-                    android:valueFrom="1"
-                    android:valueTo="1"
-                    android:valueType="floatType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="17"
-                    android:propertyName="scaleY"
-                    android:startOffset="0"
-                    android:valueFrom="1"
-                    android:valueTo="1"
-                    android:valueType="floatType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="333"
-                    android:propertyName="scaleX"
-                    android:startOffset="17"
-                    android:valueFrom="1"
-                    android:valueTo="0.4325"
-                    android:valueType="floatType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="333"
-                    android:propertyName="scaleY"
-                    android:startOffset="17"
-                    android:valueFrom="1"
-                    android:valueTo="0.4325"
-                    android:valueType="floatType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_1_G_D_0_P_0">
-        <aapt:attr name="android:animation">
-            <set android:ordering="together">
-                <objectAnimator
-                    android:duration="150"
-                    android:propertyName="fillAlpha"
-                    android:startOffset="0"
-                    android:valueFrom="0"
-                    android:valueTo="0"
-                    android:valueType="floatType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="17"
-                    android:propertyName="fillAlpha"
-                    android:startOffset="150"
-                    android:valueFrom="0"
-                    android:valueTo="1"
-                    android:valueType="floatType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_1_G_D_0_P_0">
-        <aapt:attr name="android:animation">
-            <set android:ordering="together">
-                <objectAnimator
-                    android:duration="167"
-                    android:propertyName="pathData"
-                    android:startOffset="0"
-                    android:valueFrom="M4.21 -42.01 C4.21,-42.01 4.21,-32 4.21,-32 C4.21,-32 -5.25,-32 -5.25,-32 C-5.25,-32 -5.25,-42.01 -5.25,-42.01 C-5.25,-42.01 4.21,-42.01 4.21,-42.01c "
-                    android:valueTo="M4.21 -42.01 C4.21,-42.01 4.21,-32 4.21,-32 C4.21,-32 -5.25,-32 -5.25,-32 C-5.25,-32 -5.25,-42.01 -5.25,-42.01 C-5.25,-42.01 4.21,-42.01 4.21,-42.01c "
-                    android:valueType="pathType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="183"
-                    android:propertyName="pathData"
-                    android:startOffset="167"
-                    android:valueFrom="M4.21 -42.01 C4.21,-42.01 4.21,-32 4.21,-32 C4.21,-32 -5.25,-32 -5.25,-32 C-5.25,-32 -5.25,-42.01 -5.25,-42.01 C-5.25,-42.01 4.21,-42.01 4.21,-42.01c "
-                    android:valueTo="M4.21 -42.01 C4.21,-42.01 4.16,33 4.16,33 C4.16,33 -5.3,33 -5.3,33 C-5.3,33 -5.25,-42.01 -5.25,-42.01 C-5.25,-42.01 4.21,-42.01 4.21,-42.01c "
-                    android:valueType="pathType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="50"
-                    android:propertyName="pathData"
-                    android:startOffset="350"
-                    android:valueFrom="M4.21 -42.01 C4.21,-42.01 4.16,33 4.16,33 C4.16,33 -5.3,33 -5.3,33 C-5.3,33 -5.25,-42.01 -5.25,-42.01 C-5.25,-42.01 4.21,-42.01 4.21,-42.01c "
-                    android:valueTo="M4.21 -42.01 C4.21,-42.01 4.19,30.81 4.19,30.81 C4.19,30.81 -5.27,30.81 -5.27,30.81 C-5.27,30.81 -5.25,-42.01 -5.25,-42.01 C-5.25,-42.01 4.21,-42.01 4.21,-42.01c "
-                    android:valueType="pathType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_1_G_T_1">
-        <aapt:attr name="android:animation">
-            <set android:ordering="together">
-                <objectAnimator
-                    android:duration="167"
-                    android:pathData="M 12.023,1.281C 12.023,1.656 12.023,0.9059999999999999 12.023,1.281"
-                    android:propertyName="translateXY"
-                    android:propertyXName="translateX"
-                    android:propertyYName="translateY"
-                    android:startOffset="0">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="183"
-                    android:pathData="M 12.023,1.281C 12.023,1.656 12.023,3.156 12.023,3.531"
-                    android:propertyName="translateXY"
-                    android:propertyXName="translateX"
-                    android:propertyYName="translateY"
-                    android:startOffset="167">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_1_G_T_1">
-        <aapt:attr name="android:animation">
-            <set android:ordering="together">
-                <objectAnimator
-                    android:duration="0"
-                    android:propertyName="scaleX"
-                    android:startOffset="167"
-                    android:valueFrom="0"
-                    android:valueTo="0.125"
-                    android:valueType="floatType" />
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_0_G_D_0_P_0">
-        <aapt:attr name="android:animation">
-            <set android:ordering="together">
-                <objectAnimator
-                    android:duration="267"
-                    android:propertyName="pathData"
-                    android:startOffset="0"
-                    android:valueFrom="M49.24 -12.32 C49.24,-12.32 49.24,52.91 49.24,52.91 C49.24,58.95 44.34,63.85 38.3,63.85 C38.3,63.85 -37.8,63.85 -37.8,63.85 C-43.84,63.85 -48.74,58.95 -48.74,52.91 C-48.74,52.91 -48.74,-12.32 -48.74,-12.32 C-48.74,-18.37 -43.84,-23.27 -37.8,-23.27 C-37.8,-23.27 38.3,-23.27 38.3,-23.27 C44.34,-23.27 49.24,-18.37 49.24,-12.32c "
-                    android:valueTo="M75.1 -1.1 C75.1,19.57 66.72,38.28 53.18,51.83 C39.63,65.37 20.92,73.75 0.25,73.75 C-20.42,73.75 -39.13,65.37 -52.68,51.83 C-66.22,38.28 -74.6,19.57 -74.6,-1.1 C-74.6,-21.77 -66.22,-40.48 -52.68,-54.02 C-39.13,-67.57 -20.42,-75.95 0.25,-75.95 C20.92,-75.95 39.63,-67.57 53.18,-54.02 C66.72,-40.48 75.1,-21.77 75.1,-1.1c "
-                    android:valueType="pathType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_0_G_D_1_P_0">
-        <aapt:attr name="android:animation">
-            <set android:ordering="together">
-                <objectAnimator
-                    android:duration="117"
-                    android:propertyName="strokeColor"
-                    android:startOffset="0"
-                    android:valueFrom="#fff"
-                    android:valueTo="#fff"
-                    android:valueType="colorType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="17"
-                    android:propertyName="strokeColor"
-                    android:startOffset="117"
-                    android:valueFrom="#fff"
-                    android:valueTo="#EA4335"
-                    android:valueType="colorType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_0_G_D_1_P_0">
-        <aapt:attr name="android:animation">
-            <set android:ordering="together">
-                <objectAnimator
-                    android:duration="267"
-                    android:propertyName="strokeWidth"
-                    android:startOffset="0"
-                    android:valueFrom="14"
-                    android:valueTo="12"
-                    android:valueType="floatType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_0_G_D_1_P_0">
-        <aapt:attr name="android:animation">
-            <set android:ordering="together">
-                <objectAnimator
-                    android:duration="267"
-                    android:propertyName="pathData"
-                    android:startOffset="0"
-                    android:valueFrom="M49.24 -12.32 C49.24,-12.32 49.24,52.91 49.24,52.91 C49.24,58.95 44.34,63.85 38.3,63.85 C38.3,63.85 -37.8,63.85 -37.8,63.85 C-43.84,63.85 -48.74,58.95 -48.74,52.91 C-48.74,52.91 -48.74,-12.32 -48.74,-12.32 C-48.74,-18.37 -43.84,-23.27 -37.8,-23.27 C-37.8,-23.27 38.3,-23.27 38.3,-23.27 C44.34,-23.27 49.24,-18.37 49.24,-12.32c "
-                    android:valueTo="M75.1 -1.1 C75.1,19.57 66.72,38.28 53.18,51.83 C39.63,65.37 20.92,73.75 0.25,73.75 C-20.42,73.75 -39.13,65.37 -52.68,51.83 C-66.22,38.28 -74.6,19.57 -74.6,-1.1 C-74.6,-21.77 -66.22,-40.48 -52.68,-54.02 C-39.13,-67.57 -20.42,-75.95 0.25,-75.95 C20.92,-75.95 39.63,-67.57 53.18,-54.02 C66.72,-40.48 75.1,-21.77 75.1,-1.1c "
-                    android:valueType="pathType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.293,0 0.689,1 1.0,1.0"/>
                     </aapt:attr>
                 </objectAnimator>
             </set>
@@ -561,13 +190,9 @@
     <target android:name="time_group">
         <aapt:attr name="android:animation">
             <set android:ordering="together">
-                <objectAnimator
-                    android:duration="1017"
-                    android:propertyName="translateX"
-                    android:startOffset="0"
-                    android:valueFrom="0"
-                    android:valueTo="1"
-                    android:valueType="floatType" />
+                <objectAnimator android:propertyName="translateX" android:duration="1000"
+                                android:startOffset="0" android:valueFrom="0" android:valueTo="1"
+                                android:valueType="floatType"/>
             </set>
         </aapt:attr>
     </target>
diff --git a/core/res/res/drawable/ic_auth_error.xml b/core/res/res/drawable/ic_auth_error.xml
deleted file mode 100644
index ea5f572..0000000
--- a/core/res/res/drawable/ic_auth_error.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<!--
-     Copyright (C) 2019 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector android:height="24dp" android:viewportHeight="60"
-        android:viewportWidth="60" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
-    <path android:fillColor="?attr/colorError" android:pathData="M28.8,37.5l2.4,0l0,2.5l-2.4,0z"/>
-    <path android:fillColor="?attr/colorError" android:pathData="M28.8,17.5l2.4,0l0,15l-2.4,0z"/>
-    <path android:fillColor="#00000000"
-          android:pathData="M30,6.2c-13.1,0 -23.7,10.6 -23.7,23.8S16.9,53.8 30,53.8c13.1,0 23.8,-10.6 23.8,-23.8S43.1,6.2 30,6.2z"
-          android:strokeColor="?android:attr/colorError" android:strokeWidth="2.5"/>
-</vector>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e01f421..13551e7 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1380,7 +1380,6 @@
   <java-symbol type="drawable" name="ic_print_error" />
   <java-symbol type="drawable" name="ic_lock_24dp" />
   <java-symbol type="drawable" name="ic_lock_open_24dp" />
-  <java-symbol type="drawable" name="ic_auth_error" />
   <java-symbol type="drawable" name="jog_dial_arrow_long_left_green" />
   <java-symbol type="drawable" name="jog_dial_arrow_long_right_red" />
   <java-symbol type="drawable" name="jog_dial_arrow_short_left_and_right" />
@@ -2248,6 +2247,7 @@
   <java-symbol type="anim" name="lock_lock" />
   <java-symbol type="anim" name="lock_unlock" />
   <java-symbol type="anim" name="lock_in" />
+  <java-symbol type="anim" name="lock_scanning" />
 
   <java-symbol type="bool" name="config_alwaysUseCdmaRssi" />
   <java-symbol type="dimen" name="status_bar_icon_size" />
diff --git a/core/tests/coretests/src/android/os/PowerManagerTest.java b/core/tests/coretests/src/android/os/PowerManagerTest.java
index 1b587dd..576ac73 100644
--- a/core/tests/coretests/src/android/os/PowerManagerTest.java
+++ b/core/tests/coretests/src/android/os/PowerManagerTest.java
@@ -41,7 +41,9 @@
     private UiDevice mUiDevice;
     private Executor mExec = Executors.newSingleThreadExecutor();
     @Mock
-    private PowerManager.ThermalStatusCallback mCallback;
+    private PowerManager.OnThermalStatusChangedListener mListener1;
+    @Mock
+    private PowerManager.OnThermalStatusChangedListener mListener2;
     private static final long CALLBACK_TIMEOUT_MILLI_SEC = 5000;
 
     /**
@@ -169,6 +171,11 @@
         // TODO: Threaded test (needs handler) to make sure timed wakelocks work too
     }
 
+    /**
+     * Confirm that we can get thermal status.
+     *
+     * @throws Exception
+     */
     @Test
     public void testGetThermalStatus() throws Exception {
         int status = 0;
@@ -179,24 +186,57 @@
         assertEquals(status, mPm.getCurrentThermalStatus());
     }
 
+    /**
+     * Confirm that we can add/remove thermal status listener.
+     *
+     * @throws Exception
+     */
     @Test
     public void testThermalStatusCallback() throws Exception {
-        mPm.registerThermalStatusCallback(mCallback, mExec);
-        verify(mCallback, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
-                .times(1)).onStatusChange(0);
-        reset(mCallback);
-        int status = 3;
+        // Initial override status is THERMAL_STATUS_NONE
+        int status = PowerManager.THERMAL_STATUS_NONE;
+        // Add listener1
+        mPm.addThermalStatusListener(mExec, mListener1);
+        verify(mListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
+                .times(1)).onThermalStatusChanged(status);
+        reset(mListener1);
+        status = PowerManager.THERMAL_STATUS_SEVERE;
         mUiDevice.executeShellCommand("cmd thermalservice override-status "
                 + Integer.toString(status));
-        verify(mCallback, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
-                .times(1)).onStatusChange(status);
-        reset(mCallback);
-        mPm.unregisterThermalStatusCallback(mCallback);
-        status = 2;
+        verify(mListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
+                .times(1)).onThermalStatusChanged(status);
+        reset(mListener1);
+        // Add listener1 again
+        try {
+            mPm.addThermalStatusListener(mListener1);
+            fail("Expected exception not thrown");
+        } catch (IllegalArgumentException expectedException) {
+        }
+        // Add listener2 on main thread.
+        mPm.addThermalStatusListener(mListener2);
+        status = PowerManager.THERMAL_STATUS_MODERATE;
         mUiDevice.executeShellCommand("cmd thermalservice override-status "
                 + Integer.toString(status));
-        verify(mCallback, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
-                .times(0)).onStatusChange(status);
-
+        verify(mListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
+                .times(1)).onThermalStatusChanged(status);
+        verify(mListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
+                .times(1)).onThermalStatusChanged(status);
+        reset(mListener1);
+        reset(mListener2);
+        // Remove listener1
+        mPm.removeThermalStatusListener(mListener1);
+        // Remove listener1 again
+        try {
+            mPm.removeThermalStatusListener(mListener1);
+            fail("Expected exception not thrown");
+        } catch (IllegalArgumentException expectedException) {
+        }
+        status = PowerManager.THERMAL_STATUS_LIGHT;
+        mUiDevice.executeShellCommand("cmd thermalservice override-status "
+                + Integer.toString(status));
+        verify(mListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
+                .times(0)).onThermalStatusChanged(status);
+        verify(mListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
+                .times(1)).onThermalStatusChanged(status);
     }
 }
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 28937a6..fbb629b 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -1984,41 +1984,45 @@
     {
         private MetricsConstants() {}
 
-        /**
-         * Key to extract the output format being recorded
-         * from the {@link AudioRecord#getMetrics} return value.
-         * The value is a String.
-         */
-        public static final String ENCODING = "android.media.audiorecord.encoding";
+        // MM_PREFIX is slightly different than TAG, used to avoid cut-n-paste errors.
+        private static final String MM_PREFIX = "android.media.audiorecord.";
 
         /**
-         * Key to extract the Source Type for this track
+         * Key to extract the audio data encoding for this track
          * from the {@link AudioRecord#getMetrics} return value.
-         * The value is a String.
+         * The value is a {@code String}.
          */
-        public static final String SOURCE = "android.media.audiorecord.source";
+        public static final String ENCODING = MM_PREFIX + "encoding";
+
+        /**
+         * Key to extract the source type for this track
+         * from the {@link AudioRecord#getMetrics} return value.
+         * The value is a {@code String}.
+         */
+        public static final String SOURCE = MM_PREFIX + "source";
 
         /**
          * Key to extract the estimated latency through the recording pipeline
          * from the {@link AudioRecord#getMetrics} return value.
          * This is in units of milliseconds.
-         * The value is an integer.
+         * The value is an {@code int}.
+         * @deprecated Not properly supported in the past.
          */
-        public static final String LATENCY = "android.media.audiorecord.latency";
+        @Deprecated
+        public static final String LATENCY = MM_PREFIX + "latency";
 
         /**
          * Key to extract the sink sample rate for this record track in Hz
          * from the {@link AudioRecord#getMetrics} return value.
-         * The value is an integer.
+         * The value is an {@code int}.
          */
-        public static final String SAMPLERATE = "android.media.audiorecord.samplerate";
+        public static final String SAMPLERATE = MM_PREFIX + "samplerate";
 
         /**
          * Key to extract the number of channels being recorded in this record track
          * from the {@link AudioRecord#getMetrics} return value.
-         * The value is an integer.
+         * The value is an {@code int}.
          */
-        public static final String CHANNELS = "android.media.audiorecord.channels";
-
+        public static final String CHANNELS = MM_PREFIX + "channels";
     }
 }
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 7cfe0dd..a15d322 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -3580,41 +3580,49 @@
     {
         private MetricsConstants() {}
 
-        /**
-         * Key to extract the Stream Type for this track
-         * from the {@link AudioTrack#getMetrics} return value.
-         * The value is a String.
-         */
-        public static final String STREAMTYPE = "android.media.audiotrack.streamtype";
+        // MM_PREFIX is slightly different than TAG, used to avoid cut-n-paste errors.
+        private static final String MM_PREFIX = "android.media.audiotrack.";
 
         /**
-         * Key to extract the Content Type for this track
+         * Key to extract the stream type for this track
          * from the {@link AudioTrack#getMetrics} return value.
-         * The value is a String.
+         * This value may not exist in API level {@link android.os.Build.VERSION_CODES#P}.
+         * The value is a {@code String}.
          */
-        public static final String CONTENTTYPE = "android.media.audiotrack.type";
+        public static final String STREAMTYPE = MM_PREFIX + "streamtype";
 
         /**
-         * Key to extract the Content Type for this track
+         * Key to extract the attribute content type for this track
          * from the {@link AudioTrack#getMetrics} return value.
-         * The value is a String.
+         * The value is a {@code String}.
          */
-        public static final String USAGE = "android.media.audiotrack.usage";
+        public static final String CONTENTTYPE = MM_PREFIX + "type";
+
+        /**
+         * Key to extract the attribute usage for this track
+         * from the {@link AudioTrack#getMetrics} return value.
+         * The value is a {@code String}.
+         */
+        public static final String USAGE = MM_PREFIX + "usage";
 
         /**
          * Key to extract the sample rate for this track in Hz
          * from the {@link AudioTrack#getMetrics} return value.
-         * The value is an integer.
+         * The value is an {@code int}.
+         * @deprecated This does not work. Use {@link AudioTrack#getSampleRate()} instead.
          */
+        @Deprecated
         public static final String SAMPLERATE = "android.media.audiorecord.samplerate";
 
         /**
-         * Key to extract the channel mask information for this track
+         * Key to extract the native channel mask information for this track
          * from the {@link AudioTrack#getMetrics} return value.
          *
-         * The value is a Long integer.
+         * The value is a {@code long}.
+         * @deprecated This does not work. Use {@link AudioTrack#getFormat()} and read from
+         * the returned format instead.
          */
+        @Deprecated
         public static final String CHANNELMASK = "android.media.audiorecord.channelmask";
-
     }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java b/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
index 43c97df..52d7e2c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
+++ b/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
@@ -195,19 +195,12 @@
     }
 
     private static String getRegularTimeRemainingShortString(Context context, long drainTimeMs) {
-        // Get the time of day we think device will die rounded to the nearest 15 min.
-        final long roundedTimeOfDayMs =
-                roundTimeToNearestThreshold(
-                        System.currentTimeMillis() + drainTimeMs,
-                        FIFTEEN_MINUTES_MILLIS);
+        // Get the time remaining rounded to the nearest 15 min
+        final long roundedTimeMs = roundTimeToNearestThreshold(drainTimeMs, FIFTEEN_MINUTES_MILLIS);
+        CharSequence timeString = StringUtil.formatElapsedTime(context, roundedTimeMs,
+                false /* withSeconds */);
 
-        // convert the time to a properly formatted string.
-        String skeleton = android.text.format.DateFormat.getTimeFormatString(context);
-        DateFormat fmt = DateFormat.getInstanceForSkeleton(skeleton);
-        Date date = Date.from(Instant.ofEpochMilli(roundedTimeOfDayMs));
-        CharSequence timeString = fmt.format(date);
-
-        return context.getString(R.string.power_discharge_by_only_short, timeString);
+        return context.getString(R.string.power_remaining_duration_only_short, timeString);
     }
 
     public static long convertUsToMs(long timeUs) {
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index 53b3a7e..d4957c9 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -85,7 +85,7 @@
         android:layout_marginBottom="@dimen/keyguard_lock_padding"
         android:src="@*android:drawable/ic_lock_24dp"
         android:contentDescription="@string/accessibility_unlock_button"
-        android:scaleType="fitCenter" />
+        android:scaleType="center" />
 
     <FrameLayout
         android:id="@+id/overlay_container"
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index bd9d3fb..7e0f3ae 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -174,7 +174,7 @@
             android:clipToPadding="false">
             <TextView
                 android:id="@+id/done"
-                android:text="@string/inline_done_button"
+                android:text="@string/inline_ok_button"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_centerVertical="true"
@@ -191,7 +191,7 @@
                 android:orientation="horizontal">
                 <TextView
                     android:id="@+id/deliver_silently"
-                    android:text="@string/inline_deliver_silently_button"
+                    android:text="@string/inline_silent_button_silent"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_centerVertical="true"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index cf1b4d1..9e9aada 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1580,6 +1580,9 @@
     <!-- Notification Inline controls: button to dismiss the blocking helper [CHAR_LIMIT=20] -->
     <string name="inline_done_button">Done</string>
 
+    <!-- Notification Inline controls: button to dismiss the blocking helper [CHAR_LIMIT=20] -->
+    <string name="inline_ok_button">OK</string>
+
     <!-- Notification Inline controls: continue receiving notifications prompt, channel level -->
     <string name="inline_keep_showing">Keep showing these notifications?</string>
 
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index 592b603..39a5842 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -355,15 +355,23 @@
         if (mBatteryPercentView != null) {
             if (mShowPercentMode == MODE_ESTIMATE && !mCharging) {
                 mBatteryController.getEstimatedTimeRemainingString((String estimate) -> {
-                    mBatteryPercentView.setText(estimate);
+                    if (estimate != null) {
+                        mBatteryPercentView.setText(estimate);
+                    } else {
+                        setPercentTextAtCurrentLevel();
+                    }
                 });
             } else {
-                mBatteryPercentView.setText(
-                        NumberFormat.getPercentInstance().format(mLevel / 100f));
+                setPercentTextAtCurrentLevel();
             }
         }
     }
 
+    private void setPercentTextAtCurrentLevel() {
+        mBatteryPercentView.setText(
+                NumberFormat.getPercentInstance().format(mLevel / 100f));
+    }
+
     private void updateShowPercent() {
         final boolean showing = mBatteryPercentView != null;
         final boolean systemSetting = 0 != Settings.System
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 603b3b9..4addbb5 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -49,6 +49,7 @@
 import android.util.Log;
 import android.util.StatsLog;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.WindowInsets;
 import android.widget.FrameLayout;
 import android.widget.ImageButton;
@@ -316,8 +317,25 @@
     /**
      * Lets activity view know it should be shown / populated.
      */
-    public void populateActivityView() {
-        mActivityView.setCallback(mStateCallback);
+    public void populateExpandedView() {
+        if (usingActivityView()) {
+            mActivityView.setCallback(mStateCallback);
+        } else {
+            // We're using notification template
+            ViewGroup parent = (ViewGroup) mNotifRow.getParent();
+            if (parent == this) {
+                // Already added
+                return;
+            } else if (parent != null) {
+                // Still in the shade... remove it
+                parent.removeView(mNotifRow);
+            }
+            if (mShowOnTop) {
+                addView(mNotifRow);
+            } else {
+                addView(mNotifRow, mUseFooter ? 0 : 1);
+            }
+        }
     }
 
     /**
@@ -376,14 +394,8 @@
         } else {
             // Hide activity view if we had it previously
             mActivityView.setVisibility(GONE);
-
-            // Use notification view
             mNotifRow = mEntry.getRow();
-            if (mShowOnTop) {
-                addView(mNotifRow);
-            } else {
-                addView(mNotifRow, mUseFooter ? 0 : 1);
-            }
+
         }
         updateView();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 4869485..8f9f1cb 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -807,7 +807,7 @@
         mExpandedViewContainer.removeAllViews();
         if (mExpandedBubble != null && mIsExpanded) {
             mExpandedViewContainer.addView(mExpandedBubble.expandedView);
-            mExpandedBubble.expandedView.populateActivityView();
+            mExpandedBubble.expandedView.populateExpandedView();
             mExpandedViewContainer.setVisibility(mIsExpanded ? VISIBLE : GONE);
         }
     }
@@ -817,8 +817,12 @@
 
         mExpandedViewContainer.setVisibility(mIsExpanded ? VISIBLE : GONE);
         if (mIsExpanded) {
+            // First update the view so that it calculates a new height (ensuring the y position
+            // calculation is correct)
+            mExpandedBubble.expandedView.updateView();
             final float y = getYPositionForExpandedView();
             mExpandedViewContainer.setTranslationY(y);
+            // Then update the view so that ActivityView knows we translated
             mExpandedBubble.expandedView.updateView();
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 6a8c19a..08cf606 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -15,7 +15,6 @@
 package com.android.systemui.qs;
 
 import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS;
-import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
 
 import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
 
@@ -31,15 +30,12 @@
 import android.content.IntentFilter;
 import android.content.res.Configuration;
 import android.content.res.Resources;
-import android.database.ContentObserver;
 import android.graphics.Color;
 import android.graphics.Rect;
 import android.media.AudioManager;
-import android.net.Uri;
 import android.os.Handler;
 import android.os.Looper;
 import android.provider.AlarmClock;
-import android.provider.Settings;
 import android.service.notification.ZenModeConfig;
 import android.text.format.DateUtils;
 import android.util.AttributeSet;
@@ -75,7 +71,6 @@
 import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager;
 import com.android.systemui.statusbar.phone.StatusIconContainer;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
-import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.Clock;
 import com.android.systemui.statusbar.policy.DateView;
 import com.android.systemui.statusbar.policy.NextAlarmController;
@@ -107,7 +102,6 @@
     public static final int MAX_TOOLTIP_SHOWN_COUNT = 2;
 
     private final Handler mHandler = new Handler();
-    private final BatteryController mBatteryController;
     private final NextAlarmController mAlarmController;
     private final ZenModeController mZenController;
     private final StatusBarIconController mStatusBarIconController;
@@ -162,9 +156,6 @@
     };
     private boolean mHasTopCutout = false;
 
-    private final PercentSettingObserver mPercentSettingObserver =
-            new PercentSettingObserver(new Handler(mContext.getMainLooper()));
-
     /**
      * Runnable for automatically fading out the long press tooltip (as if it were animating away).
      */
@@ -181,12 +172,11 @@
     @Inject
     public QuickStatusBarHeader(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
             NextAlarmController nextAlarmController, ZenModeController zenModeController,
-            BatteryController batteryController, StatusBarIconController statusBarIconController,
+            StatusBarIconController statusBarIconController,
             ActivityStarter activityStarter, PrivacyItemController privacyItemController) {
         super(context, attrs);
         mAlarmController = nextAlarmController;
         mZenController = zenModeController;
-        mBatteryController = batteryController;
         mStatusBarIconController = statusBarIconController;
         mActivityStarter = activityStarter;
         mPrivacyItemController = privacyItemController;
@@ -241,7 +231,9 @@
         mBatteryRemainingIcon = findViewById(R.id.batteryRemainingIcon);
         // Don't need to worry about tuner settings for this icon
         mBatteryRemainingIcon.setIgnoreTunerUpdates(true);
-        updateShowPercent();
+        // QS will always show the estimate, and BatteryMeterView handles the case where
+        // it's unavailable or charging
+        mBatteryRemainingIcon.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE);
     }
 
     private List<String> getIgnoredIconSlots() {
@@ -480,9 +472,6 @@
         super.onAttachedToWindow();
         mStatusBarIconController.addIconGroup(mIconManager);
         requestApplyInsets();
-        mContext.getContentResolver().registerContentObserver(
-                Settings.System.getUriFor(SHOW_BATTERY_PERCENT), false, mPercentSettingObserver,
-                ActivityManager.getCurrentUser());
     }
 
     @Override
@@ -521,7 +510,6 @@
     public void onDetachedFromWindow() {
         setListening(false);
         mStatusBarIconController.removeIconGroup(mIconManager);
-        mContext.getContentResolver().unregisterContentObserver(mPercentSettingObserver);
         super.onDetachedFromWindow();
     }
 
@@ -743,25 +731,4 @@
             lp.rightMargin = sideMargins;
         }
     }
-
-    private void updateShowPercent() {
-        final boolean systemSetting = 0 != Settings.System
-                .getIntForUser(getContext().getContentResolver(),
-                        SHOW_BATTERY_PERCENT, 0, ActivityManager.getCurrentUser());
-
-        mBatteryRemainingIcon.setPercentShowMode(systemSetting
-                ? BatteryMeterView.MODE_ESTIMATE : BatteryMeterView.MODE_ON);
-    }
-
-    private final class PercentSettingObserver extends ContentObserver {
-        PercentSettingObserver(Handler handler) {
-            super(handler);
-        }
-
-        @Override
-        public void onChange(boolean selfChange, Uri uri) {
-            super.onChange(selfChange, uri);
-            updateShowPercent();
-        }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index a9fe3b2..dfbb32e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -581,13 +581,12 @@
             if (!updateMonitor.isUnlockingWithBiometricAllowed()) {
                 return;
             }
-            ColorStateList errorColorState = Utils.getColorError(mContext);
             if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
                 mStatusBarKeyguardViewManager.showBouncerMessage(helpString,
-                        errorColorState);
+                        mInitialTextColorState);
             } else if (updateMonitor.isScreenOn()) {
                 mLockIcon.setTransientBiometricsError(true);
-                showTransientIndication(helpString, errorColorState);
+                showTransientIndication(helpString);
                 hideTransientIndicationDelayed(TRANSIENT_BIOMETRIC_ERROR_TIMEOUT);
                 mHandler.removeMessages(MSG_CLEAR_BIOMETRIC_MSG);
                 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CLEAR_BIOMETRIC_MSG),
@@ -605,7 +604,6 @@
             if (shouldSuppressBiometricError(msgId, biometricSourceType, updateMonitor)) {
                 return;
             }
-            ColorStateList errorColorState = Utils.getColorError(mContext);
             if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
                 // When swiping up right after receiving a biometric error, the bouncer calls
                 // authenticate leading to the same message being shown again on the bouncer.
@@ -613,10 +611,10 @@
                 // generic.
                 if (mLastSuccessiveErrorMessage != msgId) {
                     mStatusBarKeyguardViewManager.showBouncerMessage(errString,
-                            errorColorState);
+                            mInitialTextColorState);
                 }
             } else if (updateMonitor.isScreenOn()) {
-                showTransientIndication(errString, errorColorState);
+                showTransientIndication(errString);
                 // We want to keep this message around in case the screen was off
                 hideTransientIndicationDelayed(HIDE_DELAY_MS);
             } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index 4690aeb..7850035 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -328,22 +328,10 @@
             if (mExpandedChild != null
                     && mExpandedWrapper.getNotificationHeader() != null) {
                 NotificationHeaderView expandedHeader = mExpandedWrapper.getNotificationHeader();
-                int expandedSize = expandedHeader.getMeasuredWidth()
-                        - expandedHeader.getPaddingEnd();
-                int collapsedSize = contractedHeader.getMeasuredWidth()
-                        - expandedHeader.getPaddingEnd();
-                if (expandedSize != collapsedSize) {
-                    int paddingEnd = contractedHeader.getMeasuredWidth() - expandedSize;
-                    contractedHeader.setPadding(
-                            contractedHeader.isLayoutRtl()
-                                    ? paddingEnd
-                                    : contractedHeader.getPaddingLeft(),
-                            contractedHeader.getPaddingTop(),
-                            contractedHeader.isLayoutRtl()
-                                    ? contractedHeader.getPaddingLeft()
-                                    : paddingEnd,
-                            contractedHeader.getPaddingBottom());
-                    contractedHeader.setShowWorkBadgeAtEnd(true);
+
+                int headerTextMargin = expandedHeader.getHeaderTextMarginEnd();
+                if (headerTextMargin != contractedHeader.getHeaderTextMarginEnd()) {
+                    contractedHeader.setHeaderTextMarginEnd(headerTextMargin);
                     return true;
                 }
             } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index 60015ef..64e76d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -43,18 +43,15 @@
 
     private static final int STATE_LOCKED = 0;
     private static final int STATE_LOCK_OPEN = 1;
-    private static final int STATE_FACE_UNLOCK = 2;
-    private static final int STATE_FINGERPRINT = 3;
-    private static final int STATE_BIOMETRICS_ERROR = 4;
+    private static final int STATE_SCANNING_FACE = 2;
+    private static final int STATE_BIOMETRICS_ERROR = 3;
 
     private int mLastState = 0;
     private boolean mTransientBiometricsError;
     private boolean mScreenOn;
     private boolean mLastScreenOn;
-    private Drawable mUserAvatarIcon;
     private final UnlockMethodCache mUnlockMethodCache;
     private AccessibilityController mAccessibilityController;
-    private boolean mHasFingerPrintState;
     private boolean mIsFaceUnlockState;
     private int mDensity;
     private boolean mPulsing;
@@ -77,7 +74,6 @@
 
     @Override
     public void onUserInfoChanged(String name, Drawable picture, String userAccount) {
-        mUserAvatarIcon = picture;
         update();
     }
 
@@ -110,10 +106,8 @@
 
     public void update(boolean force) {
         int state = getState();
-        boolean anyFingerprintState = state == STATE_FINGERPRINT
-                || state == STATE_BIOMETRICS_ERROR;
-        mIsFaceUnlockState = state == STATE_FACE_UNLOCK;
-        if (state != mLastState || mLastDozing == mDozing || mLastPulsing == mPulsing
+        mIsFaceUnlockState = state == STATE_SCANNING_FACE;
+        if (state != mLastState || mLastDozing != mDozing || mLastPulsing != mPulsing
                 || mLastScreenOn != mScreenOn || force) {
             int iconAnimRes = getAnimationResForTransition(mLastState, state, mLastPulsing,
                     mPulsing, mLastDozing, mDozing);
@@ -138,7 +132,6 @@
                     R.string.accessibility_scanning_face));
             }
 
-            mHasFingerPrintState = anyFingerprintState;
             if (animation != null && isAnim) {
                 animation.forceAnimationOnUI();
                 animation.start();
@@ -178,7 +171,10 @@
     @Override
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
-        if (mHasFingerPrintState) {
+        KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
+        boolean fingerprintRunning = updateMonitor.isFingerprintDetectionRunning();
+        boolean unlockingAllowed = updateMonitor.isUnlockingWithBiometricAllowed();
+        if (fingerprintRunning && unlockingAllowed) {
             AccessibilityNodeInfo.AccessibilityAction unlock
                     = new AccessibilityNodeInfo.AccessibilityAction(
                     AccessibilityNodeInfo.ACTION_CLICK,
@@ -201,21 +197,16 @@
     private Drawable getIconForState(int state) {
         int iconRes;
         switch (state) {
-            case STATE_FINGERPRINT:
             case STATE_LOCKED:
-            case STATE_FACE_UNLOCK:
+            // Scanning animation is a pulsing padlock. This means that the resting state is
+            // just a padlock.
+            case STATE_SCANNING_FACE:
+            // Error animation also starts and ands on the padlock.
+            case STATE_BIOMETRICS_ERROR:
                 iconRes = com.android.internal.R.drawable.ic_lock_24dp;
                 break;
             case STATE_LOCK_OPEN:
-                if (mUnlockMethodCache.isTrustManaged() && mUnlockMethodCache.isTrusted()
-                    && mUserAvatarIcon != null) {
-                    return mUserAvatarIcon;
-                } else {
-                    iconRes = com.android.internal.R.drawable.ic_lock_open_24dp;
-                }
-                break;
-            case STATE_BIOMETRICS_ERROR:
-                iconRes = com.android.internal.R.drawable.ic_auth_error;
+                iconRes = com.android.internal.R.drawable.ic_lock_open_24dp;
                 break;
             default:
                 throw new IllegalArgumentException();
@@ -224,22 +215,28 @@
         return mContext.getDrawable(iconRes);
     }
 
-    private int getAnimationResForTransition(int oldState, int newState,
+    private static int getAnimationResForTransition(int oldState, int newState,
             boolean wasPulsing, boolean pulsing,
             boolean wasDozing, boolean dozing) {
 
-        boolean isError = newState == STATE_BIOMETRICS_ERROR;
-        boolean isUnlocked = newState == STATE_LOCK_OPEN;
-        boolean isLocked = !isUnlocked;
-        boolean wasUnlocked = oldState == STATE_LOCK_OPEN;
+        // Never animate when screen is off
+        if (dozing && !pulsing) {
+            return -1;
+        }
+
+        boolean isError = oldState != STATE_BIOMETRICS_ERROR && newState == STATE_BIOMETRICS_ERROR;
+        boolean justUnlocked = oldState != STATE_LOCK_OPEN && newState == STATE_LOCK_OPEN;
+        boolean justLocked = oldState == STATE_LOCK_OPEN && newState == STATE_LOCKED;
 
         if (isError) {
             return com.android.internal.R.anim.lock_to_error;
-        } else if (isUnlocked) {
+        } else if (justUnlocked) {
             return com.android.internal.R.anim.lock_unlock;
-        } else if (wasUnlocked && isLocked && mScreenOn) {
+        } else if (justLocked) {
             return com.android.internal.R.anim.lock_lock;
-        } else if (isLocked && (!wasPulsing && pulsing || wasDozing && !dozing)) {
+        } else if (newState == STATE_SCANNING_FACE) {
+            return com.android.internal.R.anim.lock_scanning;
+        } else if (!wasPulsing && pulsing) {
             return com.android.internal.R.anim.lock_in;
         }
         return -1;
@@ -247,17 +244,13 @@
 
     private int getState() {
         KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
-        boolean fingerprintRunning = updateMonitor.isFingerprintDetectionRunning();
-        boolean unlockingAllowed = updateMonitor.isUnlockingWithBiometricAllowed();
         if (mTransientBiometricsError) {
             return STATE_BIOMETRICS_ERROR;
         } else if (mUnlockMethodCache.canSkipBouncer()) {
             return STATE_LOCK_OPEN;
         } else if (mUnlockMethodCache.isFaceUnlockRunning()
                 || updateMonitor.isFaceDetectionRunning()) {
-            return STATE_FACE_UNLOCK;
-        } else if (fingerprintRunning && unlockingAllowed) {
-            return STATE_FINGERPRINT;
+            return STATE_SCANNING_FACE;
         } else {
             return STATE_LOCKED;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
index 5e94152..111cdd2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.policy;
 
+import android.annotation.Nullable;
+
 import com.android.systemui.DemoMode;
 import com.android.systemui.Dumpable;
 import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
@@ -78,6 +80,6 @@
          * The callback
          * @param estimate the estimate
          */
-        void onBatteryRemainingEstimateRetrieved(String estimate);
+        void onBatteryRemainingEstimateRetrieved(@Nullable String estimate);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
index 3fa3e1a..273fa55 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -237,10 +237,10 @@
 
         mFetchingEstimate = true;
         Dependency.get(Dependency.BG_HANDLER).post(() -> {
-            mEstimate = mEstimates.getEstimate();
+            // Only fetch the estimate if they are enabled
+            mEstimate = mEstimates.isHybridNotificationEnabled() ? mEstimates.getEstimate() : null;
             mLastEstimateTimestamp = System.currentTimeMillis();
             mFetchingEstimate = false;
-
             Dependency.get(Dependency.MAIN_HANDLER).post(this::notifyEstimateFetchCallbacks);
         });
     }
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 b561ac1..db2be0e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
@@ -93,14 +93,28 @@
         return null;
     }
 
+    /**
+     * Adds {@code callback} to the controller. The controller will update the callback on state
+     * changes. It will immediately trigger the callback added to notify current state.
+     * @param callback
+     */
     @Override
     public void addCallback(Callback callback) {
         synchronized (mCallbacks) {
             if (callback == null || mCallbacks.contains(callback)) return;
             if (DEBUG) Log.d(TAG, "addCallback " + callback);
             mCallbacks.add(callback);
-
-            updateWifiStateListeners(!mCallbacks.isEmpty());
+            if (mWifiManager != null) {
+                if (mCallbacks.size() == 1) {
+                    mWifiManager.registerSoftApCallback(this, mMainHandler);
+                } else {
+                    // mWifiManager#registerSoftApCallback triggers a call to onNumClientsChanged
+                    // on the Main Handler. In order to always update the callback on added, we
+                    // make this call when adding callbacks after the first.
+                    mMainHandler.post(() ->
+                            callback.onHotspotChanged(isHotspotEnabled(), mNumConnectedDevices));
+                }
+            }
         }
     }
 
@@ -110,27 +124,9 @@
         if (DEBUG) Log.d(TAG, "removeCallback " + callback);
         synchronized (mCallbacks) {
             mCallbacks.remove(callback);
-            updateWifiStateListeners(!mCallbacks.isEmpty());
-        }
-    }
-
-    /**
-     * Updates the wifi state receiver to either start or stop listening to get updates to the
-     * hotspot status. Additionally starts listening to wifi manager state to track the number of
-     * connected devices.
-     *
-     * @param shouldListen whether we should start listening to various wifi statuses
-     */
-    private void updateWifiStateListeners(boolean shouldListen) {
-        if (mWifiManager == null) {
-            return;
-        }
-        if (shouldListen) {
-            mWifiManager.registerSoftApCallback(
-                    this,
-                    mMainHandler);
-        } else {
-            mWifiManager.unregisterSoftApCallback(this);
+            if (mCallbacks.isEmpty() && mWifiManager != null) {
+                mWifiManager.unregisterSoftApCallback(this);
+            }
         }
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
index 943d927..cf25a9d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
@@ -177,6 +177,7 @@
     }
 
     @Test
+    @Ignore("Occasionally flakes, ignoring pending investigation.")
     public void testChildRemoved() throws InterruptedException {
         assertEquals(0, mLayout.getTransientViewCount());
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java
new file mode 100644
index 0000000..3e4c4d6
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.policy;
+
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.net.ConnectivityManager;
+import android.net.wifi.WifiManager;
+import android.os.Handler;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class HotspotControllerImplTest extends SysuiTestCase {
+
+    @Mock
+    private ConnectivityManager mConnectivityManager;
+    @Mock
+    private WifiManager mWifiManager;
+    @Mock
+    private HotspotController.Callback mCallback1;
+    @Mock
+    private HotspotController.Callback mCallback2;
+    private HotspotControllerImpl mController;
+    private TestableLooper mLooper;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mLooper = TestableLooper.get(this);
+
+        mContext.addMockSystemService(ConnectivityManager.class, mConnectivityManager);
+        mContext.addMockSystemService(WifiManager.class, mWifiManager);
+
+        doAnswer((InvocationOnMock invocation) -> {
+            ((WifiManager.SoftApCallback) invocation.getArgument(0)).onNumClientsChanged(1);
+            return null;
+        }).when(mWifiManager).registerSoftApCallback(any(WifiManager.SoftApCallback.class),
+                any(Handler.class));
+
+        mController = new HotspotControllerImpl(mContext, new Handler(mLooper.getLooper()));
+    }
+
+    @Test
+    public void testAddingTwoCallbacksRegistersToWifiManagerOnce() {
+        mController.addCallback(mCallback1);
+        mController.addCallback(mCallback2);
+
+        verify(mWifiManager, times(1)).registerSoftApCallback(eq(mController), any());
+    }
+
+    @Test
+    public void testAddingCallbacksDoesntUpdateAll() {
+        mController.addCallback(mCallback1);
+        mController.addCallback(mCallback2);
+
+        mLooper.processAllMessages();
+        // Each callback should be updated only once
+        verify(mCallback1, times(1)).onHotspotChanged(anyBoolean(), anyInt());
+        verify(mCallback2, times(1)).onHotspotChanged(anyBoolean(), anyInt());
+    }
+
+    @Test
+    public void testRemovingTwoCallbacksUnegistersToWifiManagerOnce() {
+        mController.addCallback(mCallback1);
+        mController.addCallback(mCallback2);
+
+        mController.removeCallback(mCallback1);
+        mController.removeCallback(mCallback2);
+
+        verify(mWifiManager, times(1)).unregisterSoftApCallback(mController);
+    }
+
+    @Test
+    public void testDoNotUnregisterIfRemainingCallbacks() {
+        mController.addCallback(mCallback1);
+        mController.addCallback(mCallback2);
+
+        verify(mWifiManager, never()).unregisterSoftApCallback(any());
+    }
+
+}
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 9f7a940..52d2334 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -89,11 +89,11 @@
     private ActivityManagerInternal mAm;
 
     /**
-     * Users disabled by {@link android.provider.Settings.Secure#CONTENT_CAPTURE_ENABLED}.
+     * Users disabled by {@link android.provider.Settings.Secure#CONTENT_CAPTURE_ENABLED}
      */
     @GuardedBy("mLock")
     @Nullable
-    private SparseBooleanArray mDisabledUsers;
+    private SparseBooleanArray mDisabledBySettings;
 
     /**
      * Global kill-switch based on value defined by
@@ -130,18 +130,18 @@
             mRequestsHistory = null;
         }
 
-        // Sets which services are disabled
+        // Sets which services are disabled by settings
         final UserManager um = getContext().getSystemService(UserManager.class);
         final List<UserInfo> users = um.getUsers();
         for (int i = 0; i < users.size(); i++) {
             final int userId = users.get(i).id;
-            final boolean disabled = mDisabledByDeviceConfig || isDisabledBySettings(userId);
+            final boolean disabled = !isEnabledBySettings(userId);
             if (disabled) {
-                Slog.i(mTag, "user " + userId + " disabled by settings or device config");
-                if (mDisabledUsers == null) {
-                    mDisabledUsers = new SparseBooleanArray(1);
+                Slog.i(mTag, "user " + userId + " disabled by settings");
+                if (mDisabledBySettings == null) {
+                    mDisabledBySettings = new SparseBooleanArray(1);
                 }
-                mDisabledUsers.put(userId, true);
+                mDisabledBySettings.put(userId, true);
             }
         }
     }
@@ -187,7 +187,8 @@
     protected void onSettingsChanged(@UserIdInt int userId, @NonNull String property) {
         switch (property) {
             case Settings.Secure.CONTENT_CAPTURE_ENABLED:
-                setContentCaptureFeatureEnabledFromSettings(userId);
+                setContentCaptureFeatureEnabledBySettingsForUser(userId,
+                        isEnabledBySettings(userId));
                 return;
             default:
                 Slog.w(mTag, "Unexpected property (" + property + "); updating cache instead");
@@ -201,31 +202,13 @@
     }
 
     private boolean isDisabledBySettingsLocked(@UserIdInt int userId) {
-        return mDisabledUsers != null && mDisabledUsers.get(userId);
+        return mDisabledBySettings != null && mDisabledBySettings.get(userId);
     }
 
-    private void setContentCaptureFeatureEnabledFromSettings(@UserIdInt int userId) {
-        setContentCaptureFeatureEnabledForUser(userId, !isDisabledBySettings(userId));
-    }
-
-    private boolean isDisabledBySettings(@UserIdInt int userId) {
-        final String property = Settings.Secure.CONTENT_CAPTURE_ENABLED;
-        final String value = Settings.Secure.getStringForUser(getContext().getContentResolver(),
-                property, userId);
-        if (value == null) {
-            if (verbose) {
-                Slog.v(mTag, "isDisabledBySettings(): assuming false as '" + property
-                        + "' is not set");
-            }
-            return false;
-        }
-
-        try {
-            return !Boolean.valueOf(value);
-        } catch (Exception e) {
-            Slog.w(mTag, "Invalid value for property " + property + ": " + value);
-        }
-        return false;
+    private boolean isEnabledBySettings(@UserIdInt int userId) {
+        final boolean enabled = Settings.Secure.getIntForUser(getContext().getContentResolver(),
+                Settings.Secure.CONTENT_CAPTURE_ENABLED, 1, userId) == 1 ? true : false;
+        return enabled;
     }
 
     private void onDeviceConfigChange(@NonNull String key, @Nullable String value) {
@@ -331,12 +314,13 @@
         }
     }
 
-    private void setContentCaptureFeatureEnabledForUser(@UserIdInt int userId, boolean enabled) {
+    private void setContentCaptureFeatureEnabledBySettingsForUser(@UserIdInt int userId,
+            boolean enabled) {
         synchronized (mLock) {
-            if (mDisabledUsers == null) {
-                mDisabledUsers = new SparseBooleanArray();
+            if (mDisabledBySettings == null) {
+                mDisabledBySettings = new SparseBooleanArray();
             }
-            final boolean alreadyEnabled = !mDisabledUsers.get(userId);
+            final boolean alreadyEnabled = !mDisabledBySettings.get(userId);
             if (!(enabled ^ alreadyEnabled)) {
                 if (debug) {
                     Slog.d(mTag, "setContentCaptureFeatureEnabledForUser(): already " + enabled);
@@ -346,13 +330,14 @@
             if (enabled) {
                 Slog.i(mTag, "setContentCaptureFeatureEnabled(): enabling service for user "
                         + userId);
-                mDisabledUsers.delete(userId);
+                mDisabledBySettings.delete(userId);
             } else {
                 Slog.i(mTag, "setContentCaptureFeatureEnabled(): disabling service for user "
                         + userId);
-                mDisabledUsers.put(userId, true);
+                mDisabledBySettings.put(userId, true);
             }
-            updateCachedServiceLocked(userId, !enabled);
+            final boolean disabled = !enabled || mDisabledByDeviceConfig;
+            updateCachedServiceLocked(userId, disabled);
         }
     }
 
@@ -472,7 +457,7 @@
 
         final String prefix2 = prefix + "  ";
 
-        pw.print(prefix); pw.print("Disabled users: "); pw.println(mDisabledUsers);
+        pw.print(prefix); pw.print("Users disabled by Settings: "); pw.println(mDisabledBySettings);
         pw.print(prefix); pw.println("DeviceConfig Settings: ");
         pw.print(prefix2); pw.print("disabled: "); pw.println(mDisabledByDeviceConfig);
         pw.print(prefix2); pw.print("loggingLevel: "); pw.println(mDevCfgLoggingLevel);
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index 9df09b9..9185cb6 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -494,7 +494,7 @@
             final long token = Binder.clearCallingIdentity();
             try {
                 Settings.Secure.putStringForUser(getContext().getContentResolver(),
-                        Settings.Secure.CONTENT_CAPTURE_ENABLED, "false", mUserId);
+                        Settings.Secure.CONTENT_CAPTURE_ENABLED, "0", mUserId);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index da89116..219e046 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -3792,10 +3792,10 @@
      * if it's really needed.
      */
     @Override
-    public void getLatestTetheringEntitlementValue(int type, ResultReceiver receiver,
+    public void getLatestTetheringEntitlementResult(int type, ResultReceiver receiver,
             boolean showEntitlementUi, String callerPkg) {
         ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
-        mTethering.getLatestTetheringEntitlementValue(type, receiver, showEntitlementUi);
+        mTethering.getLatestTetheringEntitlementResult(type, receiver, showEntitlementUi);
     }
 
     // Called when we lose the default network and have no replacement yet.
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 13ff30d..3b4b6f8 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -1677,10 +1677,10 @@
     }
 
     /** Get the latest value of the tethering entitlement check. */
-    public void getLatestTetheringEntitlementValue(int type, ResultReceiver receiver,
+    public void getLatestTetheringEntitlementResult(int type, ResultReceiver receiver,
             boolean showEntitlementUi) {
         if (receiver != null) {
-            mEntitlementMgr.getLatestTetheringEntitlementValue(type, receiver, showEntitlementUi);
+            mEntitlementMgr.getLatestTetheringEntitlementResult(type, receiver, showEntitlementUi);
         }
     }
 
diff --git a/services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java b/services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java
index 75aac10..65cc516 100644
--- a/services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java
+++ b/services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java
@@ -291,7 +291,7 @@
     }
 
     /** Get the last value of the tethering entitlement check. */
-    public void getLatestTetheringEntitlementValue(int downstream, ResultReceiver receiver,
+    public void getLatestTetheringEntitlementResult(int downstream, ResultReceiver receiver,
             boolean showEntitlementUi) {
         if (!isTetherProvisioningRequired()) {
             receiver.send(TETHER_ERROR_NO_ERROR, null);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 15a00d5..b64b7c64 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -14698,14 +14698,10 @@
                                 @Override
                                 public void onReceive(Context context, Intent intent) {
                                     // the duration to wait for rollback to be enabled, in millis
-                                    long rollbackTimeout = DEFAULT_ENABLE_ROLLBACK_TIMEOUT;
-                                    try {
-                                        rollbackTimeout = Long.valueOf(
-                                            DeviceConfig.getProperty(
-                                                DeviceConfig.Rollback.NAMESPACE,
-                                                DeviceConfig.Rollback.ENABLE_ROLLBACK_TIMEOUT));
-                                    } catch (NumberFormatException ignore) {
-                                    }
+                                    long rollbackTimeout = DeviceConfig.getLong(
+                                            DeviceConfig.Rollback.NAMESPACE,
+                                            DeviceConfig.Rollback.ENABLE_ROLLBACK_TIMEOUT,
+                                            DEFAULT_ENABLE_ROLLBACK_TIMEOUT);
                                     final Message msg = mHandler.obtainMessage(
                                             ENABLE_ROLLBACK_TIMEOUT);
                                     msg.arg1 = enableRollbackToken;
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index e241ba6..d3e1a05 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -531,17 +531,10 @@
     }
 
     private void updateRollbackLifetimeDurationInMillis() {
-        String strRollbackLifetimeInMillis = DeviceConfig.getProperty(
+        mRollbackLifetimeDurationInMillis = DeviceConfig.getLong(
                 DeviceConfig.Rollback.BOOT_NAMESPACE,
-                DeviceConfig.Rollback.ROLLBACK_LIFETIME_IN_MILLIS);
-
-        try {
-            mRollbackLifetimeDurationInMillis = (strRollbackLifetimeInMillis == null)
-                    ? DEFAULT_ROLLBACK_LIFETIME_DURATION_MILLIS
-                    : Long.parseLong(strRollbackLifetimeInMillis);
-        } catch (NumberFormatException e) {
-            mRollbackLifetimeDurationInMillis = DEFAULT_ROLLBACK_LIFETIME_DURATION_MILLIS;
-        }
+                DeviceConfig.Rollback.ROLLBACK_LIFETIME_IN_MILLIS,
+                DEFAULT_ROLLBACK_LIFETIME_DURATION_MILLIS);
     }
 
     void onBootCompleted() {
diff --git a/services/core/java/com/android/server/wm/WindowTracing.java b/services/core/java/com/android/server/wm/WindowTracing.java
index 4cf2344..765e347 100644
--- a/services/core/java/com/android/server/wm/WindowTracing.java
+++ b/services/core/java/com/android/server/wm/WindowTracing.java
@@ -98,6 +98,7 @@
             mBuffer.resetBuffer();
             mEnabled = mEnabledLockFree = true;
         }
+        log("trace.enable");
     }
 
     /**
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index 763ea62..a03d28b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -40,7 +40,6 @@
 import android.view.IRecentsAnimationRunner;
 import android.view.SurfaceControl;
 
-import androidx.test.filters.FlakyTest;
 import androidx.test.filters.SmallTest;
 
 import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
@@ -113,7 +112,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 117117823)
     public void testIncludedApps_expectTargetAndVisible() {
         mWm.setRecentsAnimationController(mController);
         final AppWindowToken homeAppWindow = createAppWindowToken(mDisplayContent,
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
index 42a205a..b140da5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
@@ -100,7 +100,6 @@
     }
 
     @Test
-    @FlakyTest(detail = "Promote to presubmit when shown to be stable.")
     public void testTaskDescriptionChanged() throws Exception {
         final Object[] params = new Object[2];
         final CountDownLatch latch = new CountDownLatch(1);
@@ -133,7 +132,6 @@
     }
 
     @Test
-    @FlakyTest(detail = "Promote to presubmit when shown to be stable.")
     public void testActivityRequestedOrientationChanged() throws Exception {
         final int[] params = new int[2];
         final CountDownLatch latch = new CountDownLatch(1);
@@ -214,6 +212,7 @@
 
         // Test for onTaskRemovalStarted.
         assertEquals(1, taskRemovalStartedLatch.getCount());
+        assertEquals(1, taskRemovedLatch.getCount());
         activity.finishAndRemoveTask();
         waitForCallback(taskRemovalStartedLatch);
         // onTaskRemovalStarted happens before the activity's window is removed.
@@ -221,7 +220,6 @@
         assertEquals(id, params[0]);
 
         // Test for onTaskRemoved.
-        assertEquals(1, taskRemovedLatch.getCount());
         waitForCallback(taskRemovedLatch);
         assertEquals(id, params[0]);
         waitForCallback(onDetachedFromWindowLatch);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java
index 8358fdd..e3691c6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java
@@ -20,6 +20,7 @@
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyZeroInteractions;
 
@@ -124,7 +125,7 @@
     public void trace_dumpsWindowManagerState_whenTracing() throws Exception {
         mWindowTracing.startTrace(mock(PrintWriter.class));
         mWindowTracing.logState("where");
-        verify(mWmMock).writeToProtoLocked(any(), eq(WindowTraceLogLevel.TRIM));
+        verify(mWmMock, times(2)).writeToProtoLocked(any(), eq(WindowTraceLogLevel.TRIM));
     }
 
     @Test
diff --git a/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java b/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java
index d685e8c..3944fad 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java
@@ -226,7 +226,7 @@
                 mCallbacklatch.countDown();
             }
         };
-        mEnMgr.getLatestTetheringEntitlementValue(TETHERING_WIFI, receiver, true);
+        mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true);
         callbackTimeoutHelper(mCallbacklatch);
         assertFalse(mEnMgr.everRunUiEntitlement);
 
@@ -242,7 +242,7 @@
                 mCallbacklatch.countDown();
             }
         };
-        mEnMgr.getLatestTetheringEntitlementValue(TETHERING_WIFI, receiver, false);
+        mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, false);
         callbackTimeoutHelper(mCallbacklatch);
         assertFalse(mEnMgr.everRunUiEntitlement);
         // 3. No cache value and ui entitlement check is needed.
@@ -255,7 +255,7 @@
                 mCallbacklatch.countDown();
             }
         };
-        mEnMgr.getLatestTetheringEntitlementValue(TETHERING_WIFI, receiver, true);
+        mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true);
         mLooper.dispatchAll();
         callbackTimeoutHelper(mCallbacklatch);
         assertTrue(mEnMgr.everRunUiEntitlement);
@@ -269,7 +269,7 @@
                 mCallbacklatch.countDown();
             }
         };
-        mEnMgr.getLatestTetheringEntitlementValue(TETHERING_WIFI, receiver, false);
+        mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, false);
         callbackTimeoutHelper(mCallbacklatch);
         assertFalse(mEnMgr.everRunUiEntitlement);
         // 5. Cache value is TETHER_ERROR_PROVISION_FAILED and ui entitlement check is needed.
@@ -282,7 +282,7 @@
                 mCallbacklatch.countDown();
             }
         };
-        mEnMgr.getLatestTetheringEntitlementValue(TETHERING_WIFI, receiver, true);
+        mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true);
         mLooper.dispatchAll();
         callbackTimeoutHelper(mCallbacklatch);
         assertTrue(mEnMgr.everRunUiEntitlement);
@@ -296,7 +296,7 @@
                 mCallbacklatch.countDown();
             }
         };
-        mEnMgr.getLatestTetheringEntitlementValue(TETHERING_WIFI, receiver, true);
+        mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true);
         callbackTimeoutHelper(mCallbacklatch);
         assertFalse(mEnMgr.everRunUiEntitlement);
         // 7. Test get value for other downstream type.
@@ -308,7 +308,7 @@
                 mCallbacklatch.countDown();
             }
         };
-        mEnMgr.getLatestTetheringEntitlementValue(TETHERING_USB, receiver, false);
+        mEnMgr.getLatestTetheringEntitlementResult(TETHERING_USB, receiver, false);
         callbackTimeoutHelper(mCallbacklatch);
         assertFalse(mEnMgr.everRunUiEntitlement);
     }
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index bc3a9a1..8bef221 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -141,6 +141,7 @@
         "ResourceValues.cpp",
         "SdkConstants.cpp",
         "StringPool.cpp",
+        "trace/TraceBuffer.cpp",
         "xml/XmlActionExecutor.cpp",
         "xml/XmlDom.cpp",
         "xml/XmlPullParser.cpp",
diff --git a/tools/aapt2/Main.cpp b/tools/aapt2/Main.cpp
index adf85b0..39eb987 100644
--- a/tools/aapt2/Main.cpp
+++ b/tools/aapt2/Main.cpp
@@ -37,6 +37,7 @@
 #include "cmd/Link.h"
 #include "cmd/Optimize.h"
 #include "io/FileStream.h"
+#include "trace/TraceBuffer.h"
 #include "util/Files.h"
 #include "util/Util.h"
 
@@ -107,9 +108,12 @@
       : Command("daemon", "m"), out_(out), diagnostics_(diagnostics) {
     SetDescription("Runs aapt in daemon mode. Each subsequent line is a single parameter to the\n"
         "command. The end of an invocation is signaled by providing an empty line.");
+    AddOptionalFlag("--trace_folder", "Generate systrace json trace fragment to specified folder.",
+                    &trace_folder_);
   }
 
-  int Action(const std::vector<std::string>& /* args */) override {
+  int Action(const std::vector<std::string>& arguments) override {
+    TRACE_FLUSH_ARGS(trace_folder_ ? trace_folder_.value() : "", "daemon", arguments);
     text::Printer printer(out_);
     std::cout << "Ready" << std::endl;
 
@@ -150,6 +154,7 @@
  private:
   io::FileOutputStream* out_;
   IDiagnostics* diagnostics_;
+  Maybe<std::string> trace_folder_;
 };
 
 }  // namespace aapt
diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp
index dbd0a0c..7c0619f 100644
--- a/tools/aapt2/ResourceTable.cpp
+++ b/tools/aapt2/ResourceTable.cpp
@@ -30,6 +30,7 @@
 #include "NameMangler.h"
 #include "ResourceValues.h"
 #include "ValueVisitor.h"
+#include "trace/TraceBuffer.h"
 #include "text/Unicode.h"
 #include "util/Util.h"
 
@@ -79,6 +80,7 @@
 }
 
 ResourceTablePackage* ResourceTable::CreatePackage(const StringPiece& name, Maybe<uint8_t> id) {
+  TRACE_CALL();
   ResourceTablePackage* package = FindOrCreatePackage(name);
   if (id && !package->id) {
     package->id = id;
diff --git a/tools/aapt2/cmd/Command.cpp b/tools/aapt2/cmd/Command.cpp
index 4424a35..919b4c9 100644
--- a/tools/aapt2/cmd/Command.cpp
+++ b/tools/aapt2/cmd/Command.cpp
@@ -25,6 +25,7 @@
 #include "android-base/utf8.h"
 #include "androidfw/StringPiece.h"
 
+#include "trace/TraceBuffer.h"
 #include "util/Util.h"
 
 using android::base::StringPrintf;
@@ -178,6 +179,7 @@
 }
 
 int Command::Execute(const std::vector<StringPiece>& args, std::ostream* out_error) {
+  TRACE_NAME_ARGS("Command::Execute", args);
   std::vector<std::string> file_args;
 
   for (size_t i = 0; i < args.size(); i++) {
diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp
index bec6c69..42dc74c 100644
--- a/tools/aapt2/cmd/Compile.cpp
+++ b/tools/aapt2/cmd/Compile.cpp
@@ -45,6 +45,7 @@
 #include "io/StringStream.h"
 #include "io/Util.h"
 #include "io/ZipArchive.h"
+#include "trace/TraceBuffer.h"
 #include "util/Files.h"
 #include "util/Maybe.h"
 #include "util/Util.h"
@@ -141,6 +142,7 @@
 static bool CompileTable(IAaptContext* context, const CompileOptions& options,
                          const ResourcePathData& path_data, io::IFile* file, IArchiveWriter* writer,
                          const std::string& output_path) {
+  TRACE_CALL();
   ResourceTable table;
   {
     auto fin = file->OpenInputStream();
@@ -286,6 +288,7 @@
 static bool WriteHeaderAndDataToWriter(const StringPiece& output_path, const ResourceFile& file,
                                        io::KnownSizeInputStream* in, IArchiveWriter* writer,
                                        IDiagnostics* diag) {
+  TRACE_CALL();
   // Start the entry so we can write the header.
   if (!writer->StartEntry(output_path, 0)) {
     diag->Error(DiagMessage(output_path) << "failed to open file");
@@ -352,6 +355,7 @@
 static bool CompileXml(IAaptContext* context, const CompileOptions& options,
                        const ResourcePathData& path_data, io::IFile* file, IArchiveWriter* writer,
                        const std::string& output_path) {
+  TRACE_CALL();
   if (context->IsVerbose()) {
     context->GetDiagnostics()->Note(DiagMessage(path_data.source) << "compiling XML");
   }
@@ -451,6 +455,7 @@
 static bool CompilePng(IAaptContext* context, const CompileOptions& options,
                        const ResourcePathData& path_data, io::IFile* file, IArchiveWriter* writer,
                        const std::string& output_path) {
+  TRACE_CALL();
   if (context->IsVerbose()) {
     context->GetDiagnostics()->Note(DiagMessage(path_data.source) << "compiling PNG");
   }
@@ -558,6 +563,7 @@
 static bool CompileFile(IAaptContext* context, const CompileOptions& options,
                         const ResourcePathData& path_data, io::IFile* file, IArchiveWriter* writer,
                         const std::string& output_path) {
+  TRACE_CALL();
   if (context->IsVerbose()) {
     context->GetDiagnostics()->Note(DiagMessage(path_data.source) << "compiling file");
   }
@@ -632,6 +638,7 @@
 
 int Compile(IAaptContext* context, io::IFileCollection* inputs, IArchiveWriter* output_writer,
              CompileOptions& options) {
+  TRACE_CALL();
   bool error = false;
 
   // Iterate over the input files in a stable, platform-independent manner
@@ -707,6 +714,7 @@
 }
 
 int CompileCommand::Action(const std::vector<std::string>& args) {
+  TRACE_FLUSH(trace_folder_? trace_folder_.value() : "", "CompileCommand::Action");
   CompileContext context(diagnostic_);
   context.SetVerbose(options_.verbose);
 
diff --git a/tools/aapt2/cmd/Compile.h b/tools/aapt2/cmd/Compile.h
index 9b32cb3..d3456b2 100644
--- a/tools/aapt2/cmd/Compile.h
+++ b/tools/aapt2/cmd/Compile.h
@@ -60,6 +60,8 @@
         "Sets the visibility of the compiled resources to the specified\n"
             "level. Accepted levels: public, private, default", &visibility_);
     AddOptionalSwitch("-v", "Enables verbose logging", &options_.verbose);
+    AddOptionalFlag("--trace-folder", "Generate systrace json trace fragment to specified folder.",
+                    &trace_folder_);
   }
 
   int Action(const std::vector<std::string>& args) override;
@@ -68,6 +70,7 @@
   IDiagnostics* diagnostic_;
   CompileOptions options_;
   Maybe<std::string> visibility_;
+  Maybe<std::string> trace_folder_;
 };
 
 int Compile(IAaptContext* context, io::IFileCollection* inputs, IArchiveWriter* output_writer,
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index a7b8d25..f354bb6 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -67,6 +67,7 @@
 #include "process/IResourceTableConsumer.h"
 #include "process/SymbolTable.h"
 #include "split/TableSplitter.h"
+#include "trace/TraceBuffer.h"
 #include "util/Files.h"
 #include "xml/XmlDom.h"
 
@@ -213,6 +214,7 @@
 static bool FlattenXml(IAaptContext* context, const xml::XmlResource& xml_res,
                        const StringPiece& path, bool keep_raw_values, bool utf16,
                        OutputFormat format, IArchiveWriter* writer) {
+  TRACE_CALL();
   if (context->IsVerbose()) {
     context->GetDiagnostics()->Note(DiagMessage(path) << "writing to archive (keep_raw_values="
                                                       << (keep_raw_values ? "true" : "false")
@@ -250,6 +252,7 @@
 
 // Inflates an XML file from the source path.
 static std::unique_ptr<xml::XmlResource> LoadXml(const std::string& path, IDiagnostics* diag) {
+  TRACE_CALL();
   FileInputStream fin(path);
   if (fin.HadError()) {
     diag->Error(DiagMessage(path) << "failed to load XML file: " << fin.GetError());
@@ -421,6 +424,7 @@
 
 std::vector<std::unique_ptr<xml::XmlResource>> ResourceFileFlattener::LinkAndVersionXmlFile(
     ResourceTable* table, FileOperation* file_op) {
+  TRACE_CALL();
   xml::XmlResource* doc = file_op->xml_to_flatten.get();
   const Source& src = doc->file.source;
 
@@ -489,6 +493,7 @@
 };
 
 bool ResourceFileFlattener::Flatten(ResourceTable* table, IArchiveWriter* archive_writer) {
+  TRACE_CALL();
   bool error = false;
   std::map<std::pair<ConfigDescription, StringPiece>, FileOperation> config_sorted_files;
 
@@ -806,6 +811,7 @@
   // Creates a SymbolTable that loads symbols from the various APKs.
   // Pre-condition: context_->GetCompilationPackage() needs to be set.
   bool LoadSymbolsFromIncludePaths() {
+    TRACE_NAME("LoadSymbolsFromIncludePaths: #" + std::to_string(options_.include_paths.size()));
     auto asset_source = util::make_unique<AssetManagerSymbolSource>();
     for (const std::string& path : options_.include_paths) {
       if (context_->IsVerbose()) {
@@ -891,6 +897,7 @@
   }
 
   Maybe<AppInfo> ExtractAppInfoFromManifest(xml::XmlResource* xml_res, IDiagnostics* diag) {
+    TRACE_CALL();
     // Make sure the first element is <manifest> with package attribute.
     xml::Element* manifest_el = xml::FindRootElement(xml_res->root.get());
     if (manifest_el == nullptr) {
@@ -1041,6 +1048,7 @@
   }
 
   bool FlattenTable(ResourceTable* table, OutputFormat format, IArchiveWriter* writer) {
+    TRACE_CALL();
     switch (format) {
       case OutputFormat::kApk: {
         BigBuffer buffer(1024);
@@ -1114,6 +1122,7 @@
   }
 
   bool GenerateJavaClasses() {
+    TRACE_CALL();
     // The set of packages whose R class to call in the main classes onResourcesLoaded callback.
     std::vector<std::string> packages_to_callback;
 
@@ -1197,6 +1206,7 @@
   }
 
   bool WriteManifestJavaFile(xml::XmlResource* manifest_xml) {
+    TRACE_CALL();
     if (!options_.generate_java_class_path) {
       return true;
     }
@@ -1254,6 +1264,7 @@
   }
 
   bool WriteProguardFile(const Maybe<std::string>& out, const proguard::KeepSet& keep_set) {
+    TRACE_CALL();
     if (!out) {
       return true;
     }
@@ -1278,6 +1289,7 @@
   }
 
   bool MergeStaticLibrary(const std::string& input, bool override) {
+    TRACE_CALL();
     if (context_->IsVerbose()) {
       context_->GetDiagnostics()->Note(DiagMessage() << "merging static library " << input);
     }
@@ -1328,6 +1340,7 @@
 
   bool MergeExportedSymbols(const Source& source,
                             const std::vector<SourcedResourceName>& exported_symbols) {
+    TRACE_CALL();
     // Add the exports of this file to the table.
     for (const SourcedResourceName& exported_symbol : exported_symbols) {
       ResourceName res_name = exported_symbol.name;
@@ -1353,6 +1366,7 @@
   }
 
   bool MergeCompiledFile(const ResourceFile& compiled_file, io::IFile* file, bool override) {
+    TRACE_CALL();
     if (context_->IsVerbose()) {
       context_->GetDiagnostics()->Note(DiagMessage()
                                        << "merging '" << compiled_file.name
@@ -1371,6 +1385,7 @@
   // An io::IFileCollection is created from the ZIP file and added to the set of
   // io::IFileCollections that are open.
   bool MergeArchive(const std::string& input, bool override) {
+    TRACE_CALL();
     if (context_->IsVerbose()) {
       context_->GetDiagnostics()->Note(DiagMessage() << "merging archive " << input);
     }
@@ -1418,6 +1433,7 @@
   // All other file types are ignored. This is because these files could be coming from a zip,
   // where we could have other files like classes.dex.
   bool MergeFile(io::IFile* file, bool override) {
+    TRACE_CALL();
     const Source& src = file->GetSource();
 
     if (util::EndsWith(src.path, ".xml") || util::EndsWith(src.path, ".png")) {
@@ -1458,6 +1474,7 @@
 
     while ((entry = reader.Next()) != nullptr) {
       if (entry->Type() == ContainerEntryType::kResTable) {
+        TRACE_NAME(std::string("Process ResTable:") + file->GetSource().path);
         pb::ResourceTable pb_table;
         if (!entry->GetResTable(&pb_table)) {
           context_->GetDiagnostics()->Error(DiagMessage(src) << "failed to read resource table: "
@@ -1478,6 +1495,7 @@
           return false;
         }
       } else if (entry->Type() == ContainerEntryType::kResFile) {
+        TRACE_NAME(std::string("Process ResFile") + file->GetSource().path);
         pb::internal::CompiledFile pb_compiled_file;
         off64_t offset;
         size_t len;
@@ -1551,6 +1569,7 @@
   // to the IArchiveWriter.
   bool WriteApk(IArchiveWriter* writer, proguard::KeepSet* keep_set, xml::XmlResource* manifest,
                 ResourceTable* table) {
+    TRACE_CALL();
     const bool keep_raw_values = (context_->GetPackageType() == PackageType::kStaticLib)
                                  || options_.keep_raw_values;
     bool result = FlattenXml(context_, *manifest, kAndroidManifestPath, keep_raw_values,
@@ -1632,6 +1651,7 @@
   }
 
   int Run(const std::vector<std::string>& input_files) {
+    TRACE_CALL();
     // Load the AndroidManifest.xml
     std::unique_ptr<xml::XmlResource> manifest_xml =
         LoadXml(options_.manifest_path, context_->GetDiagnostics());
@@ -1839,6 +1859,7 @@
       std::vector<ConfigDescription> excluded_configs;
 
       for (auto& config_string : options_.exclude_configs_) {
+        TRACE_NAME("ConfigDescription::Parse");
         ConfigDescription config_description;
 
         if (!ConfigDescription::Parse(config_string, &config_description)) {
@@ -2038,6 +2059,7 @@
 };
 
 int LinkCommand::Action(const std::vector<std::string>& args) {
+  TRACE_FLUSH(trace_folder_ ? trace_folder_.value() : "", "LinkCommand::Action");
   LinkContext context(diag_);
 
   // Expand all argument-files passed into the command line. These start with '@'.
diff --git a/tools/aapt2/cmd/Link.h b/tools/aapt2/cmd/Link.h
index 1fc149a..7c58385 100644
--- a/tools/aapt2/cmd/Link.h
+++ b/tools/aapt2/cmd/Link.h
@@ -25,6 +25,7 @@
 #include "split/TableSplitter.h"
 #include "format/binary/TableFlattener.h"
 #include "link/ManifestFixer.h"
+#include "trace/TraceBuffer.h"
 
 namespace aapt {
 
@@ -277,6 +278,8 @@
         "Do not allow overlays with different visibility levels.",
         &options_.strict_visibility);
     AddOptionalSwitch("-v", "Enables verbose logging.", &verbose_);
+    AddOptionalFlag("--trace-folder", "Generate systrace json trace fragment to specified folder.",
+                    &trace_folder_);
   }
 
   int Action(const std::vector<std::string>& args) override;
@@ -300,6 +303,7 @@
   bool proto_format_ = false;
   Maybe<std::string> stable_id_file_path_;
   std::vector<std::string> split_args_;
+  Maybe<std::string> trace_folder_;
 };
 
 }// namespace aapt
diff --git a/tools/aapt2/compile/Png.cpp b/tools/aapt2/compile/Png.cpp
index 33122dc..d396d81 100644
--- a/tools/aapt2/compile/Png.cpp
+++ b/tools/aapt2/compile/Png.cpp
@@ -27,6 +27,7 @@
 #include "androidfw/ResourceTypes.h"
 
 #include "Source.h"
+#include "trace/TraceBuffer.h"
 #include "util/BigBuffer.h"
 #include "util/Util.h"
 
@@ -1233,6 +1234,7 @@
 
 bool Png::process(const Source& source, std::istream* input,
                   BigBuffer* outBuffer, const PngOptions& options) {
+  TRACE_CALL();
   png_byte signature[kPngSignatureSize];
 
   // Read the PNG signature first.
diff --git a/tools/aapt2/compile/PngCrunch.cpp b/tools/aapt2/compile/PngCrunch.cpp
index 0346a19..1f4ea44d 100644
--- a/tools/aapt2/compile/PngCrunch.cpp
+++ b/tools/aapt2/compile/PngCrunch.cpp
@@ -27,6 +27,8 @@
 #include "android-base/logging.h"
 #include "android-base/macros.h"
 
+#include "trace/TraceBuffer.h"
+
 namespace aapt {
 
 // Custom deleter that destroys libpng read and info structs.
@@ -142,6 +144,7 @@
 }
 
 std::unique_ptr<Image> ReadPng(IAaptContext* context, const Source& source, io::InputStream* in) {
+  TRACE_CALL();
   // Create a diagnostics that has the source information encoded.
   SourcePathDiagnostics source_diag(source, context->GetDiagnostics());
 
@@ -480,6 +483,7 @@
 bool WritePng(IAaptContext* context, const Image* image,
               const NinePatch* nine_patch, io::OutputStream* out,
               const PngOptions& options) {
+  TRACE_CALL();
   // Create and initialize the write png_struct with the default error and
   // warning handlers.
   // The header version is also passed in to ensure that this was built against the same
diff --git a/tools/aapt2/compile/XmlIdCollector.cpp b/tools/aapt2/compile/XmlIdCollector.cpp
index 2199d00..5054115 100644
--- a/tools/aapt2/compile/XmlIdCollector.cpp
+++ b/tools/aapt2/compile/XmlIdCollector.cpp
@@ -22,6 +22,7 @@
 #include "ResourceUtils.h"
 #include "ResourceValues.h"
 #include "text/Unicode.h"
+#include "trace/TraceBuffer.h"
 #include "xml/XmlDom.h"
 
 namespace aapt {
@@ -72,6 +73,7 @@
 }  // namespace
 
 bool XmlIdCollector::Consume(IAaptContext* context, xml::XmlResource* xmlRes) {
+  TRACE_CALL();
   xmlRes->file.exported_symbols.clear();
   SourcePathDiagnostics source_diag(xmlRes->file.source, context->GetDiagnostics());
   IdCollector collector(&xmlRes->file.exported_symbols, &source_diag);
diff --git a/tools/aapt2/format/Container.cpp b/tools/aapt2/format/Container.cpp
index d4b4571..f189048 100644
--- a/tools/aapt2/format/Container.cpp
+++ b/tools/aapt2/format/Container.cpp
@@ -19,6 +19,8 @@
 #include "android-base/scopeguard.h"
 #include "android-base/stringprintf.h"
 
+#include "trace/TraceBuffer.h"
+
 using ::android::base::StringPrintf;
 using ::google::protobuf::io::CodedInputStream;
 using ::google::protobuf::io::CodedOutputStream;
@@ -171,6 +173,7 @@
 }
 
 bool ContainerReaderEntry::GetResTable(pb::ResourceTable* out_table) {
+  TRACE_CALL();
   CHECK(type_ == ContainerEntryType::kResTable) << "reading a kResTable when the type is kResFile";
   if (length_ > std::numeric_limits<int>::max()) {
     reader_->error_ = StringPrintf("entry length %zu is too large", length_);
@@ -261,6 +264,7 @@
       total_entry_count_(0u),
       current_entry_count_(0u),
       entry_(this) {
+  TRACE_CALL();
   ::google::protobuf::uint32 magic;
   if (!coded_in_.ReadLittleEndian32(&magic)) {
     std::ostringstream error;
diff --git a/tools/aapt2/format/binary/TableFlattener.cpp b/tools/aapt2/format/binary/TableFlattener.cpp
index d677317..aa578a2 100644
--- a/tools/aapt2/format/binary/TableFlattener.cpp
+++ b/tools/aapt2/format/binary/TableFlattener.cpp
@@ -32,6 +32,7 @@
 #include "ValueVisitor.h"
 #include "format/binary/ChunkWriter.h"
 #include "format/binary/ResourceTypeExtensions.h"
+#include "trace/TraceBuffer.h"
 #include "util/BigBuffer.h"
 
 using namespace android;
@@ -238,6 +239,7 @@
   }
 
   bool FlattenPackage(BigBuffer* buffer) {
+    TRACE_CALL();
     ChunkWriter pkg_writer(buffer);
     ResTable_package* pkg_header = pkg_writer.StartChunk<ResTable_package>(RES_TABLE_PACKAGE_TYPE);
     pkg_header->id = util::HostToDevice32(package_->id.value());
@@ -710,6 +712,7 @@
 }  // namespace
 
 bool TableFlattener::Consume(IAaptContext* context, ResourceTable* table) {
+  TRACE_CALL();
   // We must do this before writing the resources, since the string pool IDs may change.
   table->string_pool.Prune();
   table->string_pool.Sort([](const StringPool::Context& a, const StringPool::Context& b) -> int {
diff --git a/tools/aapt2/io/Util.cpp b/tools/aapt2/io/Util.cpp
index 9751632..ce6d9352 100644
--- a/tools/aapt2/io/Util.cpp
+++ b/tools/aapt2/io/Util.cpp
@@ -18,6 +18,8 @@
 
 #include "google/protobuf/io/zero_copy_stream_impl_lite.h"
 
+#include "trace/TraceBuffer.h"
+
 using ::android::StringPiece;
 using ::google::protobuf::io::ZeroCopyOutputStream;
 
@@ -26,6 +28,7 @@
 
 bool CopyInputStreamToArchive(IAaptContext* context, InputStream* in, const std::string& out_path,
                               uint32_t compression_flags, IArchiveWriter* writer) {
+  TRACE_CALL();
   if (context->IsVerbose()) {
     context->GetDiagnostics()->Note(DiagMessage() << "writing " << out_path << " to archive");
   }
@@ -40,6 +43,7 @@
 
 bool CopyFileToArchive(IAaptContext* context, io::IFile* file, const std::string& out_path,
                        uint32_t compression_flags, IArchiveWriter* writer) {
+  TRACE_CALL();
   std::unique_ptr<io::IData> data = file->OpenAsData();
   if (!data) {
     context->GetDiagnostics()->Error(DiagMessage(file->GetSource()) << "failed to open file");
@@ -57,6 +61,7 @@
 bool CopyProtoToArchive(IAaptContext* context, ::google::protobuf::MessageLite* proto_msg,
                         const std::string& out_path, uint32_t compression_flags,
                         IArchiveWriter* writer) {
+  TRACE_CALL();
   if (context->IsVerbose()) {
     context->GetDiagnostics()->Note(DiagMessage() << "writing " << out_path << " to archive");
   }
@@ -83,6 +88,7 @@
 }
 
 bool Copy(OutputStream* out, InputStream* in) {
+  TRACE_CALL();
   const void* in_buffer;
   size_t in_len;
   while (in->Next(&in_buffer, &in_len)) {
diff --git a/tools/aapt2/io/ZipArchive.cpp b/tools/aapt2/io/ZipArchive.cpp
index 427dc92..f6aaa12 100644
--- a/tools/aapt2/io/ZipArchive.cpp
+++ b/tools/aapt2/io/ZipArchive.cpp
@@ -20,6 +20,7 @@
 #include "ziparchive/zip_archive.h"
 
 #include "Source.h"
+#include "trace/TraceBuffer.h"
 #include "util/Files.h"
 #include "util/Util.h"
 
@@ -93,6 +94,7 @@
 
 std::unique_ptr<ZipFileCollection> ZipFileCollection::Create(
     const StringPiece& path, std::string* out_error) {
+  TRACE_CALL();
   constexpr static const int32_t kEmptyArchive = -6;
 
   std::unique_ptr<ZipFileCollection> collection =
diff --git a/tools/aapt2/java/ProguardRules.cpp b/tools/aapt2/java/ProguardRules.cpp
index 52e168e..05ba8f0 100644
--- a/tools/aapt2/java/ProguardRules.cpp
+++ b/tools/aapt2/java/ProguardRules.cpp
@@ -281,6 +281,15 @@
             AddClass(node->line_number, result.value(), "");
           }
         }
+
+        attr = node->FindAttribute(xml::kSchemaAndroid, "zygotePreloadName");
+        if (attr) {
+          Maybe<std::string> result = util::GetFullyQualifiedClassName(package_, attr->value);
+          if (result) {
+            AddClass(node->line_number, result.value(), "");
+          }
+        }
+
         if (main_dex_only_) {
           xml::Attribute* default_process = node->FindAttribute(xml::kSchemaAndroid, "process");
           if (default_process) {
diff --git a/tools/aapt2/java/ProguardRules_test.cpp b/tools/aapt2/java/ProguardRules_test.cpp
index da24907..559b07a 100644
--- a/tools/aapt2/java/ProguardRules_test.cpp
+++ b/tools/aapt2/java/ProguardRules_test.cpp
@@ -42,6 +42,7 @@
             android:appComponentFactory="com.foo.BarAppComponentFactory"
             android:backupAgent="com.foo.BarBackupAgent"
             android:name="com.foo.BarApplication"
+            android:zygotePreloadName="com.foo.BarZygotePreload"
             >
           <activity android:name="com.foo.BarActivity"/>
           <service android:name="com.foo.BarService"/>
@@ -63,6 +64,7 @@
   EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarReceiver { <init>(); }"));
   EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarProvider { <init>(); }"));
   EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarInstrumentation { <init>(); }"));
+  EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarZygotePreload { <init>(); }"));
 
   actual = GetKeepSetString(set, /** minimal_rules */ true);
   EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarAppComponentFactory { <init>(); }"));
@@ -73,6 +75,7 @@
   EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarReceiver { <init>(); }"));
   EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarProvider { <init>(); }"));
   EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarInstrumentation { <init>(); }"));
+  EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarZygotePreload { <init>(); }"));
 }
 
 TEST(ProguardRulesTest, FragmentNameRuleIsEmitted) {
diff --git a/tools/aapt2/link/AutoVersioner.cpp b/tools/aapt2/link/AutoVersioner.cpp
index 960c7d4..73b9254 100644
--- a/tools/aapt2/link/AutoVersioner.cpp
+++ b/tools/aapt2/link/AutoVersioner.cpp
@@ -23,6 +23,7 @@
 #include "ResourceTable.h"
 #include "SdkConstants.h"
 #include "ValueVisitor.h"
+#include "trace/TraceBuffer.h"
 
 using android::ConfigDescription;
 
@@ -70,6 +71,7 @@
 }
 
 bool AutoVersioner::Consume(IAaptContext* context, ResourceTable* table) {
+  TRACE_NAME("AutoVersioner::Consume");
   for (auto& package : table->packages) {
     for (auto& type : package->types) {
       if (type->type != ResourceType::kStyle) {
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index 582a5b8..b0a2055 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -21,6 +21,7 @@
 #include "android-base/logging.h"
 
 #include "ResourceUtils.h"
+#include "trace/TraceBuffer.h"
 #include "util/Util.h"
 #include "xml/XmlActionExecutor.h"
 #include "xml/XmlDom.h"
@@ -451,6 +452,7 @@
 }
 
 bool ManifestFixer::Consume(IAaptContext* context, xml::XmlResource* doc) {
+  TRACE_CALL();
   xml::Element* root = xml::FindRootElement(doc->root.get());
   if (!root || !root->namespace_uri.empty() || root->name != "manifest") {
     context->GetDiagnostics()->Error(DiagMessage(doc->file.source)
diff --git a/tools/aapt2/link/ProductFilter.cpp b/tools/aapt2/link/ProductFilter.cpp
index c1a95ee..793740a 100644
--- a/tools/aapt2/link/ProductFilter.cpp
+++ b/tools/aapt2/link/ProductFilter.cpp
@@ -17,6 +17,7 @@
 #include "link/Linkers.h"
 
 #include "ResourceTable.h"
+#include "trace/TraceBuffer.h"
 
 namespace aapt {
 
@@ -81,6 +82,7 @@
 }
 
 bool ProductFilter::Consume(IAaptContext* context, ResourceTable* table) {
+  TRACE_NAME("ProductFilter::Consume");
   bool error = false;
   for (auto& pkg : table->packages) {
     for (auto& type : pkg->types) {
diff --git a/tools/aapt2/link/ReferenceLinker.cpp b/tools/aapt2/link/ReferenceLinker.cpp
index c2340ba..28f09aa 100644
--- a/tools/aapt2/link/ReferenceLinker.cpp
+++ b/tools/aapt2/link/ReferenceLinker.cpp
@@ -27,6 +27,7 @@
 #include "link/Linkers.h"
 #include "process/IResourceTableConsumer.h"
 #include "process/SymbolTable.h"
+#include "trace/TraceBuffer.h"
 #include "util/Util.h"
 #include "xml/XmlUtil.h"
 
@@ -353,6 +354,7 @@
 }
 
 bool ReferenceLinker::Consume(IAaptContext* context, ResourceTable* table) {
+  TRACE_NAME("ReferenceLinker::Consume");
   EmptyDeclStack decl_stack;
   bool error = false;
   for (auto& package : table->packages) {
diff --git a/tools/aapt2/link/ResourceExcluder.cpp b/tools/aapt2/link/ResourceExcluder.cpp
index 2555995..b3b9dc4 100644
--- a/tools/aapt2/link/ResourceExcluder.cpp
+++ b/tools/aapt2/link/ResourceExcluder.cpp
@@ -20,6 +20,7 @@
 
 #include "DominatorTree.h"
 #include "ResourceTable.h"
+#include "trace/TraceBuffer.h"
 
 using android::ConfigDescription;
 
@@ -65,6 +66,7 @@
 }  // namespace
 
 bool ResourceExcluder::Consume(IAaptContext* context, ResourceTable* table) {
+  TRACE_NAME("ResourceExcluder::Consume");
   for (auto& package : table->packages) {
     for (auto& type : package->types) {
       for (auto& entry : type->entries) {
diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp
index cc9fed5..e937517 100644
--- a/tools/aapt2/link/TableMerger.cpp
+++ b/tools/aapt2/link/TableMerger.cpp
@@ -21,6 +21,7 @@
 #include "ResourceTable.h"
 #include "ResourceUtils.h"
 #include "ResourceValues.h"
+#include "trace/TraceBuffer.h"
 #include "ValueVisitor.h"
 #include "util/Util.h"
 
@@ -38,6 +39,7 @@
 }
 
 bool TableMerger::Merge(const Source& src, ResourceTable* table, bool overlay) {
+  TRACE_CALL();
   // We allow adding new resources if this is not an overlay, or if the options allow overlays
   // to add new resources.
   return MergeImpl(src, table, overlay, options_.auto_add_overlay || !overlay /*allow_new*/);
diff --git a/tools/aapt2/link/XmlReferenceLinker.cpp b/tools/aapt2/link/XmlReferenceLinker.cpp
index 160ff92..d68f7dd 100644
--- a/tools/aapt2/link/XmlReferenceLinker.cpp
+++ b/tools/aapt2/link/XmlReferenceLinker.cpp
@@ -25,6 +25,7 @@
 #include "link/ReferenceLinker.h"
 #include "process/IResourceTableConsumer.h"
 #include "process/SymbolTable.h"
+#include "trace/TraceBuffer.h"
 #include "util/Util.h"
 #include "xml/XmlDom.h"
 
@@ -151,6 +152,7 @@
 }  // namespace
 
 bool XmlReferenceLinker::Consume(IAaptContext* context, xml::XmlResource* resource) {
+  TRACE_NAME("XmlReferenceLinker::Consume");
   CallSite callsite{resource->file.name.package};
 
   std::string out_name = resource->file.name.entry;
diff --git a/tools/aapt2/optimize/ResourceDeduper.cpp b/tools/aapt2/optimize/ResourceDeduper.cpp
index ee2dfbc..78ebcb9 100644
--- a/tools/aapt2/optimize/ResourceDeduper.cpp
+++ b/tools/aapt2/optimize/ResourceDeduper.cpp
@@ -20,6 +20,7 @@
 
 #include "DominatorTree.h"
 #include "ResourceTable.h"
+#include "trace/TraceBuffer.h"
 
 using android::ConfigDescription;
 
@@ -110,6 +111,7 @@
 }  // namespace
 
 bool ResourceDeduper::Consume(IAaptContext* context, ResourceTable* table) {
+  TRACE_CALL();
   for (auto& package : table->packages) {
     for (auto& type : package->types) {
       for (auto& entry : type->entries) {
diff --git a/tools/aapt2/optimize/VersionCollapser.cpp b/tools/aapt2/optimize/VersionCollapser.cpp
index f985604..cd791bd 100644
--- a/tools/aapt2/optimize/VersionCollapser.cpp
+++ b/tools/aapt2/optimize/VersionCollapser.cpp
@@ -20,6 +20,7 @@
 #include <vector>
 
 #include "ResourceTable.h"
+#include "trace/TraceBuffer.h"
 
 using android::ConfigDescription;
 
@@ -144,6 +145,7 @@
 }
 
 bool VersionCollapser::Consume(IAaptContext* context, ResourceTable* table) {
+  TRACE_NAME("VersionCollapser::Consume");
   const int min_sdk = context->GetMinSdkVersion();
   for (auto& package : table->packages) {
     for (auto& type : package->types) {
diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp
index 78e0074..61a8fbb 100644
--- a/tools/aapt2/process/SymbolTable.cpp
+++ b/tools/aapt2/process/SymbolTable.cpp
@@ -30,6 +30,7 @@
 #include "Resource.h"
 #include "ResourceUtils.h"
 #include "ValueVisitor.h"
+#include "trace/TraceBuffer.h"
 #include "util/Util.h"
 
 using ::android::ApkAssets;
@@ -217,6 +218,7 @@
 }
 
 bool AssetManagerSymbolSource::AddAssetPath(const StringPiece& path) {
+  TRACE_CALL();
   if (std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(path.data())) {
     apk_assets_.push_back(std::move(apk));
 
@@ -233,6 +235,7 @@
 }
 
 std::map<size_t, std::string> AssetManagerSymbolSource::GetAssignedPackageIds() const {
+  TRACE_CALL();
   std::map<size_t, std::string> package_map;
   asset_manager_.ForEachPackage([&package_map](const std::string& name, uint8_t id) -> bool {
     package_map.insert(std::make_pair(id, name));
diff --git a/tools/aapt2/split/TableSplitter.cpp b/tools/aapt2/split/TableSplitter.cpp
index 24cd5ba..6a67271 100644
--- a/tools/aapt2/split/TableSplitter.cpp
+++ b/tools/aapt2/split/TableSplitter.cpp
@@ -27,6 +27,7 @@
 #include "androidfw/ConfigDescription.h"
 
 #include "ResourceTable.h"
+#include "trace/TraceBuffer.h"
 #include "util/Util.h"
 
 using ::android::ConfigDescription;
@@ -154,6 +155,7 @@
   }
 }
 bool TableSplitter::VerifySplitConstraints(IAaptContext* context) {
+  TRACE_CALL();
   bool error = false;
   for (size_t i = 0; i < split_constraints_.size(); i++) {
     if (split_constraints_[i].configs.size() == 0) {
diff --git a/tools/aapt2/trace/TraceBuffer.cpp b/tools/aapt2/trace/TraceBuffer.cpp
new file mode 100644
index 0000000..b4b31d9
--- /dev/null
+++ b/tools/aapt2/trace/TraceBuffer.cpp
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "TraceBuffer.h"
+
+#include <chrono>
+#include <sstream>
+#include <unistd.h>
+#include <vector>
+
+#include <inttypes.h>
+
+#include "android-base/utf8.h"
+
+#include "util/Files.h"
+
+namespace aapt {
+namespace tracebuffer {
+
+namespace {
+
+constexpr char kBegin = 'B';
+constexpr char kEnd = 'E';
+
+struct TracePoint {
+  pid_t tid;
+  int64_t time;
+  std::string tag;
+  char type;
+};
+
+std::vector<TracePoint> traces;
+
+int64_t GetTime() noexcept {
+  auto now = std::chrono::steady_clock::now();
+  return std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch()).count();
+}
+
+} // namespace anonymous
+
+void AddWithTime(const std::string& tag, char type, int64_t time) noexcept {
+  TracePoint t = {getpid(), time, tag, type};
+  traces.emplace_back(t);
+}
+
+void Add(const std::string& tag, char type) noexcept {
+  AddWithTime(tag, type, GetTime());
+}
+
+
+
+
+void Flush(const std::string& basePath) {
+  TRACE_CALL();
+  if (basePath.empty()) {
+    return;
+  }
+
+  std::stringstream s;
+  s << basePath << aapt::file::sDirSep << "report_aapt2_" << getpid() << ".json";
+  FILE* f = android::base::utf8::fopen(s.str().c_str(), "a");
+  if (f == nullptr) {
+    return;
+  }
+
+  for(const TracePoint& trace : traces) {
+    fprintf(f, "{\"ts\" : \"%" PRIu64 "\", \"ph\" : \"%c\", \"tid\" : \"%d\" , \"pid\" : \"%d\", "
+            "\"name\" : \"%s\" },\n", trace.time, trace.type, 0, trace.tid, trace.tag.c_str());
+  }
+  fclose(f);
+  traces.clear();
+}
+
+} // namespace tracebuffer
+
+void BeginTrace(const std::string& tag) {
+  tracebuffer::Add(tag, tracebuffer::kBegin);
+}
+
+void EndTrace() {
+  tracebuffer::Add("", tracebuffer::kEnd);
+}
+
+Trace::Trace(const std::string& tag) {
+  tracebuffer::Add(tag, tracebuffer::kBegin);
+}
+
+Trace::Trace(const std::string& tag, const std::vector<android::StringPiece>& args) {
+  std::stringstream s;
+  s << tag;
+  s << " ";
+  for (auto& arg : args) {
+    s << arg.to_string();
+    s << " ";
+  }
+  tracebuffer::Add(s.str(), tracebuffer::kBegin);
+}
+
+Trace::~Trace() {
+  tracebuffer::Add("", tracebuffer::kEnd);
+}
+
+FlushTrace::FlushTrace(const std::string& basepath, const std::string& tag)
+    : basepath_(basepath)  {
+  tracebuffer::Add(tag, tracebuffer::kBegin);
+}
+
+FlushTrace::FlushTrace(const std::string& basepath, const std::string& tag,
+    const std::vector<android::StringPiece>& args) : basepath_(basepath) {
+  std::stringstream s;
+  s << tag;
+  s << " ";
+  for (auto& arg : args) {
+    s << arg.to_string();
+    s << " ";
+  }
+  tracebuffer::Add(s.str(), tracebuffer::kBegin);
+}
+
+FlushTrace::FlushTrace(const std::string& basepath, const std::string& tag,
+    const std::vector<std::string>& args) : basepath_(basepath){
+  std::stringstream s;
+  s << tag;
+  s << " ";
+  for (auto& arg : args) {
+    s << arg;
+    s << " ";
+  }
+  tracebuffer::Add(s.str(), tracebuffer::kBegin);
+}
+
+FlushTrace::~FlushTrace() {
+  tracebuffer::Add("", tracebuffer::kEnd);
+  tracebuffer::Flush(basepath_);
+}
+
+} // namespace aapt
+
diff --git a/tools/aapt2/trace/TraceBuffer.h b/tools/aapt2/trace/TraceBuffer.h
new file mode 100644
index 0000000..8618e0e
--- /dev/null
+++ b/tools/aapt2/trace/TraceBuffer.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 AAPT_TRACEBUFFER_H
+#define AAPT_TRACEBUFFER_H
+
+#include <string>
+#include <vector>
+
+#include <androidfw/StringPiece.h>
+
+namespace aapt {
+
+// Record timestamps for beginning and end of a task and generate systrace json fragments.
+// This is an in-process ftrace which has the advantage of being platform independent.
+// These methods are NOT thread-safe since aapt2 is not multi-threaded.
+
+// Convenience RIAA object to automatically finish an event when object goes out of scope.
+class Trace {
+public:
+  Trace(const std::string& tag);
+  Trace(const std::string& tag, const std::vector<android::StringPiece>& args);
+  ~Trace();
+};
+
+// Manual markers.
+void BeginTrace(const std::string& tag);
+void EndTrace();
+
+// A master trace is required to flush events to disk. Events are formatted in systrace
+// json format.
+class FlushTrace {
+public:
+  explicit FlushTrace(const std::string& basepath, const std::string& tag);
+  explicit FlushTrace(const std::string& basepath, const std::string& tag,
+      const std::vector<android::StringPiece>& args);
+  explicit FlushTrace(const std::string& basepath, const std::string& tag,
+      const std::vector<std::string>& args);
+  ~FlushTrace();
+private:
+  std::string basepath_;
+};
+
+#define TRACE_CALL() Trace __t(__func__)
+#define TRACE_NAME(tag) Trace __t(tag)
+#define TRACE_NAME_ARGS(tag, args) Trace __t(tag, args)
+
+#define TRACE_FLUSH(basename, tag) FlushTrace __t(basename, tag)
+#define TRACE_FLUSH_ARGS(basename, tag, args) FlushTrace __t(basename, tag, args)
+} // namespace aapt
+#endif //AAPT_TRACEBUFFER_H
diff --git a/tools/aapt2/xml/XmlDom.cpp b/tools/aapt2/xml/XmlDom.cpp
index acd07c2..9a725fa 100644
--- a/tools/aapt2/xml/XmlDom.cpp
+++ b/tools/aapt2/xml/XmlDom.cpp
@@ -26,6 +26,7 @@
 #include "android-base/logging.h"
 
 #include "ResourceUtils.h"
+#include "trace/TraceBuffer.h"
 #include "XmlPullParser.h"
 #include "util/Util.h"
 
@@ -264,6 +265,7 @@
 }
 
 std::unique_ptr<XmlResource> Inflate(const void* data, size_t len, std::string* out_error) {
+  TRACE_CALL();
   // We import the android namespace because on Windows NO_ERROR is a macro, not
   // an enum, which causes errors when qualifying it with android::
   using namespace android;