diff options
87 files changed, 1542 insertions, 1054 deletions
diff --git a/api/current.txt b/api/current.txt index 8147ad58abd9..6c4bd1b1de48 100644 --- a/api/current.txt +++ b/api/current.txt @@ -11461,7 +11461,7 @@ package android.content.pm { 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 @@ package android.media { 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 @@ package android.media { } 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 @@ package android.nfc { } 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 @@ package android.nfc { 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 @@ package android.os { } 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 @@ package android.os { 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 @@ package android.os { 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 7a06803053e8..93d06928e3d0 100644 --- a/api/removed.txt +++ b/api/removed.txt @@ -335,11 +335,17 @@ package android.media.tv { 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 42486b8ca29c..805bfb519798 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -4034,7 +4034,7 @@ package android.net { 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 @@ package android.net { 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 @@ package android.nfc { 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 @@ package android.service.contentcapture { 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.accessibility { 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 3b0295488ded..26c21d362375 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -2307,7 +2307,6 @@ package android.service.contentcapture { 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 @@ 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>); 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 a1341fb001f6..f4c3e9ca180f 100644 --- a/cmds/idmap2/libidmap2/Idmap.cpp +++ b/cmds/idmap2/libidmap2/Idmap.cpp @@ -287,11 +287,20 @@ std::unique_ptr<const Idmap> Idmap::FromBinaryStream(std::istream& stream, 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 @@ std::unique_ptr<const Idmap> Idmap::FromApkAssets( 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 bbfbad9aa8ca..8d65428f134e 100644 --- a/cmds/idmap2/tests/IdmapTests.cpp +++ b/cmds/idmap2/tests/IdmapTests.cpp @@ -173,20 +173,27 @@ TEST(IdmapTests, GracefullyFailToCreateIdmapFromCorruptBinaryStream) { 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 @@ TEST(IdmapTests, CreateIdmapFromApkAssets) { // 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, CreateIdmapFromApkAssetsPolicySystemPublic) { } 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 @@ TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySignature) { 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 @@ TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) { // 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 @@ TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalidIgn 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 @@ TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsNoDefinedOverlayableAndNoTar 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 e879f443c7b1..68b9f507a11d 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 Binary files differindex 7d23c09473ce..642519008b15 100644 --- a/cmds/idmap2/tests/data/overlay/overlay-no-name.apk +++ b/cmds/idmap2/tests/data/overlay/overlay-no-name.apk diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index b20cce9b7e3e..7de810526d4b 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -2130,7 +2130,7 @@ public class PackageInstaller { * 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 1312f18a14ed..0497f8c94667 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -2681,12 +2681,39 @@ public class ConnectivityManager { } } + /** @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 @@ public class ConnectivityManager { * {@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 @@ public class ConnectivityManager { 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 6728712fe686..fd44fc8a2353 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -212,6 +212,6 @@ interface IConnectivityManager 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 a7d2ee98b45c..8970c625caa7 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -1704,11 +1704,12 @@ public final class NfcAdapter { /** * 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 @@ public final class NfcAdapter { * @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 @@ public final class NfcAdapter { /** * 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 c906d33a081e..728b215a75cb 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -809,7 +809,8 @@ public final class PowerManager { 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 @@ public final class PowerManager { } /** - * 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 @@ public final class PowerManager { } /** - * 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 3a2564ae8d93..f8dfc582fb76 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -5758,7 +5758,11 @@ public final class Settings { "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 9c4669f8dcd3..4afd204d531b 100644 --- a/core/java/android/service/contentcapture/ContentCaptureService.java +++ b/core/java/android/service/contentcapture/ContentCaptureService.java @@ -37,7 +37,6 @@ import android.os.Looper; 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 @@ public abstract class ContentCaptureService extends Service { } /** - * @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 f13cb5a197d8..2e27737782fa 100644 --- a/core/java/android/view/LayoutInflater.java +++ b/core/java/android/view/LayoutInflater.java @@ -714,7 +714,8 @@ public abstract class LayoutInflater { 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 @@ public abstract class LayoutInflater { } } + 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 @@ public abstract class LayoutInflater { 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 @@ public abstract class LayoutInflater { 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 @@ public abstract class LayoutInflater { 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 @@ public abstract class LayoutInflater { 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 @@ public abstract class LayoutInflater { /** * 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 @@ public abstract class LayoutInflater { 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 @@ public abstract class LayoutInflater { } 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 f8d5014a29c9..b2f3f5edcd20 100644 --- a/core/java/android/view/NotificationHeaderView.java +++ b/core/java/android/view/NotificationHeaderView.java @@ -67,6 +67,7 @@ public class NotificationHeaderView extends ViewGroup { 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 @@ public class NotificationHeaderView extends ViewGroup { 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 @@ public class NotificationHeaderView extends ViewGroup { 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 @@ public class NotificationHeaderView extends ViewGroup { shrinkViewForOverflow(wrapContentHeightSpec, overFlow, mSecondaryHeaderText, 0); } + totalWidth += getPaddingEnd(); mTotalWidth = Math.min(totalWidth, givenWidth); setMeasuredDimension(givenWidth, givenHeight); } @@ -383,6 +395,26 @@ public class NotificationHeaderView extends ViewGroup { 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 287365f70344..a9965b06555f 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -5803,6 +5803,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, 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 5d59e4205579..df8690d2eef8 100644 --- a/core/java/android/view/accessibility/AccessibilityCache.java +++ b/core/java/android/view/accessibility/AccessibilityCache.java @@ -360,7 +360,7 @@ public class AccessibilityCache { } 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 70fe230ce226..0c0a555fd16a 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -1827,22 +1827,6 @@ public final class AutofillManager { } /** - * @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 498bc5a7d598..de86d923d1e3 100644 --- a/core/java/com/android/internal/widget/MediaNotificationView.java +++ b/core/java/com/android/internal/widget/MediaNotificationView.java @@ -19,6 +19,7 @@ package com.android.internal.widget; 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 @@ public class MediaNotificationView extends FrameLayout { 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 @@ public class MediaNotificationView extends FrameLayout { 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 000000000000..36d8f88369a4 --- /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 29b496430555..4aad742be915 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"> - <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"> - <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_D_0_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"> - <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_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_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"> - <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_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"> - <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_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"> - <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"> + <target android:name="_R_G_L_2_G"> <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"> + <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:duration="333" - android:propertyName="scaleX" - android:startOffset="17" - android:valueFrom="1" - android:valueTo="0.4325" - android:valueType="floatType"> + <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.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:duration="333" - android:propertyName="scaleY" - android:startOffset="17" - android:valueFrom="1" - android:valueTo="0.4325" - 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_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"> + <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.167,0.167 0.833,0.833 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> - <objectAnimator - android:duration="17" - android:propertyName="fillAlpha" - android:startOffset="150" - android:valueFrom="0" - android:valueTo="1" - 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.167,0.167 0.833,0.833 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> </aapt:attr> </target> - <target android:name="_R_G_L_1_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="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"> + <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: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"> + <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.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: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"> + <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_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"> + <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> - <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"> + <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" /> + <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_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"> + <target android:name="_R_G_L_0_G_N_4_T_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"> + <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> - </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"> + <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> - <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="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.167,0.167 0.833,0.833 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_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"> + <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_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"> + <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" /> + <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 ea5f5727b0fe..000000000000 --- 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 e01f4215b7f4..13551e71b371 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 1b587dd92db0..576ac73bc183 100644 --- a/core/tests/coretests/src/android/os/PowerManagerTest.java +++ b/core/tests/coretests/src/android/os/PowerManagerTest.java @@ -41,7 +41,9 @@ public class PowerManagerTest extends AndroidTestCase { 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 @@ public class PowerManagerTest extends AndroidTestCase { // 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 @@ public class PowerManagerTest extends AndroidTestCase { 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 28937a65ad0d..fbb629b8383a 100644 --- a/media/java/android/media/AudioRecord.java +++ b/media/java/android/media/AudioRecord.java @@ -1984,41 +1984,45 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection, { private MetricsConstants() {} + // 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 output format being recorded + * 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 ENCODING = "android.media.audiorecord.encoding"; + public static final String ENCODING = MM_PREFIX + "encoding"; /** - * Key to extract the Source Type for this track + * Key to extract the source type 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 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 7cfe0dd4b596..a15d322cf8fd 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -3580,41 +3580,49 @@ public class AudioTrack extends PlayerBase { private MetricsConstants() {} + // 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 Stream 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 STREAMTYPE = "android.media.audiotrack.streamtype"; + 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 CONTENTTYPE = "android.media.audiotrack.type"; + public static final String CONTENTTYPE = MM_PREFIX + "type"; /** - * Key to extract the Content Type for this track + * Key to extract the attribute usage 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 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 43c97df24a58..52d7e2cedeb7 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 @@ public class PowerUtil { } private static String getRegularTimeRemainingShortString(Context context, long drainTimeMs) { - // Get the time of day we think device will die rounded to the nearest 15 min. - final long roundedTimeOfDayMs = - roundTimeToNearestThreshold( - System.currentTimeMillis() + drainTimeMs, - FIFTEEN_MINUTES_MILLIS); - - // convert the time to a properly formatted string. - String skeleton = android.text.format.DateFormat.getTimeFormatString(context); - DateFormat fmt = DateFormat.getInstanceForSkeleton(skeleton); - Date date = Date.from(Instant.ofEpochMilli(roundedTimeOfDayMs)); - CharSequence timeString = fmt.format(date); + // 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 */); - 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 53b3a7e2f34b..d4957c903a49 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 bd9d3fb43528..7e0f3ae3f1fc 100644 --- a/packages/SystemUI/res/layout/notification_info.xml +++ b/packages/SystemUI/res/layout/notification_info.xml @@ -174,7 +174,7 @@ asked for it --> 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 @@ asked for it --> 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 cf1b4d196847..9e9aada07bef 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 592b6039d69d..39a584272585 100644 --- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java +++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java @@ -355,15 +355,23 @@ public class BatteryMeterView extends LinearLayout implements 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 603b3b9766d9..4addbb50cd7f 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.AttributeSet; 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 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList /** * 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 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList } 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 4869485a3336..8f9f1cb95acc 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 @@ public class BubbleStackView extends FrameLayout { 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 @@ public class BubbleStackView extends FrameLayout { 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 6a8c19ad0e77..08cf606f4273 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.Intent; 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; 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 class QuickStatusBarHeader extends RelativeLayout implements 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 @@ public class QuickStatusBarHeader extends RelativeLayout implements }; 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 @@ public class QuickStatusBarHeader extends RelativeLayout implements @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 @@ public class QuickStatusBarHeader extends RelativeLayout implements 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 @@ public class QuickStatusBarHeader extends RelativeLayout implements 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 class QuickStatusBarHeader extends RelativeLayout implements public void onDetachedFromWindow() { setListening(false); mStatusBarIconController.removeIconGroup(mIconManager); - mContext.getContentResolver().unregisterContentObserver(mPercentSettingObserver); super.onDetachedFromWindow(); } @@ -743,25 +731,4 @@ public class QuickStatusBarHeader extends RelativeLayout implements 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 a9fe3b251f7b..dfbb32e451d6 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 @@ public class KeyguardIndicationController implements StateListener { 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 @@ public class KeyguardIndicationController implements StateListener { 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 @@ public class KeyguardIndicationController implements StateListener { // 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 4690aeb9245f..78500357f41f 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 @@ public class NotificationContentView extends FrameLayout { 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 60015efef92a..64e76d39af78 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 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange 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 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange @Override public void onUserInfoChanged(String name, Drawable picture, String userAccount) { - mUserAvatarIcon = picture; update(); } @@ -110,10 +106,8 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange 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 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange R.string.accessibility_scanning_face)); } - mHasFingerPrintState = anyFingerprintState; if (animation != null && isAnim) { animation.forceAnimationOnUI(); animation.start(); @@ -178,7 +171,10 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange @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 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange 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 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange 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 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange 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 5e94152e7eab..111cdd2cc32a 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 @@ public interface BatteryController extends DemoMode, Dumpable, * 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 3fa3e1a6e6d4..273fa55ee9d8 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 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC 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 b561ac1664c0..db2be0e78e9a 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 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof 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 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof 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 943d927e2190..cf25a9d59aaf 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 @@ public class StackAnimationControllerTest extends PhysicsAnimationLayoutTestCase } @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 000000000000..3e4c4d6a7a8a --- /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 9f7a940c1d16..52d233448791 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 @@ public final class ContentCaptureManagerService extends 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 @@ public final class ContentCaptureManagerService extends 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 @@ public final class ContentCaptureManagerService extends 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 @@ public final class ContentCaptureManagerService extends } 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 @@ public final class ContentCaptureManagerService extends } } - 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 @@ public final class ContentCaptureManagerService extends 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 @@ public final class ContentCaptureManagerService extends 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 9df09b97da40..9185cb6c5346 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 class ContentCapturePerUserService 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 da89116792ab..219e04659581 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -3792,10 +3792,10 @@ public class ConnectivityService extends IConnectivityManager.Stub * 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 13ff30d6ad3e..3b4b6f85372b 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 @@ public class Tethering extends BaseNetworkObserver { } /** 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 75aac106e0e0..65cc51610e72 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 @@ public class EntitlementManager { } /** 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 15a00d5151da..b64b7c64e363 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 @@ public class PackageManagerService extends IPackageManager.Stub @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 e241ba63f082..d3e1a05061d2 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 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } 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 4cf234424acc..765e34788ac8 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 @@ class WindowTracing { 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 763ea6293fcc..a03d28b47057 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.util.SparseBooleanArray; 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 @@ public class RecentsAnimationControllerTest extends WindowTestsBase { } @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 42a205a2fb3d..b140da501c38 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 @@ public class TaskStackChangedListenerTest { } @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 @@ public class TaskStackChangedListenerTest { } @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 @@ public class TaskStackChangedListenerTest { // 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 @@ public class TaskStackChangedListenerTest { 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 8358fdd18e0e..e3691c653959 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 androidx.test.platform.app.InstrumentationRegistry.getInstrumentat 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 class WindowTracingTest { 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 d685e8c3b9dc..3944fad2ac9e 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 @@ public final class EntitlementManagerTest { mCallbacklatch.countDown(); } }; - mEnMgr.getLatestTetheringEntitlementValue(TETHERING_WIFI, receiver, true); + mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true); callbackTimeoutHelper(mCallbacklatch); assertFalse(mEnMgr.everRunUiEntitlement); @@ -242,7 +242,7 @@ public final class EntitlementManagerTest { 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 @@ public final class EntitlementManagerTest { 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 @@ public final class EntitlementManagerTest { 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 @@ public final class EntitlementManagerTest { 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 @@ public final class EntitlementManagerTest { 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 @@ public final class EntitlementManagerTest { 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 bc3a9a1c88c8..8bef221fe5ed 100644 --- a/tools/aapt2/Android.bp +++ b/tools/aapt2/Android.bp @@ -141,6 +141,7 @@ cc_library_host_static { "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 adf85b0ea8e8..39eb9879f86d 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 @@ class DaemonCommand : public Command { : 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 @@ class DaemonCommand : public Command { 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 dbd0a0ca1799..7c0619f33851 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::FindPackageById(uint8_t id) const { } 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 4424a357c1dd..919b4c98fa8f 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 @@ void Command::Usage(std::ostream* out) { } 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 bec6c6973613..42dc74c6db55 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 std::string BuildIntermediateContainerFilename(const ResourcePathData& da 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 CompileTable(IAaptContext* context, const CompileOptions& options, 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 IsValidFile(IAaptContext* context, const std::string& input_path) { 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 CompileXml(IAaptContext* context, const CompileOptions& options, 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 CompilePng(IAaptContext* context, const CompileOptions& options, 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 @@ class CompileContext : public IAaptContext { 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 Compile(IAaptContext* context, io::IFileCollection* inputs, IArchiveWriter* } 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 9b32cb3750a5..d3456b25da9a 100644 --- a/tools/aapt2/cmd/Compile.h +++ b/tools/aapt2/cmd/Compile.h @@ -60,6 +60,8 @@ class CompileCommand : public Command { "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 @@ class CompileCommand : public Command { 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 a7b8d2535e79..f354bb610224 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 @@ class FeatureSplitSymbolTableDelegate : public DefaultSymbolTableDelegate { 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 @@ static bool FlattenXml(IAaptContext* context, const xml::XmlResource& xml_res, // 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<T> make_singleton_vec(T&& val) { 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 @@ static auto kDrawableVersions = std::map<std::string, ApiVersion>{ }; 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 @@ class Linker { // 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 @@ class Linker { } 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 @@ class Linker { } bool FlattenTable(ResourceTable* table, OutputFormat format, IArchiveWriter* writer) { + TRACE_CALL(); switch (format) { case OutputFormat::kApk: { BigBuffer buffer(1024); @@ -1114,6 +1122,7 @@ class Linker { } 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 @@ class Linker { } bool WriteManifestJavaFile(xml::XmlResource* manifest_xml) { + TRACE_CALL(); if (!options_.generate_java_class_path) { return true; } @@ -1254,6 +1264,7 @@ class Linker { } bool WriteProguardFile(const Maybe<std::string>& out, const proguard::KeepSet& keep_set) { + TRACE_CALL(); if (!out) { return true; } @@ -1278,6 +1289,7 @@ class Linker { } 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 @@ class Linker { 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 @@ class Linker { } 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 @@ class Linker { // 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 @@ class Linker { // 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 @@ class Linker { 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 @@ class Linker { 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 @@ class Linker { // 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 @@ class Linker { } 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 @@ class Linker { 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 @@ class Linker { }; 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 1fc149ab41af..7c583858ee1d 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 @@ class LinkCommand : public Command { "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 @@ class LinkCommand : public Command { 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 33122dccb7de..d396d81d699a 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 @@ getout: 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 0346a1982d8a..1f4ea44d9f86 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 @@ static void WriteDataToStream(png_structp png_ptr, png_bytep buffer, png_size_t } 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 @@ static void WriteNinePatch(png_structp write_ptr, png_infop write_info_ptr, 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 2199d003bccb..50541152f802 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 @@ struct IdCollector : public xml::Visitor { } // 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 d4b45717e015..f1890488276c 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 @@ ContainerEntryType ContainerReaderEntry::Type() const { } 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 @@ ContainerReader::ContainerReader(io::InputStream* in) 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 d677317dc98d..aa578a2a6ff4 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 @@ class PackageFlattener { } 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 @@ class PackageFlattener { } // 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 97516322c4cb..ce6d9352180d 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 @@ namespace io { 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 CopyInputStreamToArchive(IAaptContext* context, InputStream* in, const std: 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 CopyFileToArchivePreserveCompression(IAaptContext* context, io::IFile* file 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 CopyProtoToArchive(IAaptContext* context, ::google::protobuf::MessageLite* } 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 427dc92505d4..f6aaa1280a61 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 @@ ZipFileCollection::ZipFileCollection() : handle_(nullptr) {} 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 52e168ed47aa..05ba8f05ec67 100644 --- a/tools/aapt2/java/ProguardRules.cpp +++ b/tools/aapt2/java/ProguardRules.cpp @@ -281,6 +281,15 @@ class ManifestVisitor : public BaseVisitor { 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 da24907417fa..559b07af3e80 100644 --- a/tools/aapt2/java/ProguardRules_test.cpp +++ b/tools/aapt2/java/ProguardRules_test.cpp @@ -42,6 +42,7 @@ TEST(ProguardRulesTest, ManifestRuleDefaultConstructorOnly) { 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 @@ TEST(ProguardRulesTest, ManifestRuleDefaultConstructorOnly) { 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 @@ TEST(ProguardRulesTest, ManifestRuleDefaultConstructorOnly) { 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 960c7d46cc98..73b92542a755 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 @@ ApiVersion FindNextApiVersionForConfig(const ResourceEntry* entry, } 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 582a5b869c65..b0a2055cafc8 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 @@ static bool RenameManifestPackage(const StringPiece& package_override, xml::Elem } 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 c1a95ee1bcec..793740af3021 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 @@ ProductFilter::ResourceConfigValueIter ProductFilter::SelectProductToKeep( } 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 c2340ba65e38..28f09aa48365 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::LinkReference(const CallSite& callsite, Reference* referen } 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 2555995dfc8e..b3b9dc47fd84 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 @@ void RemoveIfExcluded(std::set<std::pair<ConfigDescription, int>>& excluded_conf } // 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 cc9fed554350..e9375176f26b 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 @@ TableMerger::TableMerger(IAaptContext* context, ResourceTable* out_table, } 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 160ff925f6cc..d68f7dd44c9f 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 @@ class XmlVisitor : public xml::PackageAwareVisitor { } // 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 ee2dfbce7c06..78ebcb97b811 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 @@ static void DedupeEntry(IAaptContext* context, ResourceEntry* entry) { } // 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 f9856047ac40..cd791bda250b 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 @@ static void CollapseVersions(int min_sdk, ResourceEntry* entry) { } 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 78e00746f6cb..61a8fbbb7f52 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 @@ std::unique_ptr<SymbolTable::Symbol> ResourceTableSymbolSource::FindByName( } 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 @@ bool AssetManagerSymbolSource::AddAssetPath(const StringPiece& path) { } 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 24cd5ba302ea..6a672717f38e 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 @@ static void MarkNonPreferredDensitiesAsClaimed( } } 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 000000000000..b4b31d9daf6e --- /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 000000000000..8618e0eeb731 --- /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 acd07c2876c8..9a725fad8727 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 @@ static void CopyAttributes(Element* el, android::ResXMLParser* parser, StringPoo } 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; |