diff options
58 files changed, 2171 insertions, 652 deletions
diff --git a/Android.bp b/Android.bp index 888c576df743..5224348621b5 100644 --- a/Android.bp +++ b/Android.bp @@ -368,6 +368,7 @@ java_library { "devicepolicyprotosnano", "com.android.sysprop.apex", + "com.android.sysprop.init", "PlatformProperties", ], sdk_version: "core_platform", @@ -911,22 +912,6 @@ gensrcs { output_extension: "proto.h", } - -subdirs = [ - "cmds/*", - "core/*", - "libs/*", - "media/*", - "proto", - "tools/*", - "native/android", - "native/graphics/jni", -] - -optional_subdirs = [ - "core/tests/utiltests/jni", -] - // TODO(b/77285514): remove this once the last few hidl interfaces have been // updated to use hwbinder.stubs. java_library { @@ -986,13 +971,6 @@ python_binary_host { } filegroup { - name: "framework-annotation-nonnull-srcs", - srcs: [ - "core/java/android/annotation/NonNull.java", - ], -} - -filegroup { name: "framework-media-annotation-srcs", srcs: [ "core/java/android/annotation/CallbackExecutor.java", diff --git a/StubLibraries.bp b/StubLibraries.bp index afe7b810e294..84b36255df51 100644 --- a/StubLibraries.bp +++ b/StubLibraries.bp @@ -49,7 +49,6 @@ stubs_defaults { ":opt-net-voip-srcs", ":core-current-stubs-source", ":core_public_api_files", - ":ike-api-srcs", ], libs: ["framework-internal-utils"], installable: false, diff --git a/apex/sdkextensions/Android.bp b/apex/sdkextensions/Android.bp index 4c5c2b2cfd4f..25765afb3ab9 100644 --- a/apex/sdkextensions/Android.bp +++ b/apex/sdkextensions/Android.bp @@ -28,7 +28,6 @@ apex_defaults { name: "com.android.sdkext-defaults", java_libs: [ "framework-sdkextensions" ], prebuilts: [ - "com.android.sdkext.ldconfig", "derive_sdk.rc", ], key: "com.android.sdkext.key", @@ -51,13 +50,6 @@ android_app_certificate { certificate: "com.android.sdkext", } -prebuilt_etc { - name: "com.android.sdkext.ldconfig", - src: "ld.config.txt", - filename: "ld.config.txt", - installable: false, -} - python_binary_host { name: "gen_sdkinfo", srcs: [ diff --git a/apex/sdkextensions/ld.config.txt b/apex/sdkextensions/ld.config.txt deleted file mode 100644 index dcc69b892760..000000000000 --- a/apex/sdkextensions/ld.config.txt +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (C) 2019 The Android Open Source Project -# -# Bionic loader config file for the sdkextensions apex. - -dir.sdkextensions = /apex/com.android.sdkext/bin/ - -[sdkextensions] -additional.namespaces = platform - -namespace.default.isolated = true -namespace.default.links = platform -namespace.default.link.platform.allow_all_shared_libs = true - -############################################################################### -# "platform" namespace: used for NDK libraries -############################################################################### -namespace.platform.isolated = true -namespace.platform.search.paths = /system/${LIB} -namespace.platform.asan.search.paths = /data/asan/system/${LIB} - -# /system/lib/libc.so, etc are symlinks to /apex/com.android.lib/lib/bionic/libc.so, etc. -# Add /apex/... path to the permitted paths because linker uses realpath(3) -# to check the accessibility of the lib. We could add this to search.paths -# instead but that makes the resolution of bionic libs be dependent on -# the order of /system/lib and /apex/... in search.paths. If /apex/... -# is after /system/lib, then /apex/... is never tried because libc.so -# is always found in /system/lib but fails to pass the accessibility test -# because of its realpath. It's better to not depend on the ordering if -# possible. -namespace.platform.permitted.paths = /apex/com.android.runtime/${LIB}/bionic -namespace.platform.asan.permitted.paths = /apex/com.android.runtime/${LIB}/bionic diff --git a/api/current.txt b/api/current.txt index 20c2ca22fb07..4118bcc6baf8 100644 --- a/api/current.txt +++ b/api/current.txt @@ -11775,6 +11775,7 @@ package android.content.pm { field public static final String FEATURE_VR_HEADTRACKING = "android.hardware.vr.headtracking"; field @Deprecated public static final String FEATURE_VR_MODE = "android.software.vr.mode"; field public static final String FEATURE_VR_MODE_HIGH_PERFORMANCE = "android.hardware.vr.high_performance"; + field public static final String FEATURE_VULKAN_DEQP_LEVEL = "android.software.vulkan.deqp.level"; field public static final String FEATURE_VULKAN_HARDWARE_COMPUTE = "android.hardware.vulkan.compute"; field public static final String FEATURE_VULKAN_HARDWARE_LEVEL = "android.hardware.vulkan.level"; field public static final String FEATURE_VULKAN_HARDWARE_VERSION = "android.hardware.vulkan.version"; diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt index 5f2af405bbdb..1b72fc3db058 100644 --- a/api/module-lib-current.txt +++ b/api/module-lib-current.txt @@ -30,7 +30,6 @@ package android.net { } public class TetheringConstants { - ctor public TetheringConstants(); field public static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType"; field public static final String EXTRA_PROVISION_CALLBACK = "extraProvisionCallback"; field public static final String EXTRA_REM_TETHER_TYPE = "extraRemTetherType"; diff --git a/api/module-lib-lint-baseline.txt b/api/module-lib-lint-baseline.txt index 6e59596cb05f..56f7a02260a7 100644 --- a/api/module-lib-lint-baseline.txt +++ b/api/module-lib-lint-baseline.txt @@ -27,7 +27,3 @@ PrivateSuperclass: android.location.GnssAntennaInfo.PhaseCenterVariationCorrecti Public class android.location.GnssAntennaInfo.PhaseCenterVariationCorrections extends private class android.location.GnssAntennaInfo.SphericalCorrections PrivateSuperclass: android.location.GnssAntennaInfo.SignalGainCorrections: Public class android.location.GnssAntennaInfo.SignalGainCorrections extends private class android.location.GnssAntennaInfo.SphericalCorrections - - -StaticUtils: android.net.TetheringConstants: - Fully-static utility classes must not have constructor diff --git a/api/system-current.txt b/api/system-current.txt index 971ea08651b4..3e853a9e02d3 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -5001,337 +5001,6 @@ package android.net.apf { } -package android.net.eap { - - public final class EapSessionConfig { - } - - public static final class EapSessionConfig.Builder { - ctor public EapSessionConfig.Builder(); - method @NonNull public android.net.eap.EapSessionConfig build(); - method @NonNull public android.net.eap.EapSessionConfig.Builder setEapAkaConfig(int, int); - method @NonNull public android.net.eap.EapSessionConfig.Builder setEapAkaPrimeConfig(int, int, @NonNull String, boolean); - method @NonNull public android.net.eap.EapSessionConfig.Builder setEapIdentity(@NonNull byte[]); - method @NonNull public android.net.eap.EapSessionConfig.Builder setEapMsChapV2Config(@NonNull String, @NonNull String); - method @NonNull public android.net.eap.EapSessionConfig.Builder setEapSimConfig(int, int); - } - - public static class EapSessionConfig.EapAkaConfig extends android.net.eap.EapSessionConfig.EapUiccConfig { - } - - public static class EapSessionConfig.EapAkaPrimeConfig extends android.net.eap.EapSessionConfig.EapAkaConfig { - method public boolean allowsMismatchedNetworkNames(); - method @NonNull public String getNetworkName(); - } - - public abstract static class EapSessionConfig.EapMethodConfig { - method public int getMethodType(); - } - - public static class EapSessionConfig.EapMsChapV2Config extends android.net.eap.EapSessionConfig.EapMethodConfig { - method @NonNull public String getPassword(); - method @NonNull public String getUsername(); - } - - public static class EapSessionConfig.EapSimConfig extends android.net.eap.EapSessionConfig.EapUiccConfig { - } - - public abstract static class EapSessionConfig.EapUiccConfig extends android.net.eap.EapSessionConfig.EapMethodConfig { - method public int getAppType(); - method public int getSubId(); - } - -} - -package android.net.ipsec.ike { - - public final class ChildSaProposal extends android.net.ipsec.ike.SaProposal { - } - - public static final class ChildSaProposal.Builder { - ctor public ChildSaProposal.Builder(); - method @NonNull public android.net.ipsec.ike.ChildSaProposal.Builder addDhGroup(int); - method @NonNull public android.net.ipsec.ike.ChildSaProposal.Builder addEncryptionAlgorithm(int, int); - method @NonNull public android.net.ipsec.ike.ChildSaProposal.Builder addIntegrityAlgorithm(int); - method @NonNull public android.net.ipsec.ike.ChildSaProposal build(); - } - - public interface ChildSessionCallback { - method public void onClosed(); - method public void onClosedExceptionally(@NonNull android.net.ipsec.ike.exceptions.IkeException); - method public void onIpSecTransformCreated(@NonNull android.net.IpSecTransform, int); - method public void onIpSecTransformDeleted(@NonNull android.net.IpSecTransform, int); - method public void onOpened(@NonNull android.net.ipsec.ike.ChildSessionConfiguration); - } - - public final class ChildSessionConfiguration { - method @NonNull public java.util.List<android.net.ipsec.ike.IkeTrafficSelector> getInboundTrafficSelectors(); - method @NonNull public java.util.List<android.net.LinkAddress> getInternalAddresses(); - method @NonNull public java.util.List<java.net.InetAddress> getInternalDhcpServers(); - method @NonNull public java.util.List<java.net.InetAddress> getInternalDnsServers(); - method @NonNull public java.util.List<android.net.IpPrefix> getInternalSubnets(); - method @NonNull public java.util.List<android.net.ipsec.ike.IkeTrafficSelector> getOutboundTrafficSelectors(); - } - - public abstract class ChildSessionParams { - method public long getHardLifetime(); - method @NonNull public java.util.List<android.net.ipsec.ike.IkeTrafficSelector> getLocalTrafficSelectors(); - method @NonNull public java.util.List<android.net.ipsec.ike.IkeTrafficSelector> getRemoteTrafficSelectors(); - method @NonNull public java.util.List<android.net.ipsec.ike.ChildSaProposal> getSaProposals(); - method public long getSoftLifetime(); - } - - public class IkeFqdnIdentification extends android.net.ipsec.ike.IkeIdentification { - ctor public IkeFqdnIdentification(@NonNull String); - field @NonNull public final String fqdn; - } - - public abstract class IkeIdentification { - } - - public final class IkeIpv4AddrIdentification extends android.net.ipsec.ike.IkeIdentification { - ctor public IkeIpv4AddrIdentification(@NonNull java.net.Inet4Address); - field @NonNull public final java.net.Inet4Address ipv4Address; - } - - public class IkeIpv6AddrIdentification extends android.net.ipsec.ike.IkeIdentification { - ctor public IkeIpv6AddrIdentification(@NonNull java.net.Inet6Address); - field @NonNull public final java.net.Inet6Address ipv6Address; - } - - public final class IkeKeyIdIdentification extends android.net.ipsec.ike.IkeIdentification { - ctor public IkeKeyIdIdentification(@NonNull byte[]); - field @NonNull public final byte[] keyId; - } - - public final class IkeRfc822AddrIdentification extends android.net.ipsec.ike.IkeIdentification { - ctor public IkeRfc822AddrIdentification(@NonNull String); - field @NonNull public final String rfc822Name; - } - - public final class IkeSaProposal extends android.net.ipsec.ike.SaProposal { - method @NonNull public java.util.List<java.lang.Integer> getPseudorandomFunctions(); - } - - public static final class IkeSaProposal.Builder { - ctor public IkeSaProposal.Builder(); - method @NonNull public android.net.ipsec.ike.IkeSaProposal.Builder addDhGroup(int); - method @NonNull public android.net.ipsec.ike.IkeSaProposal.Builder addEncryptionAlgorithm(int, int); - method @NonNull public android.net.ipsec.ike.IkeSaProposal.Builder addIntegrityAlgorithm(int); - method @NonNull public android.net.ipsec.ike.IkeSaProposal.Builder addPseudorandomFunction(int); - method @NonNull public android.net.ipsec.ike.IkeSaProposal build(); - } - - public final class IkeSession implements java.lang.AutoCloseable { - ctor public IkeSession(@NonNull android.content.Context, @NonNull android.net.ipsec.ike.IkeSessionParams, @NonNull android.net.ipsec.ike.ChildSessionParams, @NonNull java.util.concurrent.Executor, @NonNull android.net.ipsec.ike.IkeSessionCallback, @NonNull android.net.ipsec.ike.ChildSessionCallback); - method public void close(); - method public void closeChildSession(@NonNull android.net.ipsec.ike.ChildSessionCallback); - method public void kill(); - method public void openChildSession(@NonNull android.net.ipsec.ike.ChildSessionParams, @NonNull android.net.ipsec.ike.ChildSessionCallback); - } - - public interface IkeSessionCallback { - method public void onClosed(); - method public void onClosedExceptionally(@NonNull android.net.ipsec.ike.exceptions.IkeException); - method public void onError(@NonNull android.net.ipsec.ike.exceptions.IkeProtocolException); - method public void onOpened(@NonNull android.net.ipsec.ike.IkeSessionConfiguration); - } - - public final class IkeSessionConfiguration { - method @NonNull public java.util.List<java.net.InetAddress> getPcscfServers(); - method @NonNull public String getRemoteApplicationVersion(); - method @NonNull public java.util.List<byte[]> getRemoteVendorIDs(); - method public boolean isIkeExtensionEnabled(int); - field public static final int EXTENSION_TYPE_FRAGMENTATION = 1; // 0x1 - field public static final int EXTENSION_TYPE_MOBIKE = 2; // 0x2 - } - - public final class IkeSessionParams { - method @NonNull public java.util.List<android.net.ipsec.ike.IkeSessionParams.IkeConfigRequest> getConfigurationRequests(); - method public long getHardLifetime(); - method @NonNull public android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig getLocalAuthConfig(); - method @NonNull public android.net.ipsec.ike.IkeIdentification getLocalIdentification(); - method @NonNull public android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig getRemoteAuthConfig(); - method @NonNull public android.net.ipsec.ike.IkeIdentification getRemoteIdentification(); - method @NonNull public java.util.List<android.net.ipsec.ike.IkeSaProposal> getSaProposals(); - method @NonNull public java.net.InetAddress getServerAddress(); - method public long getSoftLifetime(); - method @NonNull public android.net.IpSecManager.UdpEncapsulationSocket getUdpEncapsulationSocket(); - } - - public static final class IkeSessionParams.Builder { - ctor public IkeSessionParams.Builder(); - method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder addPcscfServerRequest(@NonNull java.net.InetAddress); - method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder addPcscfServerRequest(int); - method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder addSaProposal(@NonNull android.net.ipsec.ike.IkeSaProposal); - method @NonNull public android.net.ipsec.ike.IkeSessionParams build(); - method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setAuthDigitalSignature(@Nullable java.security.cert.X509Certificate, @NonNull java.security.cert.X509Certificate, @NonNull java.security.PrivateKey); - method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setAuthDigitalSignature(@Nullable java.security.cert.X509Certificate, @NonNull java.security.cert.X509Certificate, @NonNull java.util.List<java.security.cert.X509Certificate>, @NonNull java.security.PrivateKey); - method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setAuthEap(@Nullable java.security.cert.X509Certificate, @NonNull android.net.eap.EapSessionConfig); - method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setAuthPsk(@NonNull byte[]); - method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setLifetime(long, long); - method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setLocalIdentification(@NonNull android.net.ipsec.ike.IkeIdentification); - method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setRemoteIdentification(@NonNull android.net.ipsec.ike.IkeIdentification); - method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setServerAddress(@NonNull java.net.InetAddress); - method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setUdpEncapsulationSocket(@NonNull android.net.IpSecManager.UdpEncapsulationSocket); - } - - public static interface IkeSessionParams.ConfigRequestIpv4PcscfServer extends android.net.ipsec.ike.IkeSessionParams.IkeConfigRequest { - method @Nullable public java.net.Inet4Address getAddress(); - } - - public static interface IkeSessionParams.ConfigRequestIpv6PcscfServer extends android.net.ipsec.ike.IkeSessionParams.IkeConfigRequest { - method @Nullable public java.net.Inet6Address getAddress(); - } - - public abstract static class IkeSessionParams.IkeAuthConfig { - } - - public static class IkeSessionParams.IkeAuthDigitalSignLocalConfig extends android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig { - method @NonNull public java.security.cert.X509Certificate getClientEndCertificate(); - method @NonNull public java.util.List<java.security.cert.X509Certificate> getIntermediateCertificates(); - method @NonNull public java.security.PrivateKey getPrivateKey(); - } - - public static class IkeSessionParams.IkeAuthDigitalSignRemoteConfig extends android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig { - method @Nullable public java.security.cert.X509Certificate getRemoteCaCert(); - } - - public static class IkeSessionParams.IkeAuthEapConfig extends android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig { - method @NonNull public android.net.eap.EapSessionConfig getEapConfig(); - } - - public static class IkeSessionParams.IkeAuthPskConfig extends android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig { - method @NonNull public byte[] getPsk(); - } - - public static interface IkeSessionParams.IkeConfigRequest { - } - - public final class IkeTrafficSelector { - ctor public IkeTrafficSelector(int, int, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress); - field public final int endPort; - field @NonNull public final java.net.InetAddress endingAddress; - field public final int startPort; - field @NonNull public final java.net.InetAddress startingAddress; - } - - public abstract class SaProposal { - method @NonNull public java.util.List<java.lang.Integer> getDhGroups(); - method @NonNull public java.util.List<android.util.Pair<java.lang.Integer,java.lang.Integer>> getEncryptionAlgorithms(); - method @NonNull public java.util.List<java.lang.Integer> getIntegrityAlgorithms(); - field public static final int DH_GROUP_1024_BIT_MODP = 2; // 0x2 - field public static final int DH_GROUP_2048_BIT_MODP = 14; // 0xe - field public static final int DH_GROUP_NONE = 0; // 0x0 - field public static final int ENCRYPTION_ALGORITHM_3DES = 3; // 0x3 - field public static final int ENCRYPTION_ALGORITHM_AES_CBC = 12; // 0xc - field public static final int ENCRYPTION_ALGORITHM_AES_GCM_12 = 19; // 0x13 - field public static final int ENCRYPTION_ALGORITHM_AES_GCM_16 = 20; // 0x14 - field public static final int ENCRYPTION_ALGORITHM_AES_GCM_8 = 18; // 0x12 - field public static final int INTEGRITY_ALGORITHM_AES_XCBC_96 = 5; // 0x5 - field public static final int INTEGRITY_ALGORITHM_HMAC_SHA1_96 = 2; // 0x2 - field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_256_128 = 12; // 0xc - field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_384_192 = 13; // 0xd - field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_512_256 = 14; // 0xe - field public static final int INTEGRITY_ALGORITHM_NONE = 0; // 0x0 - field public static final int KEY_LEN_AES_128 = 128; // 0x80 - field public static final int KEY_LEN_AES_192 = 192; // 0xc0 - field public static final int KEY_LEN_AES_256 = 256; // 0x100 - field public static final int KEY_LEN_UNUSED = 0; // 0x0 - field public static final int PSEUDORANDOM_FUNCTION_AES128_XCBC = 4; // 0x4 - field public static final int PSEUDORANDOM_FUNCTION_HMAC_SHA1 = 2; // 0x2 - } - - public final class TransportModeChildSessionParams extends android.net.ipsec.ike.ChildSessionParams { - } - - public static final class TransportModeChildSessionParams.Builder { - ctor public TransportModeChildSessionParams.Builder(); - method @NonNull public android.net.ipsec.ike.TransportModeChildSessionParams.Builder addInboundTrafficSelectors(@NonNull android.net.ipsec.ike.IkeTrafficSelector); - method @NonNull public android.net.ipsec.ike.TransportModeChildSessionParams.Builder addOutboundTrafficSelectors(@NonNull android.net.ipsec.ike.IkeTrafficSelector); - method @NonNull public android.net.ipsec.ike.TransportModeChildSessionParams.Builder addSaProposal(@NonNull android.net.ipsec.ike.ChildSaProposal); - method @NonNull public android.net.ipsec.ike.TransportModeChildSessionParams build(); - method @NonNull public android.net.ipsec.ike.TransportModeChildSessionParams.Builder setLifetime(long, long); - } - - public final class TunnelModeChildSessionParams extends android.net.ipsec.ike.ChildSessionParams { - method @NonNull public java.util.List<android.net.ipsec.ike.TunnelModeChildSessionParams.TunnelModeChildConfigRequest> getConfigurationRequests(); - } - - public static final class TunnelModeChildSessionParams.Builder { - ctor public TunnelModeChildSessionParams.Builder(); - method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addInboundTrafficSelectors(@NonNull android.net.ipsec.ike.IkeTrafficSelector); - method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addInternalAddressRequest(int); - method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addInternalAddressRequest(@NonNull java.net.Inet4Address); - method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addInternalAddressRequest(@NonNull java.net.Inet6Address, int); - method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addInternalDhcpServerRequest(int); - method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addInternalDnsServerRequest(int); - method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addOutboundTrafficSelectors(@NonNull android.net.ipsec.ike.IkeTrafficSelector); - method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addSaProposal(@NonNull android.net.ipsec.ike.ChildSaProposal); - method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams build(); - method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder setLifetime(long, long); - } - - public static interface TunnelModeChildSessionParams.ConfigRequestIpv4Address extends android.net.ipsec.ike.TunnelModeChildSessionParams.TunnelModeChildConfigRequest { - method @Nullable public java.net.Inet4Address getAddress(); - } - - public static interface TunnelModeChildSessionParams.ConfigRequestIpv4DhcpServer extends android.net.ipsec.ike.TunnelModeChildSessionParams.TunnelModeChildConfigRequest { - method @Nullable public java.net.Inet4Address getAddress(); - } - - public static interface TunnelModeChildSessionParams.ConfigRequestIpv4DnsServer extends android.net.ipsec.ike.TunnelModeChildSessionParams.TunnelModeChildConfigRequest { - method @Nullable public java.net.Inet4Address getAddress(); - } - - public static interface TunnelModeChildSessionParams.ConfigRequestIpv4Netmask extends android.net.ipsec.ike.TunnelModeChildSessionParams.TunnelModeChildConfigRequest { - } - - public static interface TunnelModeChildSessionParams.ConfigRequestIpv6Address extends android.net.ipsec.ike.TunnelModeChildSessionParams.TunnelModeChildConfigRequest { - method @Nullable public java.net.Inet6Address getAddress(); - method public int getPrefixLength(); - } - - public static interface TunnelModeChildSessionParams.ConfigRequestIpv6DnsServer extends android.net.ipsec.ike.TunnelModeChildSessionParams.TunnelModeChildConfigRequest { - method @Nullable public java.net.Inet6Address getAddress(); - } - - public static interface TunnelModeChildSessionParams.TunnelModeChildConfigRequest { - } - -} - -package android.net.ipsec.ike.exceptions { - - public abstract class IkeException extends java.lang.Exception { - } - - public final class IkeInternalException extends android.net.ipsec.ike.exceptions.IkeException { - } - - public abstract class IkeProtocolException extends android.net.ipsec.ike.exceptions.IkeException { - method @Nullable public byte[] getErrorData(); - method public int getErrorType(); - field public static final int ERROR_TYPE_AUTHENTICATION_FAILED = 24; // 0x18 - field public static final int ERROR_TYPE_CHILD_SA_NOT_FOUND = 44; // 0x2c - field public static final int ERROR_TYPE_FAILED_CP_REQUIRED = 37; // 0x25 - field public static final int ERROR_TYPE_INTERNAL_ADDRESS_FAILURE = 36; // 0x24 - field public static final int ERROR_TYPE_INVALID_IKE_SPI = 4; // 0x4 - field public static final int ERROR_TYPE_INVALID_KE_PAYLOAD = 17; // 0x11 - field public static final int ERROR_TYPE_INVALID_MAJOR_VERSION = 5; // 0x5 - field public static final int ERROR_TYPE_INVALID_MESSAGE_ID = 9; // 0x9 - field public static final int ERROR_TYPE_INVALID_SELECTORS = 39; // 0x27 - field public static final int ERROR_TYPE_INVALID_SYNTAX = 7; // 0x7 - field public static final int ERROR_TYPE_NO_ADDITIONAL_SAS = 35; // 0x23 - field public static final int ERROR_TYPE_NO_PROPOSAL_CHOSEN = 14; // 0xe - field public static final int ERROR_TYPE_SINGLE_PAIR_REQUIRED = 34; // 0x22 - field public static final int ERROR_TYPE_TEMPORARY_FAILURE = 43; // 0x2b - field public static final int ERROR_TYPE_TS_UNACCEPTABLE = 38; // 0x26 - field public static final int ERROR_TYPE_UNSUPPORTED_CRITICAL_PAYLOAD = 1; // 0x1 - } - -} - package android.net.metrics { public final class ApfProgramEvent implements android.net.metrics.IpConnectivityLog.Event { diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index 6cd34aecaa0f..7a63493376e6 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -355,7 +355,7 @@ message Atom { BootTimeEventElapsedTime boot_time_event_elapsed_time_reported = 240; BootTimeEventUtcTime boot_time_event_utc_time_reported = 241; BootTimeEventErrorCode boot_time_event_error_code_reported = 242; - UserspaceRebootReported userspace_reboot_reported = 243; + UserspaceRebootReported userspace_reboot_reported = 243 [(log_from_module) = "framework"]; } // Pulled events will start at field 10000. diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 93b90b410c1c..e17dda9a7913 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -2147,6 +2147,23 @@ public abstract class PackageManager { /** * Feature for {@link #getSystemAvailableFeatures} and + * {@link #hasSystemFeature(String, int)}: If this feature is supported, the feature version + * specifies a date such that the device is known to pass the Vulkan dEQP test suite associated + * with that date. The date is encoded as follows: + * <ul> + * <li>Year in bits 31-16</li> + * <li>Month in bits 15-8</li> + * <li>Day in bits 7-0</li> + * </ul> + * <p> + * Example: 2019-03-01 is encoded as 0x07E30301, and would indicate that the device passes the + * Vulkan dEQP test suite version that was current on 2019-03-01. + */ + @SdkConstant(SdkConstantType.FEATURE) + public static final String FEATURE_VULKAN_DEQP_LEVEL = "android.software.vulkan.deqp.level"; + + /** + * Feature for {@link #getSystemAvailableFeatures} and * {@link #hasSystemFeature}: The device includes broadcast radio tuner. * @hide */ diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 9cf751d66d92..589b1aaf05f1 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -1279,7 +1279,8 @@ public class ConnectivityManager { @UnsupportedAppUsage public NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId) { try { - return mService.getDefaultNetworkCapabilitiesForUser(userId); + return mService.getDefaultNetworkCapabilitiesForUser( + userId, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1361,7 +1362,7 @@ public class ConnectivityManager { @Nullable public NetworkCapabilities getNetworkCapabilities(@Nullable Network network) { try { - return mService.getNetworkCapabilities(network); + return mService.getNetworkCapabilities(network, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4035,10 +4036,9 @@ public class ConnectivityManager { @NonNull PendingIntent operation) { printStackTrace(); checkPendingIntentNotNull(operation); - final String callingPackageName = mContext.getOpPackageName(); try { mService.pendingRequestForNetwork( - request.networkCapabilities, operation, callingPackageName); + request.networkCapabilities, operation, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { @@ -4150,10 +4150,9 @@ public class ConnectivityManager { @NonNull PendingIntent operation) { printStackTrace(); checkPendingIntentNotNull(operation); - final String callingPackageName = mContext.getOpPackageName(); try { mService.pendingListenForNetwork( - request.networkCapabilities, operation, callingPackageName); + request.networkCapabilities, operation, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 3a55461a77d2..14345608e94f 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -59,7 +59,8 @@ interface IConnectivityManager NetworkInfo[] getAllNetworkInfo(); Network getNetworkForType(int networkType); Network[] getAllNetworks(); - NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId); + NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser( + int userId, String callingPackageName); boolean isNetworkSupported(int networkType); @@ -68,7 +69,7 @@ interface IConnectivityManager LinkProperties getLinkPropertiesForType(int networkType); LinkProperties getLinkProperties(in Network network); - NetworkCapabilities getNetworkCapabilities(in Network network); + NetworkCapabilities getNetworkCapabilities(in Network network, String callingPackageName); @UnsupportedAppUsage NetworkState[] getAllNetworkState(); diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index ef4a9e5f3b5d..873d6e914629 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -830,6 +830,23 @@ public final class NetworkCapabilities implements Parcelable { * <p>This field keeps track of the UID of the app that created this network and is in charge of * its lifecycle. This could be the UID of apps such as the Wifi network suggestor, the running * VPN, or Carrier Service app managing a cellular data connection. + * + * <p>For NetworkCapability instances being sent from ConnectivityService, this value MUST be + * reset to Process.INVALID_UID unless all the following conditions are met: + * + * <ol> + * <li>The destination app is the network owner + * <li>The destination app has the ACCESS_FINE_LOCATION permission granted + * <li>The user's location toggle is on + * </ol> + * + * This is because the owner UID is location-sensitive. The apps that request a network could + * know where the device is if they can tell for sure the system has connected to the network + * they requested. + * + * <p>This is populated by the network agents and for the NetworkCapabilities instance sent by + * an app to the System Server, the value MUST be reset to Process.INVALID_UID by the system + * server. */ private int mOwnerUid = Process.INVALID_UID; @@ -842,7 +859,16 @@ public final class NetworkCapabilities implements Parcelable { } /** - * Retrieves the UID of the owner app. + * Retrieves the UID of the app that owns this network. + * + * <p>For user privacy reasons, this field will only be populated if: + * + * <ol> + * <li>The calling app is the network owner + * <li>The calling app has the ACCESS_FINE_LOCATION permission granted + * <li>The user's location toggle is on + * </ol> + * */ public int getOwnerUid() { return mOwnerUid; @@ -880,8 +906,9 @@ public final class NetworkCapabilities implements Parcelable { * @param administratorUids the UIDs to be set as administrators of this Network. * @hide */ + @NonNull @SystemApi - public @NonNull NetworkCapabilities setAdministratorUids( + public NetworkCapabilities setAdministratorUids( @NonNull final List<Integer> administratorUids) { mAdministratorUids.clear(); mAdministratorUids.addAll(administratorUids); diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 3842def8751d..dcbbb709c5a0 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -9739,11 +9739,17 @@ public final class Settings { private static final Validator BUGREPORT_IN_POWER_MENU_VALIDATOR = BOOLEAN_VALIDATOR; /** - * Whether ADB is enabled. + * Whether ADB over USB is enabled. */ public static final String ADB_ENABLED = "adb_enabled"; /** + * Whether ADB over Wifi is enabled. + * @hide + */ + public static final String ADB_WIFI_ENABLED = "adb_wifi_enabled"; + + /** * Whether Views are allowed to save their attribute data. * @hide */ diff --git a/core/java/com/android/internal/os/KernelCpuUidBpfMapReader.java b/core/java/com/android/internal/os/KernelCpuUidBpfMapReader.java new file mode 100644 index 000000000000..26f81d9db9c8 --- /dev/null +++ b/core/java/com/android/internal/os/KernelCpuUidBpfMapReader.java @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.os; + +import android.os.StrictMode; +import android.os.SystemClock; +import android.util.Slog; +import android.util.SparseArray; + +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * Reads cpu time bpf maps. + * + * It is implemented as singletons for each separate set of per-UID times. Get___Instance() method + * returns the corresponding reader instance. In order to prevent frequent GC, it reuses the same + * SparseArray to store data read from BPF maps. + * + * A KernelCpuUidBpfMapReader instance keeps an error counter. When the number of read errors within + * that instance accumulates to 5, this instance will reject all further read requests. + * + * Data fetched within last 500ms is considered fresh, since the reading lifecycle can take up to + * 25ms. KernelCpuUidBpfMapReader always tries to use cache if it is fresh and valid, but it can + * be disabled through a parameter. + * + * A KernelCpuUidBpfMapReader instance is thread-safe. It acquires a write lock when reading the bpf + * map, releases it right after, then acquires a read lock before returning a BpfMapIterator. Caller + * is responsible for closing BpfMapIterator (also auto-closable) after reading, otherwise deadlock + * will occur. + */ +public abstract class KernelCpuUidBpfMapReader { + private static final int ERROR_THRESHOLD = 5; + private static final long FRESHNESS_MS = 500L; + + private static final KernelCpuUidBpfMapReader FREQ_TIME_READER = + new KernelCpuUidFreqTimeBpfMapReader(); + + private static final KernelCpuUidBpfMapReader ACTIVE_TIME_READER = + new KernelCpuUidActiveTimeBpfMapReader(); + + private static final KernelCpuUidBpfMapReader CLUSTER_TIME_READER = + new KernelCpuUidClusterTimeBpfMapReader(); + + static KernelCpuUidBpfMapReader getFreqTimeReaderInstance() { + return FREQ_TIME_READER; + } + + static KernelCpuUidBpfMapReader getActiveTimeReaderInstance() { + return ACTIVE_TIME_READER; + } + + static KernelCpuUidBpfMapReader getClusterTimeReaderInstance() { + return CLUSTER_TIME_READER; + } + + final String mTag = this.getClass().getSimpleName(); + private int mErrors = 0; + private boolean mTracking = false; + protected SparseArray<long[]> mData = new SparseArray<>(); + private long mLastReadTime = 0; + protected final ReentrantReadWriteLock mLock = new ReentrantReadWriteLock(); + protected final ReentrantReadWriteLock.ReadLock mReadLock = mLock.readLock(); + protected final ReentrantReadWriteLock.WriteLock mWriteLock = mLock.writeLock(); + + public native boolean startTrackingBpfTimes(); + + protected abstract boolean readBpfData(); + + /** + * Returns an array of metadata used to inform the caller of 1) the size of array required by + * getNextUid and 2) how to interpret the raw data copied to that array. + */ + public abstract long[] getDataDimensions(); + + public void removeUidsInRange(int startUid, int endUid) { + if (mErrors > ERROR_THRESHOLD) { + return; + } + mWriteLock.lock(); + int firstIndex = mData.indexOfKey(startUid); + int lastIndex = mData.indexOfKey(endUid); + mData.removeAtRange(firstIndex, lastIndex - firstIndex + 1); + mWriteLock.unlock(); + } + + public BpfMapIterator open() { + return open(false); + } + + public BpfMapIterator open(boolean ignoreCache) { + if (mErrors > ERROR_THRESHOLD) { + return null; + } + if (!mTracking && !startTrackingBpfTimes()) { + Slog.w(mTag, "Failed to start tracking"); + mErrors++; + return null; + } + if (ignoreCache) { + mWriteLock.lock(); + } else { + mReadLock.lock(); + if (dataValid()) { + return new BpfMapIterator(); + } + mReadLock.unlock(); + mWriteLock.lock(); + if (dataValid()) { + mReadLock.lock(); + mWriteLock.unlock(); + return new BpfMapIterator(); + } + } + if (readBpfData()) { + mLastReadTime = SystemClock.elapsedRealtime(); + mReadLock.lock(); + mWriteLock.unlock(); + return new BpfMapIterator(); + } + + mWriteLock.unlock(); + mErrors++; + Slog.w(mTag, "Failed to read bpf times"); + return null; + } + + private boolean dataValid() { + return mData.size() > 0 && (SystemClock.elapsedRealtime() - mLastReadTime < FRESHNESS_MS); + } + + public class BpfMapIterator implements AutoCloseable { + private int mPos; + + public BpfMapIterator() { + }; + + public boolean getNextUid(long[] buf) { + if (mPos >= mData.size()) { + return false; + } + buf[0] = mData.keyAt(mPos); + System.arraycopy(mData.valueAt(mPos), 0, buf, 1, mData.valueAt(mPos).length); + mPos++; + return true; + } + + public void close() { + mReadLock.unlock(); + } + } + + public static class KernelCpuUidFreqTimeBpfMapReader extends KernelCpuUidBpfMapReader { + + private final native boolean removeUidRange(int startUid, int endUid); + + @Override + protected final native boolean readBpfData(); + + @Override + public final native long[] getDataDimensions(); + + @Override + public void removeUidsInRange(int startUid, int endUid) { + mWriteLock.lock(); + super.removeUidsInRange(startUid, endUid); + removeUidRange(startUid, endUid); + mWriteLock.unlock(); + } + } + + public static class KernelCpuUidActiveTimeBpfMapReader extends KernelCpuUidBpfMapReader { + + @Override + protected final native boolean readBpfData(); + + @Override + public final native long[] getDataDimensions(); + } + + public static class KernelCpuUidClusterTimeBpfMapReader extends KernelCpuUidBpfMapReader { + + @Override + protected final native boolean readBpfData(); + + @Override + public final native long[] getDataDimensions(); + } +} diff --git a/core/java/com/android/internal/os/KernelCpuUidTimeReader.java b/core/java/com/android/internal/os/KernelCpuUidTimeReader.java index e6d044f4722b..34e75fe57fc4 100644 --- a/core/java/com/android/internal/os/KernelCpuUidTimeReader.java +++ b/core/java/com/android/internal/os/KernelCpuUidTimeReader.java @@ -28,6 +28,7 @@ import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.KernelCpuProcStringReader.ProcFileIterator; +import com.android.internal.os.KernelCpuUidBpfMapReader.BpfMapIterator; import java.io.BufferedReader; import java.io.FileWriter; @@ -57,6 +58,8 @@ public abstract class KernelCpuUidTimeReader<T> { final SparseArray<T> mLastTimes = new SparseArray<>(); final KernelCpuProcStringReader mReader; final boolean mThrottle; + protected boolean mBpfTimesAvailable; + final KernelCpuUidBpfMapReader mBpfReader; private long mMinTimeBetweenRead = DEFAULT_MIN_TIME_BETWEEN_READ; private long mLastReadTimeMs = 0; @@ -73,9 +76,15 @@ public abstract class KernelCpuUidTimeReader<T> { void onUidCpuTime(int uid, T time); } - KernelCpuUidTimeReader(KernelCpuProcStringReader reader, boolean throttle) { + KernelCpuUidTimeReader(KernelCpuProcStringReader reader, @Nullable KernelCpuUidBpfMapReader bpfReader, boolean throttle) { mReader = reader; mThrottle = throttle; + mBpfReader = bpfReader; + mBpfTimesAvailable = (mBpfReader != null); + } + + KernelCpuUidTimeReader(KernelCpuProcStringReader reader, boolean throttle) { + this(reader, null, throttle); } /** @@ -151,9 +160,13 @@ public abstract class KernelCpuUidTimeReader<T> { } mLastTimes.put(startUid, null); mLastTimes.put(endUid, null); - final int firstIndex = mLastTimes.indexOfKey(startUid); - final int lastIndex = mLastTimes.indexOfKey(endUid); + int firstIndex = mLastTimes.indexOfKey(startUid); + int lastIndex = mLastTimes.indexOfKey(endUid); mLastTimes.removeAtRange(firstIndex, lastIndex - firstIndex + 1); + + if (mBpfTimesAvailable) { + mBpfReader.removeUidsInRange(startUid, endUid); + } } /** @@ -323,13 +336,13 @@ public abstract class KernelCpuUidTimeReader<T> { public KernelCpuUidFreqTimeReader(boolean throttle) { this(UID_TIMES_PROC_FILE, KernelCpuProcStringReader.getFreqTimeReaderInstance(), - throttle); + KernelCpuUidBpfMapReader.getFreqTimeReaderInstance(), throttle); } @VisibleForTesting public KernelCpuUidFreqTimeReader(String procFile, KernelCpuProcStringReader reader, - boolean throttle) { - super(reader, throttle); + KernelCpuUidBpfMapReader bpfReader, boolean throttle) { + super(reader, bpfReader, throttle); mProcFilePath = Paths.get(procFile); } @@ -370,19 +383,24 @@ public abstract class KernelCpuUidTimeReader<T> { if (!mAllUidTimesAvailable) { return null; } - final int oldMask = StrictMode.allowThreadDiskReadsMask(); - try (BufferedReader reader = Files.newBufferedReader(mProcFilePath)) { - if (readFreqs(reader.readLine()) == null) { + if (mBpfTimesAvailable) { + readFreqsThroughBpf(); + } + if (mCpuFreqs == null) { + final int oldMask = StrictMode.allowThreadDiskReadsMask(); + try (BufferedReader reader = Files.newBufferedReader(mProcFilePath)) { + if (readFreqs(reader.readLine()) == null) { + return null; + } + } catch (IOException e) { + if (++mErrors >= MAX_ERROR_COUNT) { + mAllUidTimesAvailable = false; + } + Slog.e(mTag, "Failed to read " + UID_TIMES_PROC_FILE + ": " + e); return null; + } finally { + StrictMode.setThreadPolicyMask(oldMask); } - } catch (IOException e) { - if (++mErrors >= MAX_ERROR_COUNT) { - mAllUidTimesAvailable = false; - } - Slog.e(mTag, "Failed to read " + UID_TIMES_PROC_FILE + ": " + e); - return null; - } finally { - StrictMode.setThreadPolicyMask(oldMask); } // Check if the freqs in the proc file correspond to per-cluster freqs. final IntArray numClusterFreqs = extractClusterInfoFromProcFileFreqs(); @@ -402,6 +420,21 @@ public abstract class KernelCpuUidTimeReader<T> { return mCpuFreqs; } + private long[] readFreqsThroughBpf() { + if (!mBpfTimesAvailable || mBpfReader == null) { + return null; + } + mCpuFreqs = mBpfReader.getDataDimensions(); + if (mCpuFreqs == null) { + return null; + } + mFreqCount = mCpuFreqs.length; + mCurTimes = new long[mFreqCount]; + mDeltaTimes = new long[mFreqCount]; + mBuffer = new long[mFreqCount + 1]; + return mCpuFreqs; + } + private long[] readFreqs(String line) { if (line == null) { return null; @@ -422,8 +455,45 @@ public abstract class KernelCpuUidTimeReader<T> { return mCpuFreqs; } + private void processUidDelta(@Nullable Callback<long[]> cb) { + final int uid = (int) mBuffer[0]; + long[] lastTimes = mLastTimes.get(uid); + if (lastTimes == null) { + lastTimes = new long[mFreqCount]; + mLastTimes.put(uid, lastTimes); + } + copyToCurTimes(); + boolean notify = false; + boolean valid = true; + for (int i = 0; i < mFreqCount; i++) { + // Unit is 10ms. + mDeltaTimes[i] = mCurTimes[i] - lastTimes[i]; + if (mDeltaTimes[i] < 0) { + Slog.e(mTag, "Negative delta from freq time proc: " + mDeltaTimes[i]); + valid = false; + } + notify |= mDeltaTimes[i] > 0; + } + if (notify && valid) { + System.arraycopy(mCurTimes, 0, lastTimes, 0, mFreqCount); + if (cb != null) { + cb.onUidCpuTime(uid, mDeltaTimes); + } + } + } + @Override void readDeltaImpl(@Nullable Callback<long[]> cb) { + if (mBpfTimesAvailable) { + try (BpfMapIterator iter = mBpfReader.open(!mThrottle)) { + if (checkPrecondition(iter)) { + while (iter.getNextUid(mBuffer)) { + processUidDelta(cb); + } + return; + } + } + } try (ProcFileIterator iter = mReader.open(!mThrottle)) { if (!checkPrecondition(iter)) { return; @@ -434,36 +504,24 @@ public abstract class KernelCpuUidTimeReader<T> { Slog.wtf(mTag, "Invalid line: " + buf.toString()); continue; } - final int uid = (int) mBuffer[0]; - long[] lastTimes = mLastTimes.get(uid); - if (lastTimes == null) { - lastTimes = new long[mFreqCount]; - mLastTimes.put(uid, lastTimes); - } - copyToCurTimes(); - boolean notify = false; - boolean valid = true; - for (int i = 0; i < mFreqCount; i++) { - // Unit is 10ms. - mDeltaTimes[i] = mCurTimes[i] - lastTimes[i]; - if (mDeltaTimes[i] < 0) { - Slog.e(mTag, "Negative delta from freq time proc: " + mDeltaTimes[i]); - valid = false; - } - notify |= mDeltaTimes[i] > 0; - } - if (notify && valid) { - System.arraycopy(mCurTimes, 0, lastTimes, 0, mFreqCount); - if (cb != null) { - cb.onUidCpuTime(uid, mDeltaTimes); - } - } + processUidDelta(cb); } } } @Override void readAbsoluteImpl(Callback<long[]> cb) { + if (mBpfTimesAvailable) { + try (BpfMapIterator iter = mBpfReader.open(!mThrottle)) { + if (checkPrecondition(iter)) { + while (iter.getNextUid(mBuffer)) { + copyToCurTimes(); + cb.onUidCpuTime((int) mBuffer[0], mCurTimes); + } + return; + } + } + } try (ProcFileIterator iter = mReader.open(!mThrottle)) { if (!checkPrecondition(iter)) { return; @@ -481,9 +539,22 @@ public abstract class KernelCpuUidTimeReader<T> { } private void copyToCurTimes() { + long factor = mBpfTimesAvailable ? 1 : 10; for (int i = 0; i < mFreqCount; i++) { - mCurTimes[i] = mBuffer[i + 1] * 10; + mCurTimes[i] = mBuffer[i + 1] * factor; + } + } + + private boolean checkPrecondition(BpfMapIterator iter) { + if (iter == null) { + mBpfTimesAvailable = false; + return false; + } + if (mCpuFreqs != null) { + return true; } + mBpfTimesAvailable = (readFreqsThroughBpf() != null); + return mBpfTimesAvailable; } private boolean checkPrecondition(ProcFileIterator iter) { @@ -544,16 +615,43 @@ public abstract class KernelCpuUidTimeReader<T> { private long[] mBuffer; public KernelCpuUidActiveTimeReader(boolean throttle) { - super(KernelCpuProcStringReader.getActiveTimeReaderInstance(), throttle); + super(KernelCpuProcStringReader.getActiveTimeReaderInstance(), + KernelCpuUidBpfMapReader.getActiveTimeReaderInstance(), throttle); } @VisibleForTesting - public KernelCpuUidActiveTimeReader(KernelCpuProcStringReader reader, boolean throttle) { - super(reader, throttle); + public KernelCpuUidActiveTimeReader(KernelCpuProcStringReader reader, KernelCpuUidBpfMapReader bpfReader, boolean throttle) { + super(reader, bpfReader, throttle); + } + + private void processUidDelta(@Nullable Callback<Long> cb) { + int uid = (int) mBuffer[0]; + long cpuActiveTime = sumActiveTime(mBuffer, mBpfTimesAvailable ? 1 : 10); + if (cpuActiveTime > 0) { + long delta = cpuActiveTime - mLastTimes.get(uid, 0L); + if (delta > 0) { + mLastTimes.put(uid, cpuActiveTime); + if (cb != null) { + cb.onUidCpuTime(uid, delta); + } + } else if (delta < 0) { + Slog.e(mTag, "Negative delta from active time proc: " + delta); + } + } } @Override void readDeltaImpl(@Nullable Callback<Long> cb) { + if (mBpfTimesAvailable) { + try (BpfMapIterator iter = mBpfReader.open(!mThrottle)) { + if (checkPrecondition(iter)) { + while (iter.getNextUid(mBuffer)) { + processUidDelta(cb); + } + return; + } + } + } try (ProcFileIterator iter = mReader.open(!mThrottle)) { if (!checkPrecondition(iter)) { return; @@ -564,25 +662,30 @@ public abstract class KernelCpuUidTimeReader<T> { Slog.wtf(mTag, "Invalid line: " + buf.toString()); continue; } - int uid = (int) mBuffer[0]; - long cpuActiveTime = sumActiveTime(mBuffer); - if (cpuActiveTime > 0) { - long delta = cpuActiveTime - mLastTimes.get(uid, 0L); - if (delta > 0) { - mLastTimes.put(uid, cpuActiveTime); - if (cb != null) { - cb.onUidCpuTime(uid, delta); - } - } else if (delta < 0) { - Slog.e(mTag, "Negative delta from active time proc: " + delta); - } - } + processUidDelta(cb); } } } + private void processUidAbsolute(@Nullable Callback<Long> cb) { + long cpuActiveTime = sumActiveTime(mBuffer, mBpfTimesAvailable ? 1 : 10); + if (cpuActiveTime > 0) { + cb.onUidCpuTime((int) mBuffer[0], cpuActiveTime); + } + } + @Override void readAbsoluteImpl(Callback<Long> cb) { + if (mBpfTimesAvailable) { + try (BpfMapIterator iter = mBpfReader.open(!mThrottle)) { + if (checkPrecondition(iter)) { + while (iter.getNextUid(mBuffer)) { + processUidAbsolute(cb); + } + return; + } + } + } try (ProcFileIterator iter = mReader.open(!mThrottle)) { if (!checkPrecondition(iter)) { return; @@ -593,23 +696,38 @@ public abstract class KernelCpuUidTimeReader<T> { Slog.wtf(mTag, "Invalid line: " + buf.toString()); continue; } - long cpuActiveTime = sumActiveTime(mBuffer); - if (cpuActiveTime > 0) { - cb.onUidCpuTime((int) mBuffer[0], cpuActiveTime); - } + processUidAbsolute(cb); } } } - private static long sumActiveTime(long[] times) { + private static long sumActiveTime(long[] times, double factor) { // UID is stored at times[0]. double sum = 0; for (int i = 1; i < times.length; i++) { - sum += (double) times[i] * 10 / i; // Unit is 10ms. + sum += (double) times[i] * factor / i; // Unit is 10ms. } return (long) sum; } + private boolean checkPrecondition(BpfMapIterator iter) { + if (iter == null) { + mBpfTimesAvailable = false; + return false; + } + if (mCores > 0) { + return true; + } + long[] cores = mBpfReader.getDataDimensions(); + if (cores == null || cores.length < 1) { + mBpfTimesAvailable = false; + return false; + } + mCores = (int) cores[0]; + mBuffer = new long[mCores + 1]; + return true; + } + private boolean checkPrecondition(ProcFileIterator iter) { if (iter == null || !iter.hasNextLine()) { // Error logged in KernelCpuProcStringReader. @@ -664,16 +782,54 @@ public abstract class KernelCpuUidTimeReader<T> { private long[] mDeltaTime; public KernelCpuUidClusterTimeReader(boolean throttle) { - super(KernelCpuProcStringReader.getClusterTimeReaderInstance(), throttle); + super(KernelCpuProcStringReader.getClusterTimeReaderInstance(), + KernelCpuUidBpfMapReader.getClusterTimeReaderInstance(), throttle); } @VisibleForTesting - public KernelCpuUidClusterTimeReader(KernelCpuProcStringReader reader, boolean throttle) { - super(reader, throttle); + public KernelCpuUidClusterTimeReader(KernelCpuProcStringReader reader, + KernelCpuUidBpfMapReader bpfReader, boolean throttle) { + super(reader, bpfReader, throttle); + } + + void processUidDelta(@Nullable Callback<long[]> cb) { + int uid = (int) mBuffer[0]; + long[] lastTimes = mLastTimes.get(uid); + if (lastTimes == null) { + lastTimes = new long[mNumClusters]; + mLastTimes.put(uid, lastTimes); + } + sumClusterTime(); + boolean valid = true; + boolean notify = false; + for (int i = 0; i < mNumClusters; i++) { + mDeltaTime[i] = mCurTime[i] - lastTimes[i]; + if (mDeltaTime[i] < 0) { + Slog.e(mTag, "Negative delta from cluster time proc: " + mDeltaTime[i]); + valid = false; + } + notify |= mDeltaTime[i] > 0; + } + if (notify && valid) { + System.arraycopy(mCurTime, 0, lastTimes, 0, mNumClusters); + if (cb != null) { + cb.onUidCpuTime(uid, mDeltaTime); + } + } } @Override void readDeltaImpl(@Nullable Callback<long[]> cb) { + if (mBpfTimesAvailable) { + try (BpfMapIterator iter = mBpfReader.open(!mThrottle)) { + if (checkPrecondition(iter)) { + while (iter.getNextUid(mBuffer)) { + processUidDelta(cb); + } + return; + } + } + } try (ProcFileIterator iter = mReader.open(!mThrottle)) { if (!checkPrecondition(iter)) { return; @@ -684,35 +840,24 @@ public abstract class KernelCpuUidTimeReader<T> { Slog.wtf(mTag, "Invalid line: " + buf.toString()); continue; } - int uid = (int) mBuffer[0]; - long[] lastTimes = mLastTimes.get(uid); - if (lastTimes == null) { - lastTimes = new long[mNumClusters]; - mLastTimes.put(uid, lastTimes); - } - sumClusterTime(); - boolean valid = true; - boolean notify = false; - for (int i = 0; i < mNumClusters; i++) { - mDeltaTime[i] = mCurTime[i] - lastTimes[i]; - if (mDeltaTime[i] < 0) { - Slog.e(mTag, "Negative delta from cluster time proc: " + mDeltaTime[i]); - valid = false; - } - notify |= mDeltaTime[i] > 0; - } - if (notify && valid) { - System.arraycopy(mCurTime, 0, lastTimes, 0, mNumClusters); - if (cb != null) { - cb.onUidCpuTime(uid, mDeltaTime); - } - } + processUidDelta(cb); } } } @Override void readAbsoluteImpl(Callback<long[]> cb) { + if (mBpfTimesAvailable) { + try (BpfMapIterator iter = mBpfReader.open(!mThrottle)) { + if (checkPrecondition(iter)) { + while (iter.getNextUid(mBuffer)) { + sumClusterTime(); + cb.onUidCpuTime((int) mBuffer[0], mCurTime); + } + return; + } + } + } try (ProcFileIterator iter = mReader.open(!mThrottle)) { if (!checkPrecondition(iter)) { return; @@ -730,17 +875,45 @@ public abstract class KernelCpuUidTimeReader<T> { } private void sumClusterTime() { + double factor = mBpfTimesAvailable ? 1 : 10; // UID is stored at mBuffer[0]. int core = 1; for (int i = 0; i < mNumClusters; i++) { double sum = 0; for (int j = 1; j <= mCoresOnClusters[i]; j++) { - sum += (double) mBuffer[core++] * 10 / j; // Unit is 10ms. + sum += (double) mBuffer[core++] * factor / j; // Unit is 10ms. } mCurTime[i] = (long) sum; } } + private boolean checkPrecondition(BpfMapIterator iter) { + if (iter == null) { + mBpfTimesAvailable = false; + return false; + } + if (mNumClusters > 0) { + return true; + } + long[] coresOnClusters = mBpfReader.getDataDimensions(); + if (coresOnClusters == null || coresOnClusters.length < 1) { + mBpfTimesAvailable = false; + return false; + } + mNumClusters = coresOnClusters.length; + mCoresOnClusters = new int[mNumClusters]; + int cores = 0; + for (int i = 0; i < mNumClusters; i++) { + mCoresOnClusters[i] = (int) coresOnClusters[i]; + cores += mCoresOnClusters[i]; + } + mNumCores = cores; + mBuffer = new long[cores + 1]; + mCurTime = new long[mNumClusters]; + mDeltaTime = new long[mNumClusters]; + return true; + } + private boolean checkPrecondition(ProcFileIterator iter) { if (iter == null || !iter.hasNextLine()) { // Error logged in KernelCpuProcStringReader. diff --git a/core/java/com/android/internal/os/KernelSingleUidTimeReader.java b/core/java/com/android/internal/os/KernelSingleUidTimeReader.java index 3c43a11a8e9f..fc0ce6fb8c46 100644 --- a/core/java/com/android/internal/os/KernelSingleUidTimeReader.java +++ b/core/java/com/android/internal/os/KernelSingleUidTimeReader.java @@ -53,6 +53,8 @@ public class KernelSingleUidTimeReader { private int mReadErrorCounter; @GuardedBy("this") private boolean mSingleUidCpuTimesAvailable = true; + @GuardedBy("this") + private boolean mBpfTimesAvailable = true; // We use the freq count obtained from /proc/uid_time_in_state to decide how many longs // to read from each /proc/uid/<uid>/time_in_state. On the first read, verify if this is // correct and if not, set {@link #mSingleUidCpuTimesAvailable} to false. This flag will @@ -62,6 +64,8 @@ public class KernelSingleUidTimeReader { private final Injector mInjector; + private static final native boolean canReadBpfTimes(); + KernelSingleUidTimeReader(int cpuFreqsCount) { this(cpuFreqsCount, new Injector()); } @@ -83,6 +87,18 @@ public class KernelSingleUidTimeReader { if (!mSingleUidCpuTimesAvailable) { return null; } + if (mBpfTimesAvailable) { + final long[] cpuTimesMs = mInjector.readBpfData(uid); + if (cpuTimesMs.length == 0) { + mBpfTimesAvailable = false; + } else if (!mCpuFreqsCountVerified && cpuTimesMs.length != mCpuFreqsCount) { + mSingleUidCpuTimesAvailable = false; + return null; + } else { + mCpuFreqsCountVerified = true; + return computeDelta(uid, cpuTimesMs); + } + } // Read total cpu times from the proc file. final String procFile = new StringBuilder(PROC_FILE_DIR) .append(uid) @@ -230,6 +246,8 @@ public class KernelSingleUidTimeReader { public byte[] readData(String procFile) throws IOException { return Files.readAllBytes(Paths.get(procFile)); } + + public native long[] readBpfData(int uid); } @VisibleForTesting diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java index d3fe582ab4bd..9d0cb0115ee4 100644 --- a/core/java/com/android/internal/os/PowerProfile.java +++ b/core/java/com/android/internal/os/PowerProfile.java @@ -393,6 +393,9 @@ public class PowerProfile { } public int getNumCoresInCpuCluster(int cluster) { + if (cluster < 0 || cluster >= mCpuClusters.length) { + return 0; // index out of bound + } return mCpuClusters[cluster].numCpus; } diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 43df2e444932..872f26d1a143 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -207,6 +207,8 @@ cc_library_shared { "com_android_internal_os_AtomicDirectory.cpp", "com_android_internal_os_ClassLoaderFactory.cpp", "com_android_internal_os_FuseAppLoop.cpp", + "com_android_internal_os_KernelCpuUidBpfMapReader.cpp", + "com_android_internal_os_KernelSingleUidTimeReader.cpp", "com_android_internal_os_Zygote.cpp", "com_android_internal_os_ZygoteInit.cpp", "com_android_internal_util_VirtualRefBasePtr.cpp", @@ -303,6 +305,7 @@ cc_library_shared { "libdl", "libdl_android", "libstatslog", + "libtimeinstate", "server_configurable_flags", ], diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 5c3640e3b9a0..a2a671687eb6 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -230,6 +230,8 @@ extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env extern int register_com_android_internal_os_AtomicDirectory(JNIEnv *env); extern int register_com_android_internal_os_ClassLoaderFactory(JNIEnv* env); extern int register_com_android_internal_os_FuseAppLoop(JNIEnv* env); +extern int register_com_android_internal_os_KernelCpuUidBpfMapReader(JNIEnv *env); +extern int register_com_android_internal_os_KernelSingleUidTimeReader(JNIEnv *env); extern int register_com_android_internal_os_Zygote(JNIEnv *env); extern int register_com_android_internal_os_ZygoteInit(JNIEnv *env); extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv *env); @@ -1640,6 +1642,8 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_com_android_internal_content_NativeLibraryHelper), REG_JNI(register_com_android_internal_os_AtomicDirectory), REG_JNI(register_com_android_internal_os_FuseAppLoop), + REG_JNI(register_com_android_internal_os_KernelCpuUidBpfMapReader), + REG_JNI(register_com_android_internal_os_KernelSingleUidTimeReader), }; /* diff --git a/core/jni/com_android_internal_os_KernelCpuUidBpfMapReader.cpp b/core/jni/com_android_internal_os_KernelCpuUidBpfMapReader.cpp new file mode 100644 index 000000000000..7c68de504417 --- /dev/null +++ b/core/jni/com_android_internal_os_KernelCpuUidBpfMapReader.cpp @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "core_jni_helpers.h" + +#include <sys/sysinfo.h> + +#include <android-base/stringprintf.h> +#include <cputimeinstate.h> + +namespace android { + +static constexpr uint64_t NSEC_PER_MSEC = 1000000; + +static struct { + jclass clazz; + jmethodID put; + jmethodID get; +} gSparseArrayClassInfo; + +static jfieldID gmData; + +static jlongArray getUidArray(JNIEnv *env, jobject sparseAr, uint32_t uid, jsize sz) { + jlongArray ar = (jlongArray)env->CallObjectMethod(sparseAr, gSparseArrayClassInfo.get, uid); + if (!ar) { + ar = env->NewLongArray(sz); + if (ar == NULL) return ar; + env->CallVoidMethod(sparseAr, gSparseArrayClassInfo.put, uid, ar); + } + return ar; +} + +static void copy2DVecToArray(JNIEnv *env, jlongArray ar, std::vector<std::vector<uint64_t>> &vec) { + jsize start = 0; + for (auto &subVec : vec) { + for (uint32_t i = 0; i < subVec.size(); ++i) subVec[i] /= NSEC_PER_MSEC; + env->SetLongArrayRegion(ar, start, subVec.size(), + reinterpret_cast<const jlong *>(subVec.data())); + start += subVec.size(); + } +} + +static jboolean KernelCpuUidFreqTimeBpfMapReader_removeUidRange(JNIEnv *env, jclass, jint startUid, + jint endUid) { + for (uint32_t uid = startUid; uid <= endUid; ++uid) { + if (!android::bpf::clearUidTimes(uid)) return false; + } + return true; +} + +static jboolean KernelCpuUidFreqTimeBpfMapReader_readBpfData(JNIEnv *env, jobject thiz) { + static uint64_t lastUpdate = 0; + uint64_t newLastUpdate = lastUpdate; + auto sparseAr = env->GetObjectField(thiz, gmData); + if (sparseAr == NULL) return false; + auto data = android::bpf::getUidsUpdatedCpuFreqTimes(&newLastUpdate); + if (!data.has_value()) return false; + + jsize s = 0; + for (auto &[uid, times] : *data) { + if (s == 0) { + for (const auto &subVec : times) s += subVec.size(); + } + jlongArray ar = getUidArray(env, sparseAr, uid, s); + if (ar == NULL) return false; + copy2DVecToArray(env, ar, times); + } + lastUpdate = newLastUpdate; + return true; +} + +static jlongArray KernelCpuUidFreqTimeBpfMapReader_getDataDimensions(JNIEnv *env, jobject) { + auto freqs = android::bpf::getCpuFreqs(); + if (!freqs) return NULL; + + std::vector<uint64_t> allFreqs; + for (const auto &vec : *freqs) std::copy(vec.begin(), vec.end(), std::back_inserter(allFreqs)); + + auto ar = env->NewLongArray(allFreqs.size()); + if (ar != NULL) { + env->SetLongArrayRegion(ar, 0, allFreqs.size(), + reinterpret_cast<const jlong *>(allFreqs.data())); + } + return ar; +} + +static const JNINativeMethod gFreqTimeMethods[] = { + {"removeUidRange", "(II)Z", (void *)KernelCpuUidFreqTimeBpfMapReader_removeUidRange}, + {"readBpfData", "()Z", (void *)KernelCpuUidFreqTimeBpfMapReader_readBpfData}, + {"getDataDimensions", "()[J", (void *)KernelCpuUidFreqTimeBpfMapReader_getDataDimensions}, +}; + +static jboolean KernelCpuUidActiveTimeBpfMapReader_readBpfData(JNIEnv *env, jobject thiz) { + static uint64_t lastUpdate = 0; + uint64_t newLastUpdate = lastUpdate; + auto sparseAr = env->GetObjectField(thiz, gmData); + if (sparseAr == NULL) return false; + auto data = android::bpf::getUidsUpdatedConcurrentTimes(&newLastUpdate); + if (!data.has_value()) return false; + + for (auto &[uid, times] : *data) { + // TODO: revise calling code so we can divide by NSEC_PER_MSEC here instead + for (auto &time : times.active) time /= NSEC_PER_MSEC; + jlongArray ar = getUidArray(env, sparseAr, uid, times.active.size()); + if (ar == NULL) return false; + env->SetLongArrayRegion(ar, 0, times.active.size(), + reinterpret_cast<const jlong *>(times.active.data())); + } + lastUpdate = newLastUpdate; + return true; +} + +static jlongArray KernelCpuUidActiveTimeBpfMapReader_getDataDimensions(JNIEnv *env, jobject) { + jlong nCpus = get_nprocs_conf(); + + auto ar = env->NewLongArray(1); + if (ar != NULL) env->SetLongArrayRegion(ar, 0, 1, &nCpus); + return ar; +} + +static const JNINativeMethod gActiveTimeMethods[] = { + {"readBpfData", "()Z", (void *)KernelCpuUidActiveTimeBpfMapReader_readBpfData}, + {"getDataDimensions", "()[J", (void *)KernelCpuUidActiveTimeBpfMapReader_getDataDimensions}, +}; + +static jboolean KernelCpuUidClusterTimeBpfMapReader_readBpfData(JNIEnv *env, jobject thiz) { + static uint64_t lastUpdate = 0; + uint64_t newLastUpdate = lastUpdate; + auto sparseAr = env->GetObjectField(thiz, gmData); + if (sparseAr == NULL) return false; + auto data = android::bpf::getUidsUpdatedConcurrentTimes(&newLastUpdate); + if (!data.has_value()) return false; + + jsize s = 0; + for (auto &[uid, times] : *data) { + if (s == 0) { + for (const auto &subVec : times.policy) s += subVec.size(); + } + jlongArray ar = getUidArray(env, sparseAr, uid, s); + if (ar == NULL) return false; + copy2DVecToArray(env, ar, times.policy); + } + lastUpdate = newLastUpdate; + return true; +} + +static jlongArray KernelCpuUidClusterTimeBpfMapReader_getDataDimensions(JNIEnv *env, jobject) { + auto times = android::bpf::getUidConcurrentTimes(0); + if (!times.has_value()) return NULL; + + std::vector<jlong> clusterCores; + for (const auto &vec : times->policy) clusterCores.push_back(vec.size()); + auto ar = env->NewLongArray(clusterCores.size()); + if (ar != NULL) env->SetLongArrayRegion(ar, 0, clusterCores.size(), clusterCores.data()); + return ar; +} + +static const JNINativeMethod gClusterTimeMethods[] = { + {"readBpfData", "()Z", (void *)KernelCpuUidClusterTimeBpfMapReader_readBpfData}, + {"getDataDimensions", "()[J", + (void *)KernelCpuUidClusterTimeBpfMapReader_getDataDimensions}, +}; + +struct readerMethods { + const char *name; + const JNINativeMethod *methods; + int numMethods; +}; + +static const readerMethods gAllMethods[] = { + {"KernelCpuUidFreqTimeBpfMapReader", gFreqTimeMethods, NELEM(gFreqTimeMethods)}, + {"KernelCpuUidActiveTimeBpfMapReader", gActiveTimeMethods, NELEM(gActiveTimeMethods)}, + {"KernelCpuUidClusterTimeBpfMapReader", gClusterTimeMethods, NELEM(gClusterTimeMethods)}, +}; + +static jboolean KernelCpuUidBpfMapReader_startTrackingBpfTimes(JNIEnv *, jobject) { + return android::bpf::startTrackingUidTimes(); +} + +int register_com_android_internal_os_KernelCpuUidBpfMapReader(JNIEnv *env) { + gSparseArrayClassInfo.clazz = FindClassOrDie(env, "android/util/SparseArray"); + gSparseArrayClassInfo.clazz = MakeGlobalRefOrDie(env, gSparseArrayClassInfo.clazz); + gSparseArrayClassInfo.put = + GetMethodIDOrDie(env, gSparseArrayClassInfo.clazz, "put", "(ILjava/lang/Object;)V"); + gSparseArrayClassInfo.get = + GetMethodIDOrDie(env, gSparseArrayClassInfo.clazz, "get", "(I)Ljava/lang/Object;"); + constexpr auto readerName = "com/android/internal/os/KernelCpuUidBpfMapReader"; + constexpr JNINativeMethod method = {"startTrackingBpfTimes", "()Z", + (void *)KernelCpuUidBpfMapReader_startTrackingBpfTimes}; + + int ret = RegisterMethodsOrDie(env, readerName, &method, 1); + if (ret < 0) return ret; + auto c = FindClassOrDie(env, readerName); + gmData = GetFieldIDOrDie(env, c, "mData", "Landroid/util/SparseArray;"); + + for (const auto &m : gAllMethods) { + auto fullName = android::base::StringPrintf("%s$%s", readerName, m.name); + ret = RegisterMethodsOrDie(env, fullName.c_str(), m.methods, m.numMethods); + if (ret < 0) break; + } + return ret; +} + +} // namespace android diff --git a/core/jni/com_android_internal_os_KernelSingleUidTimeReader.cpp b/core/jni/com_android_internal_os_KernelSingleUidTimeReader.cpp new file mode 100644 index 000000000000..c0ecf33bd521 --- /dev/null +++ b/core/jni/com_android_internal_os_KernelSingleUidTimeReader.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "core_jni_helpers.h" + +#include <cputimeinstate.h> + +namespace android { + +static constexpr uint64_t NSEC_PER_MSEC = 1000000; + +static jlongArray copyVecsToArray(JNIEnv *env, std::vector<std::vector<uint64_t>> &vec) { + jsize s = 0; + for (const auto &subVec : vec) s += subVec.size(); + jlongArray ar = env->NewLongArray(s); + jsize start = 0; + for (auto &subVec : vec) { + for (uint32_t i = 0; i < subVec.size(); ++i) subVec[i] /= NSEC_PER_MSEC; + env->SetLongArrayRegion(ar, start, subVec.size(), + reinterpret_cast<const jlong*>(subVec.data())); + start += subVec.size(); + } + return ar; +} + +static jlongArray getUidCpuFreqTimeMs(JNIEnv *env, jclass, jint uid) { + auto out = android::bpf::getUidCpuFreqTimes(uid); + if (!out) return env->NewLongArray(0); + return copyVecsToArray(env, out.value()); +} + +static const JNINativeMethod g_single_methods[] = { + {"readBpfData", "(I)[J", (void *)getUidCpuFreqTimeMs}, +}; + +int register_com_android_internal_os_KernelSingleUidTimeReader(JNIEnv *env) { + return RegisterMethodsOrDie(env, "com/android/internal/os/KernelSingleUidTimeReader$Injector", + g_single_methods, NELEM(g_single_methods)); +} + +} diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 054195588102..c52c53f9549a 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2718,6 +2718,18 @@ <string name="config_customAdbPublicKeyConfirmationSecondaryUserComponent" >com.android.systemui/com.android.systemui.usb.UsbDebuggingSecondaryUserActivity</string> + <!-- Name of the activity or service that prompts the user to reject, accept, or whitelist + a wireless network for wireless debugging. + Can be customized for other product types --> + <string name="config_customAdbWifiNetworkConfirmationComponent" + >com.android.systemui/com.android.systemui.wifi.WifiDebuggingActivity</string> + + <!-- Name of the activity that prompts the secondary user to acknowledge she/he needs to + switch to the primary user to enable wireless debugging. + Can be customized for other product types --> + <string name="config_customAdbWifiNetworkConfirmationSecondaryUserComponent" + >com.android.systemui/com.android.systemui.wifi.WifiDebuggingSecondaryUserActivity</string> + <!-- Name of the dialog that is used to request the user's consent for a Platform VPN --> <string name="config_platformVpnConfirmDialogComponent" translatable="false" >com.android.vpndialogs/com.android.vpndialogs.PlatformVpnConfirmDialog</string> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 9bc0d969aed9..175870298f91 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -3642,6 +3642,12 @@ <!-- Message of notification shown when ADB is actively connected to the phone. --> <string name="adb_active_notification_message">Tap to turn off USB debugging</string> <string name="adb_active_notification_message" product="tv">Select to disable USB debugging.</string> + <!-- Title of notification shown when ADB Wireless is actively connected to the phone. [CHAR LIMIT=NONE] --> + <string name="adbwifi_active_notification_title">Wireless debugging connected</string> + <!-- Message of notification shown when ADB Wireless is actively connected to the phone. [CHAR LIMIT=NONE] --> + <string name="adbwifi_active_notification_message">Tap to turn off wireless debugging</string> + <!-- Message of notification shown when ADB Wireless is actively connected to the TV. [CHAR LIMIT=NONE] --> + <string name="adbwifi_active_notification_message" product="tv">Select to disable wireless debugging.</string> <!-- Title of notification shown when Test Harness Mode is enabled. [CHAR LIMIT=NONE] --> <string name="test_harness_mode_notification_title">Test Harness Mode enabled</string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index d1e449e13e0f..62cc7b3fc65e 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2090,6 +2090,8 @@ <java-symbol type="string" name="accessibility_binding_label" /> <java-symbol type="string" name="adb_active_notification_message" /> <java-symbol type="string" name="adb_active_notification_title" /> + <java-symbol type="string" name="adbwifi_active_notification_message" /> + <java-symbol type="string" name="adbwifi_active_notification_title" /> <java-symbol type="string" name="test_harness_mode_notification_title" /> <java-symbol type="string" name="test_harness_mode_notification_message" /> <java-symbol type="string" name="taking_remote_bugreport_notification_title" /> @@ -2232,6 +2234,8 @@ <java-symbol type="fraction" name="config_maximumScreenDimRatio" /> <java-symbol type="string" name="config_customAdbPublicKeyConfirmationComponent" /> <java-symbol type="string" name="config_customAdbPublicKeyConfirmationSecondaryUserComponent" /> + <java-symbol type="string" name="config_customAdbWifiNetworkConfirmationComponent" /> + <java-symbol type="string" name="config_customAdbWifiNetworkConfirmationSecondaryUserComponent" /> <java-symbol type="string" name="config_customVpnConfirmDialogComponent" /> <java-symbol type="string" name="config_customVpnAlwaysOnDisconnectedDialogComponent" /> <java-symbol type="string" name="config_platformVpnConfirmDialogComponent" /> diff --git a/core/res/res/xml/power_profile.xml b/core/res/res/xml/power_profile.xml index 899d630a51b7..d8ec72f33ddc 100644 --- a/core/res/res/xml/power_profile.xml +++ b/core/res/res/xml/power_profile.xml @@ -51,6 +51,12 @@ <value>0.1</value> <!-- ~1mA --> </array> + <!-- Additional power consumption by CPU excluding cluster and core when + running --> + <array name="cpu.active"> + <value>0.1</value> + </array> + <!-- A list of heterogeneous CPU clusters, where the value for each cluster represents the number of CPU cores for that cluster. diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index e60e5555cc9d..4b1691dc0a84 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -104,6 +104,7 @@ public class SettingsBackupTest { Settings.Global.ADAPTIVE_BATTERY_MANAGEMENT_ENABLED, Settings.Global.ADB_ALLOWED_CONNECTION_TIME, Settings.Global.ADB_ENABLED, + Settings.Global.ADB_WIFI_ENABLED, Settings.Global.ADD_USERS_WHEN_LOCKED, Settings.Global.AIRPLANE_MODE_ON, Settings.Global.AIRPLANE_MODE_RADIOS, diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java index a6329298b0f9..2ad8e18741f9 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java @@ -40,6 +40,7 @@ import org.junit.runners.Suite; BatteryStatsUserLifecycleTests.class, KernelCpuProcStringReaderTest.class, KernelCpuUidActiveTimeReaderTest.class, + KernelCpuUidBpfMapReaderTest.class, KernelCpuUidClusterTimeReaderTest.class, KernelCpuUidFreqTimeReaderTest.class, KernelCpuUidUserSysTimeReaderTest.class, diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidActiveTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidActiveTimeReaderTest.java index 1b13a9927beb..2ccd74e99116 100644 --- a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidActiveTimeReaderTest.java +++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidActiveTimeReaderTest.java @@ -21,11 +21,11 @@ import static org.junit.Assert.assertTrue; import android.content.Context; import android.os.FileUtils; +import android.util.SparseArray; import android.util.SparseLongArray; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeReader; @@ -33,11 +33,15 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; import java.io.BufferedWriter; import java.io.File; import java.io.IOException; import java.nio.file.Files; +import java.util.Arrays; +import java.util.Collection; import java.util.Random; /** @@ -46,14 +50,16 @@ import java.util.Random; * $ atest FrameworksCoreTests:com.android.internal.os.KernelCpuUidActiveTimeReaderTest */ @SmallTest -@RunWith(AndroidJUnit4.class) +@RunWith(Parameterized.class) public class KernelCpuUidActiveTimeReaderTest { private File mTestDir; private File mTestFile; private KernelCpuUidActiveTimeReader mReader; + private KernelCpuUidTestBpfMapReader mBpfMapReader; private VerifiableCallback mCallback; private Random mRand = new Random(12345); + protected boolean mUseBpf; private final int mCpus = 4; private final String mHeadline = "cpus: 4\n"; private final int[] mUids = {0, 1, 22, 333, 4444, 55555}; @@ -62,12 +68,22 @@ public class KernelCpuUidActiveTimeReaderTest { return InstrumentationRegistry.getContext(); } + @Parameters(name="useBpf={0}") + public static Collection<Object[]> data() { + return Arrays.asList(new Object[][] { {true}, {false} }); + } + + public KernelCpuUidActiveTimeReaderTest(boolean useBpf) { + mUseBpf = useBpf; + } + @Before public void setUp() { mTestDir = getContext().getDir("test", Context.MODE_PRIVATE); mTestFile = new File(mTestDir, "test.file"); + mBpfMapReader = new KernelCpuUidTestBpfMapReader(); mReader = new KernelCpuUidActiveTimeReader( - new KernelCpuProcStringReader(mTestFile.getAbsolutePath()), false); + new KernelCpuProcStringReader(mTestFile.getAbsolutePath()), mBpfMapReader, false); mCallback = new VerifiableCallback(); } @@ -80,7 +96,7 @@ public class KernelCpuUidActiveTimeReaderTest { @Test public void testReadDelta() throws Exception { final long[][] times = increaseTime(new long[mUids.length][mCpus]); - writeToFile(mHeadline + uidLines(mUids, times)); + setCpusAndData(times); mReader.readDelta(mCallback); for (int i = 0; i < mUids.length; ++i) { mCallback.verify(mUids[i], getActiveTime(times[i])); @@ -90,7 +106,7 @@ public class KernelCpuUidActiveTimeReaderTest { // Verify that a second call will only return deltas. mCallback.clear(); final long[][] newTimes1 = increaseTime(times); - writeToFile(mHeadline + uidLines(mUids, newTimes1)); + setCpusAndData(newTimes1); mReader.readDelta(mCallback); for (int i = 0; i < mUids.length; ++i) { mCallback.verify(mUids[i], getActiveTime(newTimes1[i]) - getActiveTime(times[i])); @@ -105,7 +121,7 @@ public class KernelCpuUidActiveTimeReaderTest { // Verify that calling with a null callback doesn't result in any crashes mCallback.clear(); final long[][] newTimes2 = increaseTime(newTimes1); - writeToFile(mHeadline + uidLines(mUids, newTimes2)); + setCpusAndData(newTimes2); mReader.readDelta(null); mCallback.verifyNoMoreInteractions(); @@ -113,19 +129,20 @@ public class KernelCpuUidActiveTimeReaderTest { // the previous call had null callback. mCallback.clear(); final long[][] newTimes3 = increaseTime(newTimes2); + setCpusAndData(newTimes3); writeToFile(mHeadline + uidLines(mUids, newTimes3)); mReader.readDelta(mCallback); for (int i = 0; i < mUids.length; ++i) { mCallback.verify(mUids[i], getActiveTime(newTimes3[i]) - getActiveTime(newTimes2[i])); } mCallback.verifyNoMoreInteractions(); - assertTrue(mTestFile.delete()); + clearCpusAndData(); } @Test public void testReadAbsolute() throws Exception { final long[][] times1 = increaseTime(new long[mUids.length][mCpus]); - writeToFile(mHeadline + uidLines(mUids, times1)); + setCpusAndData(times1); mReader.readAbsolute(mCallback); for (int i = 0; i < mUids.length; i++) { mCallback.verify(mUids[i], getActiveTime(times1[i])); @@ -135,19 +152,19 @@ public class KernelCpuUidActiveTimeReaderTest { // Verify that a second call should still return absolute values mCallback.clear(); final long[][] times2 = increaseTime(times1); - writeToFile(mHeadline + uidLines(mUids, times2)); + setCpusAndData(times2); mReader.readAbsolute(mCallback); for (int i = 0; i < mUids.length; i++) { mCallback.verify(mUids[i], getActiveTime(times2[i])); } mCallback.verifyNoMoreInteractions(); - assertTrue(mTestFile.delete()); + clearCpusAndData(); } @Test public void testReadDeltaDecreasedTime() throws Exception { final long[][] times1 = increaseTime(new long[mUids.length][mCpus]); - writeToFile(mHeadline + uidLines(mUids, times1)); + setCpusAndData(times1); mReader.readDelta(mCallback); // Verify that there should not be a callback for a particular UID if its time decreases. @@ -155,19 +172,19 @@ public class KernelCpuUidActiveTimeReaderTest { final long[][] times2 = increaseTime(times1); System.arraycopy(times1[0], 0, times2[0], 0, mCpus); times2[0][0] = 100; - writeToFile(mHeadline + uidLines(mUids, times2)); + setCpusAndData(times2); mReader.readDelta(mCallback); for (int i = 1; i < mUids.length; i++) { mCallback.verify(mUids[i], getActiveTime(times2[i]) - getActiveTime(times1[i])); } mCallback.verifyNoMoreInteractions(); - assertTrue(mTestFile.delete()); + clearCpusAndData(); // Verify that the internal state was not modified. mCallback.clear(); final long[][] times3 = increaseTime(times2); times3[0] = increaseTime(times1)[0]; - writeToFile(mHeadline + uidLines(mUids, times3)); + setCpusAndData(times3); mReader.readDelta(mCallback); mCallback.verify(mUids[0], getActiveTime(times3[0]) - getActiveTime(times1[0])); for (int i = 1; i < mUids.length; i++) { @@ -179,26 +196,26 @@ public class KernelCpuUidActiveTimeReaderTest { @Test public void testReadDeltaNegativeTime() throws Exception { final long[][] times1 = increaseTime(new long[mUids.length][mCpus]); - writeToFile(mHeadline + uidLines(mUids, times1)); + setCpusAndData(times1); mReader.readDelta(mCallback); // Verify that there should not be a callback for a particular UID if its time is -ve. mCallback.clear(); final long[][] times2 = increaseTime(times1); times2[0][0] *= -1; - writeToFile(mHeadline + uidLines(mUids, times2)); + setCpusAndData(times2); mReader.readDelta(mCallback); for (int i = 1; i < mUids.length; i++) { mCallback.verify(mUids[i], getActiveTime(times2[i]) - getActiveTime(times1[i])); } mCallback.verifyNoMoreInteractions(); - assertTrue(mTestFile.delete()); + clearCpusAndData(); // Verify that the internal state was not modified. mCallback.clear(); final long[][] times3 = increaseTime(times2); times3[0] = increaseTime(times1)[0]; - writeToFile(mHeadline + uidLines(mUids, times3)); + setCpusAndData(times3); mReader.readDelta(mCallback); mCallback.verify(mUids[0], getActiveTime(times3[0]) - getActiveTime(times1[0])); for (int i = 1; i < mUids.length; i++) { @@ -207,6 +224,28 @@ public class KernelCpuUidActiveTimeReaderTest { mCallback.verifyNoMoreInteractions(); } + private void setCpusAndData(long[][] times) throws IOException { + if (mUseBpf) { + mBpfMapReader.setCpus(new long[]{ mCpus }); + SparseArray<long[]> data = new SparseArray<>(); + for (int i = 0; i < mUids.length; i++) { + data.put(mUids[i], times[i]); + } + mBpfMapReader.setData(data); + } else { + writeToFile(mHeadline + uidLines(mUids, times)); + } + } + + private void clearCpusAndData() { + if (mUseBpf) { + mBpfMapReader.setCpus(null); + mBpfMapReader.setData(new SparseArray<>()); + } else { + assertTrue(mTestFile.delete()); + } + } + private String uidLines(int[] uids, long[][] times) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < uids.length; i++) { @@ -261,4 +300,36 @@ public class KernelCpuUidActiveTimeReaderTest { assertEquals(0, mData.size()); } } + + private class KernelCpuUidTestBpfMapReader extends KernelCpuUidBpfMapReader { + private long[] mCpus; + private SparseArray<long[]> mNewData = new SparseArray<>(); + + public void setData(SparseArray<long[]> data) { + mNewData = data; + } + + public void setCpus(long[] cpus) { + mCpus = cpus; + } + + @Override + public final boolean startTrackingBpfTimes() { + return true; + } + + @Override + protected final boolean readBpfData() { + if (!mUseBpf) { + return false; + } + mData = mNewData; + return true; + } + + @Override + public final long[] getDataDimensions() { + return mCpus; + } + } } diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidBpfMapReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidBpfMapReaderTest.java new file mode 100644 index 000000000000..257b388917e4 --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidBpfMapReaderTest.java @@ -0,0 +1,237 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.os; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import android.content.Context; +import android.util.SparseArray; + +import androidx.test.InstrumentationRegistry; +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; +import org.junit.runner.RunWith; + +import com.android.internal.os.KernelCpuUidBpfMapReader.BpfMapIterator; + +import org.junit.Before; +import org.junit.Test; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Random; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.stream.IntStream; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class KernelCpuUidBpfMapReaderTest { + private Random mRand = new Random(12345); + private KernelCpuUidTestBpfMapReader mReader; + + private Context getContext() { + return InstrumentationRegistry.getContext(); + } + + @Before + public void setUp() { + mReader = new KernelCpuUidTestBpfMapReader(); + } + + /** + * Tests that reading returns null if readBpfData() fails. + */ + @Test + public void testUnsuccessfulRead() { + assertEquals(null, mReader.open()); + } + + /** + * Tests that reading will always return null after 5 failures. + */ + @Test + public void testReadErrorsLimit() { + for (int i = 0; i < 3; i++) { + try (BpfMapIterator iter = mReader.open()) { + assertNull(iter); + } + } + + SparseArray<long[]> data = new SparseArray<>(); + long[] times = {2}; + data.put(1, new long[]{2}); + mReader.setData(data); + testOpenAndReadData(data); + + mReader.setData(null); + for (int i = 0; i < 3; i++) { + try (BpfMapIterator iter = mReader.open(true)) { + assertNull(iter); + } + } + mReader.setData(data); + try (BpfMapIterator iter = mReader.open(true)) { + assertNull(iter); + } + } + + /** Tests getNextUid functionality. */ + @Test + public void testGetNextUid() { + final SparseArray<long[]> data = getTestSparseArray(800, 50); + mReader.setData(data); + testOpenAndReadData(data); + } + + @Test + public void testConcurrent() throws Exception { + final SparseArray<long[]> data = getTestSparseArray(200, 50); + final SparseArray<long[]> data1 = getTestSparseArray(180, 70); + final List<Throwable> errs = Collections.synchronizedList(new ArrayList<>()); + mReader.setData(data); + // An additional thread for modifying the data. + ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(11); + final CountDownLatch ready = new CountDownLatch(10); + final CountDownLatch start = new CountDownLatch(1); + final CountDownLatch modify = new CountDownLatch(1); + final CountDownLatch done = new CountDownLatch(10); + + for (int i = 0; i < 5; i++) { + threadPool.submit(() -> { + ready.countDown(); + try { + start.await(); + testOpenAndReadData(data); + } catch (Throwable e) { + errs.add(e); + } finally { + done.countDown(); + } + }); + threadPool.submit(() -> { + ready.countDown(); + try { + start.await(); + // Wait for data modification. + modify.await(); + testOpenAndReadData(data1); + } catch (Throwable e) { + errs.add(e); + } finally { + done.countDown(); + } + }); + } + + assertTrue("Prep timed out", ready.await(100, TimeUnit.MILLISECONDS)); + start.countDown(); + + threadPool.schedule(() -> { + mReader.setData(data1); + modify.countDown(); + }, 600, TimeUnit.MILLISECONDS); + + assertTrue("Execution timed out", done.await(3, TimeUnit.SECONDS)); + threadPool.shutdownNow(); + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + errs.forEach(e -> e.printStackTrace(pw)); + + assertTrue("All Exceptions:\n" + sw.toString(), errs.isEmpty()); + } + + @Test + public void testRemoveUidsInRange() { + final SparseArray<long[]> data = getTestSparseArray(200, 50); + mReader.setData(data); + testOpenAndReadData(data); + SparseArray<long[]> changedData = new SparseArray<>(); + for (int i = 6; i < 200; i++) { + changedData.put(i, data.get(i)); + } + mReader.removeUidsInRange(0, 5); + testOpenAndReadData(changedData); + } + + private void testOpenAndReadData(SparseArray<long[]> expectedData) { + try (BpfMapIterator iter = mReader.open()) { + long[] actual; + if (expectedData.size() > 0) { + actual = new long[expectedData.valueAt(0).length + 1]; + } else { + actual = new long[0]; + } + for (int i = 0; i < expectedData.size(); i++) { + assertTrue(iter.getNextUid(actual)); + assertEquals(expectedData.keyAt(i), actual[0]); + assertArrayEquals(expectedData.valueAt(i), Arrays.copyOfRange(actual, 1, actual.length)); + } + assertFalse(iter.getNextUid(actual)); + assertFalse(iter.getNextUid(actual)); + } + } + + + private SparseArray<long[]> getTestSparseArray(int uids, int numPerUid) { + SparseArray<long[]> data = new SparseArray<>(); + for (int i = 0; i < uids; i++) { + data.put(i, mRand.longs(numPerUid, 0, Long.MAX_VALUE).toArray()); + } + return data; + } + + + private class KernelCpuUidTestBpfMapReader extends KernelCpuUidBpfMapReader { + private SparseArray<long[]> mNewData; + + public final void setData(SparseArray<long[]> newData) { + mNewData = newData; + } + + @Override + public final boolean startTrackingBpfTimes() { + return true; + } + + @Override + public final boolean readBpfData() { + if (mNewData == null) { + return false; + } + mData = mNewData; + return true; + } + + @Override + public final long[] getDataDimensions() { + return null; + } + + } +} diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidClusterTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidClusterTimeReaderTest.java index 2ea80da9e6d0..a0dab28a6da5 100644 --- a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidClusterTimeReaderTest.java +++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidClusterTimeReaderTest.java @@ -27,7 +27,6 @@ import android.util.SparseArray; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader; @@ -35,11 +34,15 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; import java.io.BufferedWriter; import java.io.File; import java.io.IOException; import java.nio.file.Files; +import java.util.Arrays; +import java.util.Collection; import java.util.Random; /** @@ -48,28 +51,42 @@ import java.util.Random; * $ atest FrameworksCoreTests:com.android.internal.os.KernelCpuUidClusterTimeReaderTest */ @SmallTest -@RunWith(AndroidJUnit4.class) +@RunWith(Parameterized.class) public class KernelCpuUidClusterTimeReaderTest { private File mTestDir; private File mTestFile; private KernelCpuUidClusterTimeReader mReader; + private KernelCpuUidTestBpfMapReader mBpfMapReader; private VerifiableCallback mCallback; private Random mRand = new Random(12345); + protected boolean mUseBpf; private final int mCpus = 6; private final String mHeadline = "policy0: 4 policy4: 2\n"; + private final long[] mCores = {4, 2}; private final int[] mUids = {0, 1, 22, 333, 4444, 55555}; private Context getContext() { return InstrumentationRegistry.getContext(); } + @Parameters(name="useBpf={0}") + public static Collection<Object[]> data() { + return Arrays.asList(new Object[][] { {true}, {false} }); + } + + public KernelCpuUidClusterTimeReaderTest(boolean useBpf) { + mUseBpf = useBpf; + } + @Before public void setUp() { mTestDir = getContext().getDir("test", Context.MODE_PRIVATE); mTestFile = new File(mTestDir, "test.file"); + mBpfMapReader = new KernelCpuUidTestBpfMapReader(); mReader = new KernelCpuUidClusterTimeReader( - new KernelCpuProcStringReader(mTestFile.getAbsolutePath()), false); + new KernelCpuProcStringReader(mTestFile.getAbsolutePath()), mBpfMapReader, + false); mCallback = new VerifiableCallback(); } @@ -82,7 +99,7 @@ public class KernelCpuUidClusterTimeReaderTest { @Test public void testReadDelta() throws Exception { final long[][] times1 = increaseTime(new long[mUids.length][mCpus]); - writeToFile(mHeadline + uidLines(mUids, times1)); + setCoresAndData(times1); mReader.readDelta(mCallback); for (int i = 0; i < mUids.length; ++i) { mCallback.verify(mUids[i], clusterTime(times1[i])); @@ -92,7 +109,7 @@ public class KernelCpuUidClusterTimeReaderTest { // Verify that a second call will only return deltas. mCallback.clear(); final long[][] times2 = increaseTime(times1); - writeToFile(mHeadline + uidLines(mUids, times2)); + setCoresAndData(times2); mReader.readDelta(mCallback); for (int i = 0; i < mUids.length; ++i) { mCallback.verify(mUids[i], subtract(clusterTime(times2[i]), clusterTime(times1[i]))); @@ -107,7 +124,7 @@ public class KernelCpuUidClusterTimeReaderTest { // Verify that calling with a null callback doesn't result in any crashes mCallback.clear(); final long[][] times3 = increaseTime(times2); - writeToFile(mHeadline + uidLines(mUids, times3)); + setCoresAndData(times3); mReader.readDelta(null); mCallback.verifyNoMoreInteractions(); @@ -115,19 +132,19 @@ public class KernelCpuUidClusterTimeReaderTest { // the previous call had null callback. mCallback.clear(); final long[][] times4 = increaseTime(times3); - writeToFile(mHeadline + uidLines(mUids, times4)); + setCoresAndData(times4); mReader.readDelta(mCallback); for (int i = 0; i < mUids.length; ++i) { mCallback.verify(mUids[i], subtract(clusterTime(times4[i]), clusterTime(times3[i]))); } mCallback.verifyNoMoreInteractions(); - assertTrue(mTestFile.delete()); + clearCoresAndData(); } @Test public void testReadAbsolute() throws Exception { final long[][] times1 = increaseTime(new long[mUids.length][mCpus]); - writeToFile(mHeadline + uidLines(mUids, times1)); + setCoresAndData(times1); mReader.readAbsolute(mCallback); for (int i = 0; i < mUids.length; i++) { mCallback.verify(mUids[i], clusterTime(times1[i])); @@ -137,19 +154,19 @@ public class KernelCpuUidClusterTimeReaderTest { // Verify that a second call should still return absolute values mCallback.clear(); final long[][] times2 = increaseTime(times1); - writeToFile(mHeadline + uidLines(mUids, times2)); + setCoresAndData(times2); mReader.readAbsolute(mCallback); for (int i = 0; i < mUids.length; i++) { mCallback.verify(mUids[i], clusterTime(times2[i])); } mCallback.verifyNoMoreInteractions(); - assertTrue(mTestFile.delete()); + clearCoresAndData(); } @Test public void testReadDeltaDecreasedTime() throws Exception { final long[][] times1 = increaseTime(new long[mUids.length][mCpus]); - writeToFile(mHeadline + uidLines(mUids, times1)); + setCoresAndData(times1); mReader.readDelta(mCallback); // Verify that there should not be a callback for a particular UID if its time decreases. @@ -157,19 +174,19 @@ public class KernelCpuUidClusterTimeReaderTest { final long[][] times2 = increaseTime(times1); System.arraycopy(times1[0], 0, times2[0], 0, mCpus); times2[0][0] = 100; - writeToFile(mHeadline + uidLines(mUids, times2)); + setCoresAndData(times2); mReader.readDelta(mCallback); for (int i = 1; i < mUids.length; i++) { mCallback.verify(mUids[i], subtract(clusterTime(times2[i]), clusterTime(times1[i]))); } mCallback.verifyNoMoreInteractions(); - assertTrue(mTestFile.delete()); + clearCoresAndData(); // Verify that the internal state was not modified. mCallback.clear(); final long[][] times3 = increaseTime(times2); times3[0] = increaseTime(times1)[0]; - writeToFile(mHeadline + uidLines(mUids, times3)); + setCoresAndData(times3); mReader.readDelta(mCallback); mCallback.verify(mUids[0], subtract(clusterTime(times3[0]), clusterTime(times1[0]))); for (int i = 1; i < mUids.length; i++) { @@ -181,26 +198,26 @@ public class KernelCpuUidClusterTimeReaderTest { @Test public void testReadDeltaNegativeTime() throws Exception { final long[][] times1 = increaseTime(new long[mUids.length][mCpus]); - writeToFile(mHeadline + uidLines(mUids, times1)); + setCoresAndData(times1); mReader.readDelta(mCallback); // Verify that there should not be a callback for a particular UID if its time decreases. mCallback.clear(); final long[][] times2 = increaseTime(times1); times2[0][0] *= -1; - writeToFile(mHeadline + uidLines(mUids, times2)); + setCoresAndData(times2); mReader.readDelta(mCallback); for (int i = 1; i < mUids.length; i++) { mCallback.verify(mUids[i], subtract(clusterTime(times2[i]), clusterTime(times1[i]))); } mCallback.verifyNoMoreInteractions(); - assertTrue(mTestFile.delete()); + clearCoresAndData(); // Verify that the internal state was not modified. mCallback.clear(); final long[][] times3 = increaseTime(times2); times3[0] = increaseTime(times1)[0]; - writeToFile(mHeadline + uidLines(mUids, times3)); + setCoresAndData(times3); mReader.readDelta(mCallback); mCallback.verify(mUids[0], subtract(clusterTime(times3[0]), clusterTime(times1[0]))); for (int i = 1; i < mUids.length; i++) { @@ -209,6 +226,28 @@ public class KernelCpuUidClusterTimeReaderTest { mCallback.verifyNoMoreInteractions(); } + private void setCoresAndData(long[][] times) throws IOException { + if (mUseBpf) { + mBpfMapReader.setClusterCores(mCores); + SparseArray<long[]> data = new SparseArray<>(); + for (int i = 0; i < mUids.length; i++) { + data.put(mUids[i], times[i]); + } + mBpfMapReader.setData(data); + } else { + writeToFile(mHeadline + uidLines(mUids, times)); + } + } + + private void clearCoresAndData() { + if (mUseBpf) { + mBpfMapReader.setClusterCores(null); + mBpfMapReader.setData(new SparseArray<>()); + } else { + assertTrue(mTestFile.delete()); + } + } + private long[] clusterTime(long[] times) { // Assumes 4 + 2 cores return new long[]{times[0] + times[1] / 2 + times[2] / 3 + times[3] / 4, @@ -277,4 +316,36 @@ public class KernelCpuUidClusterTimeReaderTest { assertEquals(0, mData.size()); } } + + private class KernelCpuUidTestBpfMapReader extends KernelCpuUidBpfMapReader { + private long[] mClusterCores; + private SparseArray<long[]> mNewData = new SparseArray<>(); + + public void setData(SparseArray<long[]> data) { + mNewData = data; + } + + public void setClusterCores(long[] cores) { + mClusterCores = cores; + } + + @Override + public final boolean startTrackingBpfTimes() { + return true; + } + + @Override + protected final boolean readBpfData() { + if (!mUseBpf) { + return false; + } + mData = mNewData; + return true; + } + + @Override + public final long[] getDataDimensions() { + return mClusterCores; + } + } } diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidFreqTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidFreqTimeReaderTest.java index 0b6fed386117..c60a6d61ffa1 100644 --- a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidFreqTimeReaderTest.java +++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidFreqTimeReaderTest.java @@ -29,7 +29,6 @@ import android.util.SparseArray; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader; @@ -37,6 +36,8 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -45,6 +46,7 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.util.Arrays; +import java.util.Collection; import java.util.Random; /** @@ -53,14 +55,16 @@ import java.util.Random; * $ atest FrameworksCoreTests:com.android.internal.os.KernelCpuUidFreqTimeReaderTest */ @SmallTest -@RunWith(AndroidJUnit4.class) +@RunWith(Parameterized.class) public class KernelCpuUidFreqTimeReaderTest { private File mTestDir; private File mTestFile; private KernelCpuUidFreqTimeReader mReader; + private KernelCpuUidTestBpfMapReader mBpfMapReader; private VerifiableCallback mCallback; @Mock private PowerProfile mPowerProfile; + private boolean mUseBpf; private Random mRand = new Random(12345); private final int[] mUids = {0, 1, 22, 333, 4444, 55555}; @@ -69,13 +73,23 @@ public class KernelCpuUidFreqTimeReaderTest { return InstrumentationRegistry.getContext(); } + @Parameters(name="useBpf={0}") + public static Collection<Object[]> data() { + return Arrays.asList(new Object[][] { {true}, {false} }); + } + + public KernelCpuUidFreqTimeReaderTest(boolean useBpf) { + mUseBpf = useBpf; + } + @Before public void setUp() { MockitoAnnotations.initMocks(this); mTestDir = getContext().getDir("test", Context.MODE_PRIVATE); mTestFile = new File(mTestDir, "test.file"); + mBpfMapReader = new KernelCpuUidTestBpfMapReader(); mReader = new KernelCpuUidFreqTimeReader(mTestFile.getAbsolutePath(), - new KernelCpuProcStringReader(mTestFile.getAbsolutePath()), false); + new KernelCpuProcStringReader(mTestFile.getAbsolutePath()), mBpfMapReader, false); mCallback = new VerifiableCallback(); } @@ -97,17 +111,17 @@ public class KernelCpuUidFreqTimeReaderTest { final int[][] numFreqs = {{3, 6}, {4, 5}, {3, 5, 4}, {3}}; for (int i = 0; i < freqs.length; ++i) { mReader = new KernelCpuUidFreqTimeReader(mTestFile.getAbsolutePath(), - new KernelCpuProcStringReader(mTestFile.getAbsolutePath()), false); + new KernelCpuProcStringReader(mTestFile.getAbsolutePath()), mBpfMapReader, false); setCpuClusterFreqs(numClusters[i], numFreqs[i]); - writeToFile(freqsLine(freqs[i])); + setFreqs(freqs[i]); long[] actualFreqs = mReader.readFreqs(mPowerProfile); assertArrayEquals(freqs[i], actualFreqs); final String errMsg = String.format("Freqs=%s, nClusters=%d, nFreqs=%s", Arrays.toString(freqs[i]), numClusters[i], Arrays.toString(numFreqs[i])); assertFalse(errMsg, mReader.perClusterTimesAvailable()); - // Verify that a second call won't read the proc file again - assertTrue(mTestFile.delete()); + // Verify that a second call won't re-read the freqs + clearFreqsAndData(); actualFreqs = mReader.readFreqs(mPowerProfile); assertArrayEquals(freqs[i], actualFreqs); assertFalse(errMsg, mReader.perClusterTimesAvailable()); @@ -125,17 +139,17 @@ public class KernelCpuUidFreqTimeReaderTest { final int[][] numFreqs = {{4}, {3, 5}, {3, 5, 4}}; for (int i = 0; i < freqs.length; ++i) { mReader = new KernelCpuUidFreqTimeReader(mTestFile.getAbsolutePath(), - new KernelCpuProcStringReader(mTestFile.getAbsolutePath()), false); + new KernelCpuProcStringReader(mTestFile.getAbsolutePath()), mBpfMapReader, false); setCpuClusterFreqs(numClusters[i], numFreqs[i]); - writeToFile(freqsLine(freqs[i])); + setFreqs(freqs[i]); long[] actualFreqs = mReader.readFreqs(mPowerProfile); assertArrayEquals(freqs[i], actualFreqs); final String errMsg = String.format("Freqs=%s, nClusters=%d, nFreqs=%s", Arrays.toString(freqs[i]), numClusters[i], Arrays.toString(numFreqs[i])); assertTrue(errMsg, mReader.perClusterTimesAvailable()); - // Verify that a second call won't read the proc file again - assertTrue(mTestFile.delete()); + // Verify that a second call won't re-read the freqs + clearFreqsAndData(); actualFreqs = mReader.readFreqs(mPowerProfile); assertArrayEquals(freqs[i], actualFreqs); assertTrue(errMsg, mReader.perClusterTimesAvailable()); @@ -147,7 +161,7 @@ public class KernelCpuUidFreqTimeReaderTest { final long[] freqs = {110, 123, 145, 167, 289, 997}; final long[][] times = increaseTime(new long[mUids.length][freqs.length]); - writeToFile(freqsLine(freqs) + uidLines(mUids, times)); + setFreqsAndData(freqs, times); mReader.readDelta(mCallback); for (int i = 0; i < mUids.length; ++i) { mCallback.verify(mUids[i], times[i]); @@ -155,14 +169,14 @@ public class KernelCpuUidFreqTimeReaderTest { mCallback.verifyNoMoreInteractions(); // Verify that readDelta also reads the frequencies if not already available. - assertTrue(mTestFile.delete()); + clearFreqsAndData(); long[] actualFreqs = mReader.readFreqs(mPowerProfile); assertArrayEquals(freqs, actualFreqs); // Verify that a second call will only return deltas. mCallback.clear(); final long[][] newTimes1 = increaseTime(times); - writeToFile(freqsLine(freqs) + uidLines(mUids, newTimes1)); + setFreqsAndData(freqs, newTimes1); mReader.readDelta(mCallback); for (int i = 0; i < mUids.length; ++i) { mCallback.verify(mUids[i], subtract(newTimes1[i], times[i])); @@ -177,7 +191,7 @@ public class KernelCpuUidFreqTimeReaderTest { // Verify that calling with a null callback doesn't result in any crashes mCallback.clear(); final long[][] newTimes2 = increaseTime(newTimes1); - writeToFile(freqsLine(freqs) + uidLines(mUids, newTimes2)); + setFreqsAndData(freqs, newTimes2); mReader.readDelta(null); mCallback.verifyNoMoreInteractions(); @@ -185,13 +199,13 @@ public class KernelCpuUidFreqTimeReaderTest { // the previous call had null callback. mCallback.clear(); final long[][] newTimes3 = increaseTime(newTimes2); - writeToFile(freqsLine(freqs) + uidLines(mUids, newTimes3)); + setFreqsAndData(freqs, newTimes3); mReader.readDelta(mCallback); for (int i = 0; i < mUids.length; ++i) { mCallback.verify(mUids[i], subtract(newTimes3[i], newTimes2[i])); } mCallback.verifyNoMoreInteractions(); - assertTrue(mTestFile.delete()); + clearFreqsAndData(); } @Test @@ -199,7 +213,7 @@ public class KernelCpuUidFreqTimeReaderTest { final long[] freqs = {110, 123, 145, 167, 289, 997}; final long[][] times1 = increaseTime(new long[mUids.length][freqs.length]); - writeToFile(freqsLine(freqs) + uidLines(mUids, times1)); + setFreqsAndData(freqs, times1); mReader.readAbsolute(mCallback); for (int i = 0; i < mUids.length; i++) { mCallback.verify(mUids[i], times1[i]); @@ -207,20 +221,20 @@ public class KernelCpuUidFreqTimeReaderTest { mCallback.verifyNoMoreInteractions(); // Verify that readDelta also reads the frequencies if not already available. - assertTrue(mTestFile.delete()); + clearFreqsAndData(); long[] actualFreqs = mReader.readFreqs(mPowerProfile); assertArrayEquals(freqs, actualFreqs); // Verify that a second call should still return absolute values mCallback.clear(); final long[][] times2 = increaseTime(times1); - writeToFile(freqsLine(freqs) + uidLines(mUids, times2)); + setFreqsAndData(freqs, times2); mReader.readAbsolute(mCallback); for (int i = 0; i < mUids.length; i++) { mCallback.verify(mUids[i], times2[i]); } mCallback.verifyNoMoreInteractions(); - assertTrue(mTestFile.delete()); + clearFreqsAndData(); } @Test @@ -228,14 +242,14 @@ public class KernelCpuUidFreqTimeReaderTest { final long[] freqs = {110, 123, 145, 167, 289, 997}; final long[][] times1 = increaseTime(new long[mUids.length][freqs.length]); - writeToFile(freqsLine(freqs) + uidLines(mUids, times1)); + setFreqsAndData(freqs, times1); mReader.readDelta(mCallback); // Verify that there should not be a callback for a particular UID if its time decreases. mCallback.clear(); final long[][] times2 = increaseTime(times1); times2[0][0] = 1000; - writeToFile(freqsLine(freqs) + uidLines(mUids, times2)); + setFreqsAndData(freqs, times2); mReader.readDelta(mCallback); for (int i = 1; i < mUids.length; i++) { mCallback.verify(mUids[i], subtract(times2[i], times1[i])); @@ -246,7 +260,7 @@ public class KernelCpuUidFreqTimeReaderTest { mCallback.clear(); final long[][] times3 = increaseTime(times2); times3[0] = increaseTime(times1)[0]; - writeToFile(freqsLine(freqs) + uidLines(mUids, times3)); + setFreqsAndData(freqs, times3); mReader.readDelta(mCallback); mCallback.verify(mUids[0], subtract(times3[0], times1[0])); for (int i = 1; i < mUids.length; i++) { @@ -258,7 +272,7 @@ public class KernelCpuUidFreqTimeReaderTest { mCallback.clear(); final long[][] times4 = increaseTime(times3); times4[0][0] *= -1; - writeToFile(freqsLine(freqs) + uidLines(mUids, times4)); + setFreqsAndData(freqs, times4); mReader.readDelta(mCallback); for (int i = 1; i < mUids.length; ++i) { mCallback.verify(mUids[i], subtract(times4[i], times3[i])); @@ -269,14 +283,44 @@ public class KernelCpuUidFreqTimeReaderTest { mCallback.clear(); final long[][] times5 = increaseTime(times4); times5[0] = increaseTime(times3)[0]; - writeToFile(freqsLine(freqs) + uidLines(mUids, times5)); + setFreqsAndData(freqs, times5); mReader.readDelta(mCallback); mCallback.verify(mUids[0], subtract(times5[0], times3[0])); for (int i = 1; i < mUids.length; i++) { mCallback.verify(mUids[i], subtract(times5[i], times4[i])); } - assertTrue(mTestFile.delete()); + clearFreqsAndData(); + } + + private void setFreqs(long[] freqs) throws IOException { + if (mUseBpf) { + mBpfMapReader.setFreqs(freqs); + } else { + writeToFile(freqsLine(freqs)); + } + } + + private void setFreqsAndData(long[] freqs, long[][] times) throws IOException { + if (mUseBpf) { + mBpfMapReader.setFreqs(freqs); + SparseArray<long[]> data = new SparseArray<>(); + for (int i = 0; i < mUids.length; i++) { + data.put(mUids[i], times[i]); + } + mBpfMapReader.setData(data); + } else { + writeToFile(freqsLine(freqs) + uidLines(mUids, times)); + } + } + + private void clearFreqsAndData() { + if (mUseBpf) { + mBpfMapReader.setFreqs(null); + mBpfMapReader.setData(new SparseArray<>()); + } else { + assertTrue(mTestFile.delete()); + } } private String freqsLine(long[] freqs) { @@ -358,4 +402,36 @@ public class KernelCpuUidFreqTimeReaderTest { assertEquals(0, mData.size()); } } + + private class KernelCpuUidTestBpfMapReader extends KernelCpuUidBpfMapReader { + private long[] mCpuFreqs; + private SparseArray<long[]> mNewData = new SparseArray<>(); + + public void setData(SparseArray<long[]> data) { + mNewData = data; + } + + public void setFreqs(long[] freqs) { + mCpuFreqs = freqs; + } + + @Override + public final boolean startTrackingBpfTimes() { + return true; + } + + @Override + protected final boolean readBpfData() { + if (!mUseBpf) { + return false; + } + mData = mNewData; + return true; + } + + @Override + public final long[] getDataDimensions() { + return mCpuFreqs; + } + } } diff --git a/core/tests/coretests/src/com/android/internal/os/KernelSingleUidTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelSingleUidTimeReaderTest.java index 479e19e10ba0..dac35e5ec4b1 100644 --- a/core/tests/coretests/src/com/android/internal/os/KernelSingleUidTimeReaderTest.java +++ b/core/tests/coretests/src/com/android/internal/os/KernelSingleUidTimeReaderTest.java @@ -31,20 +31,33 @@ import com.android.internal.os.KernelSingleUidTimeReader.Injector; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Arrays; +import java.util.Collection; @SmallTest -@RunWith(AndroidJUnit4.class) +@RunWith(Parameterized.class) public class KernelSingleUidTimeReaderTest { private final static int TEST_UID = 2222; private final static int TEST_FREQ_COUNT = 5; private KernelSingleUidTimeReader mReader; private TestInjector mInjector; + protected boolean mUseBpf; + + @Parameters(name="useBpf={0}") + public static Collection<Object[]> data() { + return Arrays.asList(new Object[][] { {true}, {false} }); + } + + public KernelSingleUidTimeReaderTest(boolean useBpf) { + mUseBpf = useBpf; + } @Before public void setUp() { @@ -273,6 +286,7 @@ public class KernelSingleUidTimeReaderTest { class TestInjector extends Injector { private byte[] mData; + private long[] mBpfData; private boolean mThrowExcpetion; @Override @@ -284,6 +298,14 @@ public class KernelSingleUidTimeReaderTest { } } + @Override + public long[] readBpfData(int uid) { + if (!mUseBpf || mBpfData == null) { + return new long[0]; + } + return mBpfData; + } + public void setData(long[] cpuTimes) { final ByteBuffer buffer = ByteBuffer.allocate(cpuTimes.length * Long.BYTES); buffer.order(ByteOrder.nativeOrder()); @@ -291,6 +313,7 @@ public class KernelSingleUidTimeReaderTest { buffer.putLong(time / 10); } mData = buffer.array(); + mBpfData = cpuTimes.clone(); } public void letReadDataThrowException(boolean throwException) { diff --git a/libs/usb/Android.bp b/libs/usb/Android.bp index 027a7488f723..e752b55f5ef7 100644 --- a/libs/usb/Android.bp +++ b/libs/usb/Android.bp @@ -19,5 +19,3 @@ java_sdk_library { srcs: ["src/**/*.java"], api_packages: ["com.android.future.usb"], } - -subdirs = ["tests/*"] diff --git a/libs/usb/tests/AccessoryChat/Android.bp b/libs/usb/tests/AccessoryChat/Android.bp index 63a670c67bfc..19ed3d3ef52e 100644 --- a/libs/usb/tests/AccessoryChat/Android.bp +++ b/libs/usb/tests/AccessoryChat/Android.bp @@ -1,4 +1,3 @@ -subdirs = ["accessorychat"] // // Copyright (C) 2011 The Android Open Source Project // diff --git a/media/jni/Android.bp b/media/jni/Android.bp index f873eeb9aa00..27660db1f4a9 100644 --- a/media/jni/Android.bp +++ b/media/jni/Android.bp @@ -124,8 +124,3 @@ cc_library_shared { "-Wunreachable-code", ], } - -subdirs = [ - "audioeffect", - "soundpool", -] diff --git a/media/native/Android.bp b/media/native/Android.bp deleted file mode 100644 index b44c2960127f..000000000000 --- a/media/native/Android.bp +++ /dev/null @@ -1 +0,0 @@ -subdirs = ["*"] diff --git a/packages/DynamicSystemInstallationService/res/values/strings.xml b/packages/DynamicSystemInstallationService/res/values/strings.xml index 25b7fc1b5ce2..e124be605cc7 100644 --- a/packages/DynamicSystemInstallationService/res/values/strings.xml +++ b/packages/DynamicSystemInstallationService/res/values/strings.xml @@ -27,10 +27,11 @@ <string name="notification_action_cancel">Cancel</string> <!-- Action on notification: Discard installation [CHAR LIMIT=16] --> <string name="notification_action_discard">Discard</string> - <!-- Action on notification: Uninstall Dynamic System [CHAR LIMIT=16] --> - <string name="notification_action_uninstall">Uninstall</string> <!-- Action on notification: Restart to Dynamic System [CHAR LIMIT=16] --> <string name="notification_action_reboot_to_dynsystem">Restart</string> + <!-- Action on notification: Restart to original Android version [CHAR LIMIT=16] --> + <string name="notification_action_reboot_to_origin">Restart</string> + <!-- Toast when installed Dynamic System is discarded [CHAR LIMIT=64] --> <string name="toast_dynsystem_discarded">Discarded dynamic system</string> diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java index 7affe8888628..37a77be52983 100644 --- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java +++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java @@ -462,7 +462,7 @@ public class DynamicSystemInstallationService extends Service .setStyle(new Notification.BigTextStyle().bigText(msgInUse)); builder.addAction(new Notification.Action.Builder( - null, getString(R.string.notification_action_uninstall), + null, getString(R.string.notification_action_reboot_to_origin), createPendingIntent(ACTION_REBOOT_TO_NORMAL)).build()); break; diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index e75ad13780d5..6c1d2796add7 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -1009,6 +1009,11 @@ public class SettingsProvider extends ContentProvider { String value = setting != null ? setting.getValue() : null; updateGlobalSetting(Settings.Global.ADB_ENABLED, value, null, true, userId, true); + + setting = getGlobalSetting(Settings.Global.ADB_WIFI_ENABLED); + value = setting != null ? setting.getValue() : null; + updateGlobalSetting(Settings.Global.ADB_WIFI_ENABLED, + value, null, true, userId, true); } } finally { Binder.restoreCallingIdentity(identity); diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 262365da3a06..a9fa2ac28e89 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -430,6 +430,25 @@ android:excludeFromRecents="true"> </activity> + <!-- started from WirelessDebuggingManager --> + <activity android:name=".wifi.WifiDebuggingActivity" + android:permission="android.permission.MANAGE_DEBUGGING" + android:theme="@style/Theme.SystemUI.Dialog.Alert" + android:finishOnCloseSystemDialogs="true" + android:excludeFromRecents="true"> + </activity> + <activity-alias + android:name=".WifiDebuggingActivityAlias" + android:permission="android.permission.DUMP" + android:targetActivity=".wifi.WifiDebuggingActivity" + android:exported="true"> + </activity-alias> + <activity android:name=".wifi.WifiDebuggingSecondaryUserActivity" + android:theme="@style/Theme.SystemUI.Dialog.Alert" + android:finishOnCloseSystemDialogs="true" + android:excludeFromRecents="true"> + </activity> + <!-- started from NetworkPolicyManagerService --> <activity android:name=".net.NetworkOverLimitActivity" diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index d58f83fb8a3b..f5ccc53aaa24 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -162,6 +162,24 @@ <!-- Message of notification shown when trying to enable USB debugging but a secondary user is the current foreground user. --> <string name="usb_debugging_secondary_user_message">The user currently signed in to this device can\'t turn on USB debugging. To use this feature, switch to the primary user.</string> + <!-- Title of confirmation dialog for wireless debugging [CHAR LIMIT=NONE] --> + <string name="wifi_debugging_title">Allow wireless debugging on this network?</string> + + <!-- Message of confirmation dialog for wireless debugging [CHAR LIMIT=NONE] --> + <string name="wifi_debugging_message">Network Name (SSID)\n<xliff:g id="ssid" example="My wifi">%1$s</xliff:g>\n\nWi\u2011Fi Address (BSSID)\n<xliff:g id="bssid" example="AB:CD:EF:12:34:56">%2$s</xliff:g></string> + + <!-- Option to always allow wireless debugging on this network [CHAR LIMIT=NONE] --> + <string name="wifi_debugging_always">Always allow on this network</string> + + <!-- Button label for confirming acceptance of enabling wireless debugging [CHAR LIMIT=15] --> + <string name="wifi_debugging_allow">Allow</string> + + <!-- Title of notification shown when trying to enable wireless debugging but a secondary user is the current foreground user. [CHAR LIMIT=NONE] --> + <string name="wifi_debugging_secondary_user_title">Wireless debugging not allowed</string> + + <!-- Message of notification shown when trying to enable wireless debugging but a secondary user is the current foreground user. [CHAR LIMIT=NONE] --> + <string name="wifi_debugging_secondary_user_message">The user currently signed in to this device can\u2019t turn on wireless debugging. To use this feature, switch to the primary user.</string> + <!-- Title of USB contaminant presence dialog [CHAR LIMIT=NONE] --> <string name="usb_contaminant_title">USB port disabled</string> diff --git a/packages/SystemUI/src/com/android/systemui/wifi/WifiDebuggingActivity.java b/packages/SystemUI/src/com/android/systemui/wifi/WifiDebuggingActivity.java new file mode 100644 index 000000000000..a94af24fc843 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/wifi/WifiDebuggingActivity.java @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.wifi; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.IntentFilter; +import android.debug.IAdbManager; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; +import android.os.Bundle; +import android.os.IBinder; +import android.os.ServiceManager; +import android.util.EventLog; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.CheckBox; +import android.widget.Toast; + +import com.android.internal.app.AlertActivity; +import com.android.internal.app.AlertController; +import com.android.systemui.R; + +/** + * Alerts the user of an untrusted network when enabling wireless debugging. + * The user can either deny, allow, or allow with the "always allow on this + * network" checked. + */ +public class WifiDebuggingActivity extends AlertActivity + implements DialogInterface.OnClickListener { + private static final String TAG = "WifiDebuggingActivity"; + + private CheckBox mAlwaysAllow; + // Notifies when wifi is disabled, or the network changed + private WifiChangeReceiver mWifiChangeReceiver; + private WifiManager mWifiManager; + private String mBssid; + private boolean mClicked = false; + + @Override + public void onCreate(Bundle icicle) { + Window window = getWindow(); + window.addSystemFlags( + WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); + window.setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG); + + super.onCreate(icicle); + + + mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE); + mWifiChangeReceiver = new WifiChangeReceiver(this); + + Intent intent = getIntent(); + String ssid = intent.getStringExtra("ssid"); + mBssid = intent.getStringExtra("bssid"); + + if (ssid == null || mBssid == null) { + finish(); + return; + } + + final AlertController.AlertParams ap = mAlertParams; + ap.mTitle = getString(R.string.wifi_debugging_title); + ap.mMessage = getString(R.string.wifi_debugging_message, ssid, mBssid); + ap.mPositiveButtonText = getString(R.string.wifi_debugging_allow); + ap.mNegativeButtonText = getString(android.R.string.cancel); + ap.mPositiveButtonListener = this; + ap.mNegativeButtonListener = this; + + // add "always allow" checkbox + LayoutInflater inflater = LayoutInflater.from(ap.mContext); + View checkbox = inflater.inflate(com.android.internal.R.layout.always_use_checkbox, null); + mAlwaysAllow = (CheckBox) checkbox.findViewById(com.android.internal.R.id.alwaysUse); + mAlwaysAllow.setText(getString(R.string.wifi_debugging_always)); + ap.mView = checkbox; + window.setCloseOnTouchOutside(false); + + setupAlert(); + + // adding touch listener on affirmative button - checks if window is obscured + // if obscured, do not let user give permissions (could be tapjacking involved) + final View.OnTouchListener filterTouchListener = (View v, MotionEvent event) -> { + // Filter obscured touches by consuming them. + if (((event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) + || ((event.getFlags() & MotionEvent.FLAG_WINDOW_IS_PARTIALLY_OBSCURED) != 0)) { + if (event.getAction() == MotionEvent.ACTION_UP) { + // TODO: need a different value for safety net? + EventLog.writeEvent(0x534e4554, "62187985"); // safety net logging + Toast.makeText(v.getContext(), + R.string.touch_filtered_warning, + Toast.LENGTH_SHORT).show(); + } + return true; + } + return false; + }; + mAlert.getButton(BUTTON_POSITIVE).setOnTouchListener(filterTouchListener); + + } + + @Override + public void onWindowAttributesChanged(WindowManager.LayoutParams params) { + super.onWindowAttributesChanged(params); + } + + private class WifiChangeReceiver extends BroadcastReceiver { + private final Activity mActivity; + WifiChangeReceiver(Activity activity) { + mActivity = activity; + } + + @Override + public void onReceive(Context content, Intent intent) { + String action = intent.getAction(); + if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) { + int state = intent.getIntExtra( + WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_DISABLED); + if (state == WifiManager.WIFI_STATE_DISABLED) { + mActivity.finish(); + } + } else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) { + NetworkInfo networkInfo = (NetworkInfo) intent.getParcelableExtra( + WifiManager.EXTRA_NETWORK_INFO); + if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI) { + if (!networkInfo.isConnected()) { + mActivity.finish(); + return; + } + WifiInfo wifiInfo = mWifiManager.getConnectionInfo(); + if (wifiInfo == null || wifiInfo.getNetworkId() == -1) { + mActivity.finish(); + return; + } + String bssid = wifiInfo.getBSSID(); + if (bssid == null || bssid.isEmpty()) { + mActivity.finish(); + return; + } + if (!bssid.equals(mBssid)) { + mActivity.finish(); + return; + } + } + } + } + } + + @Override + public void onStart() { + super.onStart(); + IntentFilter filter = new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION); + filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); + registerReceiver(mWifiChangeReceiver, filter); + } + + @Override + protected void onStop() { + if (mWifiChangeReceiver != null) { + unregisterReceiver(mWifiChangeReceiver); + } + super.onStop(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + + // In the case where user dismissed the dialog, we don't get an onClick event. + // In that case, tell adb to deny the network connection. + if (!mClicked) { + try { + IBinder b = ServiceManager.getService(ADB_SERVICE); + IAdbManager service = IAdbManager.Stub.asInterface(b); + service.denyWirelessDebugging(); + } catch (Exception e) { + Log.e(TAG, "Unable to notify Adb service", e); + } + } + } + + @Override + public void onClick(DialogInterface dialog, int which) { + mClicked = true; + boolean allow = (which == AlertDialog.BUTTON_POSITIVE); + boolean alwaysAllow = allow && mAlwaysAllow.isChecked(); + try { + IBinder b = ServiceManager.getService(ADB_SERVICE); + IAdbManager service = IAdbManager.Stub.asInterface(b); + if (allow) { + service.allowWirelessDebugging(alwaysAllow, mBssid); + } else { + service.denyWirelessDebugging(); + } + } catch (Exception e) { + Log.e(TAG, "Unable to notify Adb service", e); + } + finish(); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/wifi/WifiDebuggingSecondaryUserActivity.java b/packages/SystemUI/src/com/android/systemui/wifi/WifiDebuggingSecondaryUserActivity.java new file mode 100644 index 000000000000..0266a84503a1 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/wifi/WifiDebuggingSecondaryUserActivity.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.wifi; + +import android.app.Activity; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.IntentFilter; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; +import android.os.Bundle; + +import com.android.internal.app.AlertActivity; +import com.android.internal.app.AlertController; +import com.android.systemui.R; + +/** + * Alerts the user that wireless debugging cannot be enabled by a secondary user. + */ +public class WifiDebuggingSecondaryUserActivity extends AlertActivity + implements DialogInterface.OnClickListener { + private WifiChangeReceiver mWifiChangeReceiver; + private WifiManager mWifiManager; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE); + mWifiChangeReceiver = new WifiChangeReceiver(this); + + final AlertController.AlertParams ap = mAlertParams; + ap.mTitle = getString(R.string.wifi_debugging_secondary_user_title); + ap.mMessage = getString(R.string.wifi_debugging_secondary_user_message); + ap.mPositiveButtonText = getString(android.R.string.ok); + ap.mPositiveButtonListener = this; + + setupAlert(); + } + + private class WifiChangeReceiver extends BroadcastReceiver { + private final Activity mActivity; + WifiChangeReceiver(Activity activity) { + mActivity = activity; + } + + @Override + public void onReceive(Context content, Intent intent) { + String action = intent.getAction(); + if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) { + int state = intent.getIntExtra( + WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_DISABLED); + if (state == WifiManager.WIFI_STATE_DISABLED) { + mActivity.finish(); + } + } else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) { + NetworkInfo networkInfo = (NetworkInfo) intent.getParcelableExtra( + WifiManager.EXTRA_NETWORK_INFO); + if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI) { + if (!networkInfo.isConnected()) { + mActivity.finish(); + return; + } + WifiInfo wifiInfo = mWifiManager.getConnectionInfo(); + if (wifiInfo == null || wifiInfo.getNetworkId() == -1) { + mActivity.finish(); + return; + } + } + } + } + } + + @Override + public void onStart() { + super.onStart(); + + IntentFilter filter = new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION); + filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); + registerReceiver(mWifiChangeReceiver, filter); + } + + @Override + protected void onStop() { + if (mWifiChangeReceiver != null) { + unregisterReceiver(mWifiChangeReceiver); + } + super.onStop(); + } + + @Override + public void onClick(DialogInterface dialog, int which) { + finish(); + } +} diff --git a/packages/Tethering/common/TetheringLib/Android.bp b/packages/Tethering/common/TetheringLib/Android.bp index cb0de7a860ac..1a3d5b659ee3 100644 --- a/packages/Tethering/common/TetheringLib/Android.bp +++ b/packages/Tethering/common/TetheringLib/Android.bp @@ -83,7 +83,6 @@ java_library { name: "framework-tethering-stubs", srcs: [":framework-tethering-stubs-sources"], libs: ["framework-all"], - static_libs: ["tethering-aidl-interfaces-java"], sdk_version: "core_platform", } diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringConstants.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheringConstants.java index df87ac994d42..a18f5da60cad 100644 --- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringConstants.java +++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheringConstants.java @@ -33,6 +33,9 @@ import android.os.ResultReceiver; */ @SystemApi(client = MODULE_LIBRARIES) public class TetheringConstants { + /** An explicit private class to avoid exposing constructor.*/ + private TetheringConstants() { } + /** * Extra used for communicating with the TetherService. Includes the type of tethering to * enable if any. diff --git a/services/Android.bp b/services/Android.bp index cecadfd65c6d..bca34f55fddd 100644 --- a/services/Android.bp +++ b/services/Android.bp @@ -110,9 +110,10 @@ droidstubs { name: "services-stubs.sources", srcs: [":services-sources"], installable: false, - // TODO: remove the --hide options below args: " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.SYSTEM_SERVER\\)" + " --hide-annotation android.annotation.Hide" + + " --hide InternalClasses" + // com.android.* classes are okay in this interface + // TODO: remove the --hide options below " --hide-package com.google.android.startop.iorap" + " --hide ReferencesHidden" + " --hide DeprecationMismatch" + diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 52a2ca974d40..1eb77a496315 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -1536,7 +1536,8 @@ public class ConnectivityService extends IConnectivityManager.Stub } @Override - public NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId) { + public NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser( + int userId, String callingPackageName) { // The basic principle is: if an app's traffic could possibly go over a // network, without the app doing anything multinetwork-specific, // (hence, by "default"), then include that network's capabilities in @@ -1558,7 +1559,10 @@ public class ConnectivityService extends IConnectivityManager.Stub NetworkAgentInfo nai = getDefaultNetwork(); NetworkCapabilities nc = getNetworkCapabilitiesInternal(nai); if (nc != null) { - result.put(nai.network, nc); + result.put( + nai.network, + maybeSanitizeLocationInfoForCaller( + nc, Binder.getCallingUid(), callingPackageName)); } synchronized (mVpns) { @@ -1568,10 +1572,12 @@ public class ConnectivityService extends IConnectivityManager.Stub Network[] networks = vpn.getUnderlyingNetworks(); if (networks != null) { for (Network network : networks) { - nai = getNetworkAgentInfoForNetwork(network); - nc = getNetworkCapabilitiesInternal(nai); + nc = getNetworkCapabilitiesInternal(network); if (nc != null) { - result.put(network, nc); + result.put( + network, + maybeSanitizeLocationInfoForCaller( + nc, Binder.getCallingUid(), callingPackageName)); } } } @@ -1638,20 +1644,26 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + private NetworkCapabilities getNetworkCapabilitiesInternal(Network network) { + return getNetworkCapabilitiesInternal(getNetworkAgentInfoForNetwork(network)); + } + private NetworkCapabilities getNetworkCapabilitiesInternal(NetworkAgentInfo nai) { if (nai == null) return null; synchronized (nai) { if (nai.networkCapabilities == null) return null; return networkCapabilitiesRestrictedForCallerPermissions( - nai.networkCapabilities, - Binder.getCallingPid(), Binder.getCallingUid()); + nai.networkCapabilities, Binder.getCallingPid(), Binder.getCallingUid()); } } @Override - public NetworkCapabilities getNetworkCapabilities(Network network) { + public NetworkCapabilities getNetworkCapabilities(Network network, String callingPackageName) { + mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackageName); enforceAccessPermission(); - return getNetworkCapabilitiesInternal(getNetworkAgentInfoForNetwork(network)); + return maybeSanitizeLocationInfoForCaller( + getNetworkCapabilitiesInternal(network), + Binder.getCallingUid(), callingPackageName); } @VisibleForTesting @@ -1667,20 +1679,34 @@ public class ConnectivityService extends IConnectivityManager.Stub } newNc.setAdministratorUids(Collections.EMPTY_LIST); - maybeSanitizeLocationInfoForCaller(newNc, callerUid); - return newNc; } - private void maybeSanitizeLocationInfoForCaller( - NetworkCapabilities nc, int callerUid) { - // TODO(b/142072839): Conditionally reset the owner UID if the following - // conditions are not met: - // 1. The destination app is the network owner - // 2. The destination app has the ACCESS_COARSE_LOCATION permission granted - // if target SDK<29 or otherwise has the ACCESS_FINE_LOCATION permission granted - // 3. The user's location toggle is on - nc.setOwnerUid(INVALID_UID); + @VisibleForTesting + @Nullable + NetworkCapabilities maybeSanitizeLocationInfoForCaller( + @Nullable NetworkCapabilities nc, int callerUid, @NonNull String callerPkgName) { + if (nc == null) { + return null; + } + final NetworkCapabilities newNc = new NetworkCapabilities(nc); + if (callerUid != newNc.getOwnerUid()) { + newNc.setOwnerUid(INVALID_UID); + return newNc; + } + + Binder.withCleanCallingIdentity( + () -> { + if (!mLocationPermissionChecker.checkLocationPermission( + callerPkgName, null /* featureId */, callerUid, null /* message */)) { + // Caller does not have the requisite location permissions. Reset the + // owner's UID in the NetworkCapabilities. + newNc.setOwnerUid(INVALID_UID); + } + } + ); + + return newNc; } private LinkProperties linkPropertiesRestrictedForCallerPermissions( @@ -1755,7 +1781,7 @@ public class ConnectivityService extends IConnectivityManager.Stub public boolean isActiveNetworkMetered() { enforceAccessPermission(); - final NetworkCapabilities caps = getNetworkCapabilities(getActiveNetwork()); + final NetworkCapabilities caps = getNetworkCapabilitiesInternal(getActiveNetwork()); if (caps != null) { return !caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); } else { @@ -5322,8 +5348,8 @@ public class ConnectivityService extends IConnectivityManager.Stub } public String toString() { - return "uid/pid:" + mUid + "/" + mPid + " " + request + - (mPendingIntent == null ? "" : " to trigger " + mPendingIntent); + return "uid/pid:" + mUid + "/" + mPid + " " + request + + (mPendingIntent == null ? "" : " to trigger " + mPendingIntent); } } @@ -6416,8 +6442,13 @@ public class ConnectivityService extends IConnectivityManager.Stub } switch (notificationType) { case ConnectivityManager.CALLBACK_AVAILABLE: { - putParcelable(bundle, networkCapabilitiesRestrictedForCallerPermissions( - networkAgent.networkCapabilities, nri.mPid, nri.mUid)); + final NetworkCapabilities nc = + networkCapabilitiesRestrictedForCallerPermissions( + networkAgent.networkCapabilities, nri.mPid, nri.mUid); + putParcelable( + bundle, + maybeSanitizeLocationInfoForCaller( + nc, nri.mUid, nri.request.getRequestorPackageName())); putParcelable(bundle, linkPropertiesRestrictedForCallerPermissions( networkAgent.linkProperties, nri.mPid, nri.mUid)); // For this notification, arg1 contains the blocked status. @@ -6430,9 +6461,13 @@ public class ConnectivityService extends IConnectivityManager.Stub } case ConnectivityManager.CALLBACK_CAP_CHANGED: { // networkAgent can't be null as it has been accessed a few lines above. - final NetworkCapabilities nc = networkCapabilitiesRestrictedForCallerPermissions( - networkAgent.networkCapabilities, nri.mPid, nri.mUid); - putParcelable(bundle, nc); + final NetworkCapabilities netCap = + networkCapabilitiesRestrictedForCallerPermissions( + networkAgent.networkCapabilities, nri.mPid, nri.mUid); + putParcelable( + bundle, + maybeSanitizeLocationInfoForCaller( + netCap, nri.mUid, nri.request.getRequestorPackageName())); break; } case ConnectivityManager.CALLBACK_IP_CHANGED: { diff --git a/services/core/java/com/android/server/UserspaceRebootLogger.java b/services/core/java/com/android/server/UserspaceRebootLogger.java new file mode 100644 index 000000000000..74f113f58c70 --- /dev/null +++ b/services/core/java/com/android/server/UserspaceRebootLogger.java @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; + +import static com.android.internal.util.FrameworkStatsLog.USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_SHUTDOWN_SEQUENCE_ABORTED; +import static com.android.internal.util.FrameworkStatsLog.USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_USERDATA_REMOUNT; +import static com.android.internal.util.FrameworkStatsLog.USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_USERSPACE_REBOOT_WATCHDOG_TRIGGERED; +import static com.android.internal.util.FrameworkStatsLog.USERSPACE_REBOOT_REPORTED__OUTCOME__OUTCOME_UNKNOWN; +import static com.android.internal.util.FrameworkStatsLog.USERSPACE_REBOOT_REPORTED__OUTCOME__SUCCESS; +import static com.android.internal.util.FrameworkStatsLog.USERSPACE_REBOOT_REPORTED__USER_ENCRYPTION_STATE__LOCKED; +import static com.android.internal.util.FrameworkStatsLog.USERSPACE_REBOOT_REPORTED__USER_ENCRYPTION_STATE__UNLOCKED; + +import android.os.SystemClock; +import android.os.SystemProperties; +import android.util.Slog; + +import com.android.internal.util.FrameworkStatsLog; + +import java.util.concurrent.Executor; + +/** + * Utility class to help abstract logging {@code UserspaceRebootReported} atom. + */ +public final class UserspaceRebootLogger { + + private static final String TAG = "UserspaceRebootLogger"; + + private static final String USERSPACE_REBOOT_SHOULD_LOG_PROPERTY = + "persist.sys.userspace_reboot.log.should_log"; + private static final String USERSPACE_REBOOT_LAST_STARTED_PROPERTY = + "sys.userspace_reboot.log.last_started"; + private static final String USERSPACE_REBOOT_LAST_FINISHED_PROPERTY = + "sys.userspace_reboot.log.last_finished"; + private static final String BOOT_REASON_PROPERTY = "sys.boot.reason"; + + private UserspaceRebootLogger() {} + + /** + * Modifies internal state to note that {@code UserspaceRebootReported} atom needs to be + * logged on the next successful boot. + */ + public static void noteUserspaceRebootWasRequested() { + SystemProperties.set(USERSPACE_REBOOT_SHOULD_LOG_PROPERTY, "1"); + SystemProperties.set(USERSPACE_REBOOT_LAST_STARTED_PROPERTY, + String.valueOf(SystemClock.elapsedRealtime())); + } + + /** + * Updates internal state on boot after successful userspace reboot. + * + * <p>Should be called right before framework sets {@code sys.boot_completed} property. + */ + public static void noteUserspaceRebootSuccess() { + SystemProperties.set(USERSPACE_REBOOT_LAST_FINISHED_PROPERTY, + String.valueOf(SystemClock.elapsedRealtime())); + } + + /** + * Returns {@code true} if {@code UserspaceRebootReported} atom should be logged. + */ + public static boolean shouldLogUserspaceRebootEvent() { + return SystemProperties.getBoolean(USERSPACE_REBOOT_SHOULD_LOG_PROPERTY, false); + } + + /** + * Asynchronously logs {@code UserspaceRebootReported} on the given {@code executor}. + * + * <p>Should be called in the end of {@link + * com.android.server.am.ActivityManagerService#finishBooting()} method, after framework have + * tried to proactivelly unlock storage of the primary user. + */ + public static void logEventAsync(boolean userUnlocked, Executor executor) { + final int outcome = computeOutcome(); + final long durationMillis; + if (outcome == USERSPACE_REBOOT_REPORTED__OUTCOME__SUCCESS) { + durationMillis = SystemProperties.getLong(USERSPACE_REBOOT_LAST_FINISHED_PROPERTY, 0) + - SystemProperties.getLong(USERSPACE_REBOOT_LAST_STARTED_PROPERTY, 0); + } else { + durationMillis = 0; + } + final int encryptionState = + userUnlocked + ? USERSPACE_REBOOT_REPORTED__USER_ENCRYPTION_STATE__UNLOCKED + : USERSPACE_REBOOT_REPORTED__USER_ENCRYPTION_STATE__LOCKED; + executor.execute( + () -> { + Slog.i(TAG, "Logging UserspaceRebootReported atom: { outcome: " + outcome + + " durationMillis: " + durationMillis + " encryptionState: " + + encryptionState + " }"); + FrameworkStatsLog.write(FrameworkStatsLog.USERSPACE_REBOOT_REPORTED, outcome, + durationMillis, encryptionState); + SystemProperties.set(USERSPACE_REBOOT_SHOULD_LOG_PROPERTY, ""); + }); + } + + private static int computeOutcome() { + if (SystemProperties.getLong(USERSPACE_REBOOT_LAST_STARTED_PROPERTY, -1) != -1) { + return USERSPACE_REBOOT_REPORTED__OUTCOME__SUCCESS; + } + String reason = SystemProperties.get(BOOT_REASON_PROPERTY, ""); + if (reason.startsWith("reboot,")) { + reason = reason.substring("reboot".length()); + } + switch (reason) { + case "userspace_failed,watchdog_fork": + // Since fork happens before shutdown sequence, attribute it to + // USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_SHUTDOWN_SEQUENCE_ABORTED. + case "userspace_failed,shutdown_aborted": + return USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_SHUTDOWN_SEQUENCE_ABORTED; + case "userspace_failed,init_user0_failed": + // init_user0 will fail if userdata wasn't remounted correctly, attribute to + // USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_USERDATA_REMOUNT. + case "mount_userdata_failed": + return USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_USERDATA_REMOUNT; + case "userspace_failed,watchdog_triggered": + return + USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_USERSPACE_REBOOT_WATCHDOG_TRIGGERED; + default: + return USERSPACE_REBOOT_REPORTED__OUTCOME__OUTCOME_UNKNOWN; + } + } +} diff --git a/services/core/java/com/android/server/adb/AdbService.java b/services/core/java/com/android/server/adb/AdbService.java index f2a8615dca88..0d161b943d15 100644 --- a/services/core/java/com/android/server/adb/AdbService.java +++ b/services/core/java/com/android/server/adb/AdbService.java @@ -134,9 +134,13 @@ public class AdbService extends IAdbManager.Stub { mIsAdbWifiEnabled = false; // register observer to listen for settings changes + mObserver = new AdbSettingsObserver(); mContentResolver.registerContentObserver( Settings.Global.getUriFor(Settings.Global.ADB_ENABLED), - false, new AdbSettingsObserver()); + false, mObserver); + mContentResolver.registerContentObserver( + Settings.Global.getUriFor(Settings.Global.ADB_WIFI_ENABLED), + false, mObserver); } catch (Exception e) { Slog.e(TAG, "Error in initAdbState", e); } @@ -153,6 +157,7 @@ public class AdbService extends IAdbManager.Stub { private class AdbSettingsObserver extends ContentObserver { private final Uri mAdbUsbUri = Settings.Global.getUriFor(Settings.Global.ADB_ENABLED); + private final Uri mAdbWifiUri = Settings.Global.getUriFor(Settings.Global.ADB_WIFI_ENABLED); AdbSettingsObserver() { super(null); @@ -166,8 +171,13 @@ public class AdbService extends IAdbManager.Stub { FgThread.getHandler().sendMessage(obtainMessage( AdbService::setAdbEnabled, AdbService.this, shouldEnable, AdbTransportType.USB)); + } else if (mAdbWifiUri.equals(uri)) { + boolean shouldEnable = (Settings.Global.getInt(mContentResolver, + Settings.Global.ADB_WIFI_ENABLED, 0) > 0); + FgThread.getHandler().sendMessage(obtainMessage( + AdbService::setAdbEnabled, AdbService.this, shouldEnable, + AdbTransportType.WIFI)); } - // TODO(joshuaduong): Add condition for WIFI transport } } @@ -188,6 +198,8 @@ public class AdbService extends IAdbManager.Stub { private boolean mIsAdbWifiEnabled; private AdbDebuggingManager mDebuggingManager; + private ContentObserver mObserver; + private AdbService(Context context) { mContext = context; mContentResolver = context.getContentResolver(); @@ -213,6 +225,8 @@ public class AdbService extends IAdbManager.Stub { try { Settings.Global.putInt(mContentResolver, Settings.Global.ADB_ENABLED, mIsAdbUsbEnabled ? 1 : 0); + Settings.Global.putInt(mContentResolver, + Settings.Global.ADB_WIFI_ENABLED, mIsAdbWifiEnabled ? 1 : 0); } catch (SecurityException e) { // If UserManager.DISALLOW_DEBUGGING_FEATURES is on, that this setting can't be changed. Slog.d(TAG, "ADB_ENABLED is restricted."); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 2af04ae3f800..53d23842ec79 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -275,6 +275,7 @@ import android.provider.DeviceConfig; import android.provider.DeviceConfig.Properties; import android.provider.Settings; import android.server.ServerProtoEnums; +import android.sysprop.InitProperties; import android.sysprop.VoldProperties; import android.text.TextUtils; import android.text.format.DateUtils; @@ -346,6 +347,7 @@ import com.android.server.SystemConfig; import com.android.server.SystemService; import com.android.server.SystemServiceManager; import com.android.server.ThreadPriorityBooster; +import com.android.server.UserspaceRebootLogger; import com.android.server.Watchdog; import com.android.server.am.ActivityManagerServiceDumpProcessesProto.UidObserverRegistrationProto; import com.android.server.appop.AppOpsService; @@ -2253,6 +2255,20 @@ public class ActivityManagerService extends IActivityManager.Stub } } + private void maybeLogUserspaceRebootEvent() { + if (!UserspaceRebootLogger.shouldLogUserspaceRebootEvent()) { + return; + } + final int userId = mUserController.getCurrentUserId(); + if (userId != UserHandle.USER_SYSTEM) { + // Only log for user0. + return; + } + // TODO(b/148767783): should we check all profiles under user0? + UserspaceRebootLogger.logEventAsync(StorageManager.isUserKeyUnlocked(userId), + BackgroundThread.getExecutor()); + } + /** * Encapsulates global settings related to hidden API enforcement behaviour, including tracking * the latest value via a content observer. @@ -5306,6 +5322,12 @@ public class ActivityManagerService extends IActivityManager.Stub // Start looking for apps that are abusing wake locks. Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_POWER_USE_MSG); mHandler.sendMessageDelayed(nmsg, mConstants.POWER_CHECK_INTERVAL); + // Check if we are performing userspace reboot before setting sys.boot_completed to + // avoid race with init reseting sys.init.userspace_reboot.in_progress once sys + // .boot_completed is 1. + if (InitProperties.userspace_reboot_in_progress().orElse(false)) { + UserspaceRebootLogger.noteUserspaceRebootSuccess(); + } // Tell anyone interested that we are done booting! SystemProperties.set("sys.boot_completed", "1"); @@ -5326,6 +5348,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } }); + maybeLogUserspaceRebootEvent(); mUserController.scheduleStartProfiles(); } diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java index 3be51c58798e..98c6c6d3861f 100644 --- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java +++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java @@ -562,6 +562,9 @@ public class UserRestrictionsUtils { android.provider.Settings.Global.putStringForUser(cr, android.provider.Settings.Global.ADB_ENABLED, "0", userId); + android.provider.Settings.Global.putStringForUser(cr, + android.provider.Settings.Global.ADB_WIFI_ENABLED, "0", + userId); } } break; @@ -702,6 +705,7 @@ public class UserRestrictionsUtils { break; case android.provider.Settings.Global.ADB_ENABLED: + case android.provider.Settings.Global.ADB_WIFI_ENABLED: if ("0".equals(value)) { return false; } diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 3a7604aa7d69..26a623f9a1fc 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -23,6 +23,7 @@ import static android.os.PowerManagerInternal.WAKEFULNESS_DREAMING; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.SynchronousUserSwitchObserver; @@ -91,6 +92,7 @@ import com.android.server.RescueParty; import com.android.server.ServiceThread; import com.android.server.SystemService; import com.android.server.UiThread; +import com.android.server.UserspaceRebootLogger; import com.android.server.Watchdog; import com.android.server.am.BatteryStatsService; import com.android.server.lights.LightsManager; @@ -2834,7 +2836,10 @@ public final class PowerManagerService extends SystemService } private void shutdownOrRebootInternal(final @HaltMode int haltMode, final boolean confirm, - final String reason, boolean wait) { + @Nullable final String reason, boolean wait) { + if (PowerManager.REBOOT_USERSPACE.equals(reason)) { + UserspaceRebootLogger.noteUserspaceRebootWasRequested(); + } if (mHandler == null || !mSystemReady) { if (RescueParty.isAttemptingFactoryReset()) { // If we're stuck in a really low-level reboot loop, and a @@ -4649,7 +4654,7 @@ public final class PowerManagerService extends SystemService * @param wait If true, this call waits for the reboot to complete and does not return. */ @Override // Binder call - public void reboot(boolean confirm, String reason, boolean wait) { + public void reboot(boolean confirm, @Nullable String reason, boolean wait) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null); if (PowerManager.REBOOT_RECOVERY.equals(reason) || PowerManager.REBOOT_RECOVERY_UPDATE.equals(reason)) { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index cbbb7fff8aea..03f64fca5591 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -434,6 +434,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { GLOBAL_SETTINGS_WHITELIST = new ArraySet<>(); GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.ADB_ENABLED); + GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.ADB_WIFI_ENABLED); GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.AUTO_TIME); GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.AUTO_TIME_ZONE); GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.DATA_ROAMING); diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index b93365ad0ad5..de7ae5509a18 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -41,7 +41,6 @@ import android.database.sqlite.SQLiteCompatibilityWalFlags; import android.database.sqlite.SQLiteGlobal; import android.hardware.display.DisplayManagerInternal; import android.net.ConnectivityModuleConnector; -import android.net.ITetheringConnector; import android.net.NetworkStackClient; import android.os.BaseBundle; import android.os.Binder; @@ -286,6 +285,8 @@ public final class SystemServer { private static final String CONTENT_SUGGESTIONS_SERVICE_CLASS = "com.android.server.contentsuggestions.ContentSuggestionsManagerService"; + private static final String TETHERING_CONNECTOR_CLASS = "android.net.ITetheringConnector"; + private static final String PERSISTENT_DATA_BLOCK_PROP = "ro.frp.pst"; private static final String UNCRYPT_PACKAGE_FILE = "/cache/recovery/uncrypt_file"; @@ -2226,7 +2227,7 @@ public final class SystemServer { try { // TODO: hide implementation details, b/146312721. ConnectivityModuleConnector.getInstance().startModuleService( - ITetheringConnector.class.getName(), + TETHERING_CONNECTOR_CLASS, PERMISSION_MAINLINE_NETWORK_STACK, service -> { ServiceManager.addService(Context.TETHERING_SERVICE, service, false /* allowIsolated */, diff --git a/tests/net/AndroidManifest.xml b/tests/net/AndroidManifest.xml index 638b6d1d7b5a..480b12be91c8 100644 --- a/tests/net/AndroidManifest.xml +++ b/tests/net/AndroidManifest.xml @@ -50,6 +50,7 @@ <application> <uses-library android:name="android.test.runner" /> + <uses-library android:name="android.net.ipsec.ike" /> </application> <instrumentation diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 77147c8a35af..86ba8afe0c1c 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -1180,6 +1180,10 @@ public class ConnectivityServiceTest { Arrays.asList(new UserInfo[] { new UserInfo(VPN_USER, "", 0), })); + final ApplicationInfo applicationInfo = new ApplicationInfo(); + applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q; + when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any())) + .thenReturn(applicationInfo); // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not. // http://b/25897652 . @@ -3041,7 +3045,7 @@ public class ConnectivityServiceTest { networkCapabilities.addTransportType(TRANSPORT_WIFI) .setNetworkSpecifier(new MatchAllNetworkSpecifier()); mService.requestNetwork(networkCapabilities, null, 0, null, - ConnectivityManager.TYPE_WIFI, TEST_PACKAGE_NAME); + ConnectivityManager.TYPE_WIFI, mContext.getPackageName()); }); class NonParcelableSpecifier extends NetworkSpecifier { @@ -6438,17 +6442,89 @@ public class ConnectivityServiceTest { assertEquals(wifiLp, mService.getActiveLinkProperties()); } + private void setupLocationPermissions( + int targetSdk, boolean locationToggle, String op, String perm) throws Exception { + final ApplicationInfo applicationInfo = new ApplicationInfo(); + applicationInfo.targetSdkVersion = targetSdk; + when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any())) + .thenReturn(applicationInfo); + + when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(locationToggle); + + if (op != null) { + when(mAppOpsManager.noteOp(eq(op), eq(Process.myUid()), eq(mContext.getPackageName()))) + .thenReturn(AppOpsManager.MODE_ALLOWED); + } + + if (perm != null) { + mServiceContext.setPermission(perm, PERMISSION_GRANTED); + } + } + + private int getOwnerUidNetCapsForCallerPermission(int ownerUid, int callerUid) { + final NetworkCapabilities netCap = new NetworkCapabilities().setOwnerUid(ownerUid); + + return mService + .maybeSanitizeLocationInfoForCaller(netCap, callerUid, mContext.getPackageName()) + .getOwnerUid(); + } + + @Test + public void testMaybeSanitizeLocationInfoForCallerWithFineLocationAfterQ() throws Exception { + setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION); + + final int myUid = Process.myUid(); + assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid)); + } + + @Test + public void testMaybeSanitizeLocationInfoForCallerWithCoarseLocationPreQ() throws Exception { + setupLocationPermissions(Build.VERSION_CODES.P, true, AppOpsManager.OPSTR_COARSE_LOCATION, + Manifest.permission.ACCESS_COARSE_LOCATION); + + final int myUid = Process.myUid(); + assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid)); + } + + @Test + public void testMaybeSanitizeLocationInfoForCallerLocationOff() throws Exception { + // Test that even with fine location permission, and UIDs matching, the UID is sanitized. + setupLocationPermissions(Build.VERSION_CODES.Q, false, AppOpsManager.OPSTR_FINE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION); + + final int myUid = Process.myUid(); + assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid)); + } + + @Test + public void testMaybeSanitizeLocationInfoForCallerWrongUid() throws Exception { + // Test that even with fine location permission, not being the owner leads to sanitization. + setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION); + + final int myUid = Process.myUid(); + assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid + 1, myUid)); + } + @Test - public void testNetworkCapabilitiesRestrictedForCallerPermissions() { - int callerUid = Process.myUid(); - final NetworkCapabilities originalNc = new NetworkCapabilities(); - originalNc.setOwnerUid(callerUid); + public void testMaybeSanitizeLocationInfoForCallerWithCoarseLocationAfterQ() throws Exception { + // Test that not having fine location permission leads to sanitization. + setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_COARSE_LOCATION, + Manifest.permission.ACCESS_COARSE_LOCATION); + + // Test that without the location permission, the owner field is sanitized. + final int myUid = Process.myUid(); + assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid)); + } - final NetworkCapabilities newNc = - mService.networkCapabilitiesRestrictedForCallerPermissions( - originalNc, Process.myPid(), callerUid); + @Test + public void testMaybeSanitizeLocationInfoForCallerWithoutLocationPermission() throws Exception { + setupLocationPermissions(Build.VERSION_CODES.Q, true, null /* op */, null /* perm */); - assertEquals(Process.INVALID_UID, newNc.getOwnerUid()); + // Test that without the location permission, the owner field is sanitized. + final int myUid = Process.myUid(); + assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid)); } private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType) @@ -6734,21 +6810,6 @@ public class ConnectivityServiceTest { mContext.getOpPackageName())); } - private void setupLocationPermissions( - int targetSdk, boolean locationToggle, String op, String perm) throws Exception { - final ApplicationInfo applicationInfo = new ApplicationInfo(); - applicationInfo.targetSdkVersion = targetSdk; - when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any())) - .thenReturn(applicationInfo); - - when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(locationToggle); - - when(mAppOpsManager.noteOp(eq(op), eq(Process.myUid()), eq(mContext.getPackageName()))) - .thenReturn(AppOpsManager.MODE_ALLOWED); - - mServiceContext.setPermission(perm, PERMISSION_GRANTED); - } - private void setUpConnectivityDiagnosticsCallback() throws Exception { final NetworkRequest request = new NetworkRequest.Builder().build(); when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder); diff --git a/tools/hiddenapi/merge_csv.py b/tools/hiddenapi/merge_csv.py index 96619273af8d..6a5b0e1347b2 100755 --- a/tools/hiddenapi/merge_csv.py +++ b/tools/hiddenapi/merge_csv.py @@ -14,26 +14,56 @@ # See the License for the specific language governing permissions and # limitations under the License. """ -Merge mutliple CSV files, possibly with different columns, writing to stdout. +Merge multiple CSV files, possibly with different columns. """ +import argparse import csv -import sys +import io -csv_readers = [ - csv.DictReader(open(csv_file, 'r'), delimiter=',', quotechar='|') - for csv_file in sys.argv[1:] -] +from zipfile import ZipFile + +args_parser = argparse.ArgumentParser(description='Merge given CSV files into a single one.') +args_parser.add_argument('--header', help='Comma separated field names; ' + 'if missing determines the header from input files.') +args_parser.add_argument('--zip_input', help='ZIP archive with all CSV files to merge.') +args_parser.add_argument('--output', help='Output file for merged CSV.', + default='-', type=argparse.FileType('w')) +args_parser.add_argument('files', nargs=argparse.REMAINDER) +args = args_parser.parse_args() + + +def dict_reader(input): + return csv.DictReader(input, delimiter=',', quotechar='|') + + +if args.zip_input and len(args.files) > 0: + raise ValueError('Expecting either a single ZIP with CSV files' + ' or a list of CSV files as input; not both.') + +csv_readers = [] +if len(args.files) > 0: + for file in args.files: + csv_readers.append(dict_reader(open(file, 'r'))) +elif args.zip_input: + with ZipFile(args.zip_input) as zip: + for entry in zip.namelist(): + if entry.endswith('.uau'): + csv_readers.append(dict_reader(io.TextIOWrapper(zip.open(entry, 'r')))) -# Build union of all columns from source files: headers = set() -for reader in csv_readers: - headers = headers.union(reader.fieldnames) +if args.header: + fieldnames = args.header.split(',') +else: + # Build union of all columns from source files: + for reader in csv_readers: + headers = headers.union(reader.fieldnames) + fieldnames = sorted(headers) # Concatenate all files to output: -out = csv.DictWriter(sys.stdout, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL, - dialect='unix', fieldnames=sorted(headers)) -out.writeheader() +writer = csv.DictWriter(args.output, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL, + dialect='unix', fieldnames=fieldnames) +writer.writeheader() for reader in csv_readers: for row in reader: - out.writerow(row) + writer.writerow(row) |