diff options
284 files changed, 3135 insertions, 995 deletions
diff --git a/StubLibraries.bp b/StubLibraries.bp index 626f9772655d..e194c47e8f9c 100644 --- a/StubLibraries.bp +++ b/StubLibraries.bp @@ -251,7 +251,7 @@ modules_public_stubs = [ modules_system_stubs = [ "android.net.ipsec.ike.stubs.system", - "art.module.public.api.stubs", // Only has public stubs + "art.module.public.api.stubs.system", "conscrypt.module.public.api.stubs", // Only has public stubs "framework-connectivity.stubs.system", "framework-media.stubs.system", diff --git a/apex/media/Android.bp b/apex/media/Android.bp index 308741a6733d..a75f1aed4ade 100644 --- a/apex/media/Android.bp +++ b/apex/media/Android.bp @@ -24,3 +24,10 @@ package { // SPDX-license-identifier-Apache-2.0 default_applicable_licenses: ["frameworks_base_license"], } + +sdk { + name: "media-module-sdk", + java_sdk_libs: [ + "framework-media", + ], +} diff --git a/api/Android.bp b/api/Android.bp index 2df31ecb7715..438e7dc29b22 100644 --- a/api/Android.bp +++ b/api/Android.bp @@ -24,12 +24,17 @@ package { default_applicable_licenses: ["frameworks_base_license"], } +metalava_cmd = "$(location metalava)" +// Silence reflection warnings. See b/168689341 +metalava_cmd += " -J--add-opens=java.base/java.util=ALL-UNNAMED " +metalava_cmd += " --no-banner --format=v2 " + genrule { name: "current-api-xml", tools: ["metalava"], srcs: [":frameworks-base-api-current.txt"], out: ["current.api"], - cmd: "$(location metalava) --no-banner -convert2xmlnostrip $(in) $(out)", + cmd: metalava_cmd + "-convert2xmlnostrip $(in) $(out)", visibility: ["//visibility:public"], } @@ -52,7 +57,7 @@ genrule { ], out: ["current.txt"], tools: ["metalava"], - cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)", + cmd: metalava_cmd + "$(in) --api $(out)", dists: [ { targets: ["droidcore"], @@ -77,7 +82,7 @@ genrule { ], out: ["stdout.txt"], tools: ["metalava"], - cmd: "$(location metalava) --no-banner --format=v2 " + + cmd: metalava_cmd + "--check-compatibility:api:released $(location :android.api.public.latest) " + "--baseline:compatibility:released $(location :android-incompatibilities.api.public.latest) " + "$(location :frameworks-base-api-current.txt) " + @@ -126,7 +131,7 @@ genrule { ], out: ["removed.txt"], tools: ["metalava"], - cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)", + cmd: metalava_cmd + "$(in) --api $(out)", dists: [ { targets: ["droidcore"], @@ -144,6 +149,7 @@ genrule { genrule { name: "frameworks-base-api-system-current.txt", srcs: [ + ":art.module.public.api{.system.api.txt}", ":android.net.ipsec.ike{.system.api.txt}", ":framework-connectivity{.system.api.txt}", ":framework-media{.system.api.txt}", @@ -157,7 +163,7 @@ genrule { ], out: ["system-current.txt"], tools: ["metalava"], - cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)", + cmd: metalava_cmd + "$(in) --api $(out)", dists: [ { targets: ["droidcore"], @@ -183,7 +189,7 @@ genrule { ], out: ["stdout.txt"], tools: ["metalava"], - cmd: "$(location metalava) --no-banner --format=v2 " + + cmd: metalava_cmd + "--check-compatibility:api:released $(location :android.api.system.latest) " + "--check-compatibility:base $(location :frameworks-base-api-current.txt) " + "--baseline:compatibility:released $(location :android-incompatibilities.api.system.latest) " + @@ -194,6 +200,7 @@ genrule { genrule { name: "frameworks-base-api-system-removed.txt", srcs: [ + ":art.module.public.api{.system.removed-api.txt}", ":android.net.ipsec.ike{.system.removed-api.txt}", ":framework-connectivity{.system.removed-api.txt}", ":framework-media{.system.removed-api.txt}", @@ -207,7 +214,7 @@ genrule { ], out: ["system-removed.txt"], tools: ["metalava"], - cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)", + cmd: metalava_cmd + "$(in) --api $(out)", dists: [ { targets: ["droidcore"], @@ -226,6 +233,7 @@ genrule { genrule { name: "frameworks-base-api-module-lib-current.txt", srcs: [ + ":art.module.public.api{.module-lib.api.txt}", ":android.net.ipsec.ike{.module-lib.api.txt}", ":framework-connectivity{.module-lib.api.txt}", ":framework-media{.module-lib.api.txt}", @@ -239,7 +247,7 @@ genrule { ], out: ["module-lib-current.txt"], tools: ["metalava"], - cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)", + cmd: metalava_cmd + "$(in) --api $(out)", dists: [ { targets: ["droidcore"], @@ -264,7 +272,7 @@ genrule { ], out: ["stdout.txt"], tools: ["metalava"], - cmd: "$(location metalava) --no-banner --format=v2 " + + cmd: metalava_cmd + "--check-compatibility:api:released $(location :android.api.module-lib.latest) " + // Note: having "public" be the base of module-lib is not perfect -- it should // ideally be a merged public+system), but this will help when migrating from @@ -278,6 +286,7 @@ genrule { genrule { name: "frameworks-base-api-module-lib-removed.txt", srcs: [ + ":art.module.public.api{.module-lib.removed-api.txt}", ":android.net.ipsec.ike{.module-lib.removed-api.txt}", ":framework-connectivity{.module-lib.removed-api.txt}", ":framework-media{.module-lib.removed-api.txt}", @@ -291,7 +300,7 @@ genrule { ], out: ["module-lib-removed.txt"], tools: ["metalava"], - cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)", + cmd: metalava_cmd + "$(in) --api $(out)", dists: [ { targets: ["droidcore"], @@ -331,7 +340,7 @@ genrule { ], out: ["system-server-current.txt"], tools: ["metalava"], - cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)", + cmd: metalava_cmd + "$(in) --api $(out)", dists: [ { targets: ["droidcore"], @@ -354,7 +363,7 @@ genrule { ], out: ["system-server-removed.txt"], tools: ["metalava"], - cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)", + cmd: metalava_cmd + "$(in) --api $(out)", dists: [ { targets: ["droidcore"], diff --git a/cmds/idmap2/OWNERS b/cmds/idmap2/OWNERS index f1903a5a54a7..69dfcc98340d 100644 --- a/cmds/idmap2/OWNERS +++ b/cmds/idmap2/OWNERS @@ -1,3 +1,4 @@ set noparent toddke@google.com -rtmitchell@google.com
\ No newline at end of file +rtmitchell@google.com +patb@google.com
\ No newline at end of file diff --git a/core/api/current.txt b/core/api/current.txt index cd4e6f9a826c..e32f07b53187 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -25711,7 +25711,7 @@ package android.net.vcn { public final class VcnGatewayConnectionConfig { method @NonNull public int[] getExposedCapabilities(); method @NonNull public String getGatewayConnectionName(); - method @IntRange(from=android.net.vcn.VcnGatewayConnectionConfig.MIN_MTU_V6) public int getMaxMtu(); + method @IntRange(from=0x500) public int getMaxMtu(); method @NonNull public long[] getRetryIntervalsMillis(); } @@ -25720,7 +25720,7 @@ package android.net.vcn { method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder addExposedCapability(int); method @NonNull public android.net.vcn.VcnGatewayConnectionConfig build(); method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder removeExposedCapability(int); - method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder setMaxMtu(@IntRange(from=android.net.vcn.VcnGatewayConnectionConfig.MIN_MTU_V6) int); + method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder setMaxMtu(@IntRange(from=0x500) int); method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder setRetryIntervalsMillis(@NonNull long[]); } diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index 848f480c79a1..5d23eb20a81a 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -89,9 +89,9 @@ package android.net { public final class UnderlyingNetworkInfo implements android.os.Parcelable { ctor public UnderlyingNetworkInfo(int, @NonNull String, @NonNull java.util.List<java.lang.String>); method public int describeContents(); - method @NonNull public String getIface(); + method @NonNull public String getInterface(); method public int getOwnerUid(); - method @NonNull public java.util.List<java.lang.String> getUnderlyingIfaces(); + method @NonNull public java.util.List<java.lang.String> getUnderlyingInterfaces(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.net.UnderlyingNetworkInfo> CREATOR; } diff --git a/core/api/system-current.txt b/core/api/system-current.txt index bb42ddcda37f..1aa8aed7c7ec 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -1124,10 +1124,10 @@ package android.app.backup { package android.app.compat { public final class CompatChanges { - method @RequiresPermission(android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD) public static void addPackageOverrides(@NonNull String, @NonNull java.util.Map<java.lang.Long,android.app.compat.PackageOverride>); method public static boolean isChangeEnabled(long); method @RequiresPermission(allOf={"android.permission.READ_COMPAT_CHANGE_CONFIG", "android.permission.LOG_COMPAT_CHANGE"}) public static boolean isChangeEnabled(long, @NonNull String, @NonNull android.os.UserHandle); method @RequiresPermission(allOf={"android.permission.READ_COMPAT_CHANGE_CONFIG", "android.permission.LOG_COMPAT_CHANGE"}) public static boolean isChangeEnabled(long, int); + method @RequiresPermission(android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD) public static void putPackageOverrides(@NonNull String, @NonNull java.util.Map<java.lang.Long,android.app.compat.PackageOverride>); method @RequiresPermission(android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD) public static void removePackageOverrides(@NonNull String, @NonNull java.util.Set<java.lang.Long>); } diff --git a/core/java/android/app/DexLoadReporter.java b/core/java/android/app/DexLoadReporter.java index 5bc999240a66..a172c058e091 100644 --- a/core/java/android/app/DexLoadReporter.java +++ b/core/java/android/app/DexLoadReporter.java @@ -138,23 +138,25 @@ import java.util.Set; // NOTE: Keep this in sync with installd expectations. File dexPathFile = new File(dexPath); File secondaryProfileDir = new File(dexPathFile.getParent(), "oat"); - File secondaryProfile = new File(secondaryProfileDir, dexPathFile.getName() + ".cur.prof"); + File secondaryCurProfile = + new File(secondaryProfileDir, dexPathFile.getName() + ".cur.prof"); + File secondaryRefProfile = new File(secondaryProfileDir, dexPathFile.getName() + ".prof"); // Create the profile if not already there. // Returns true if the file was created, false if the file already exists. // or throws exceptions in case of errors. if (!secondaryProfileDir.exists()) { if (!secondaryProfileDir.mkdir()) { - Slog.e(TAG, "Could not create the profile directory: " + secondaryProfile); + Slog.e(TAG, "Could not create the profile directory: " + secondaryCurProfile); // Do not continue with registration if we could not create the oat dir. return; } } try { - boolean created = secondaryProfile.createNewFile(); + boolean created = secondaryCurProfile.createNewFile(); if (DEBUG && created) { - Slog.i(TAG, "Created profile for secondary dex: " + secondaryProfile); + Slog.i(TAG, "Created profile for secondary dex: " + secondaryCurProfile); } } catch (IOException ex) { Slog.e(TAG, "Failed to create profile for secondary dex " + dexPath @@ -165,7 +167,12 @@ import java.util.Set; // If we got here, the dex paths is a secondary dex and we were able to create the profile. // Register the path to the runtime. - VMRuntime.registerAppInfo(secondaryProfile.getPath(), new String[] { dexPath }); + VMRuntime.registerAppInfo( + ActivityThread.currentPackageName(), + secondaryCurProfile.getPath(), + secondaryRefProfile.getPath(), + new String[] { dexPath }, + VMRuntime.CODE_PATH_TYPE_SECONDARY_DEX); } // A dex file is a secondary dex file if it is in any of the registered app diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index b45f3893db8c..5d2370db8e88 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -884,7 +884,7 @@ public final class LoadedApk { if (DEBUG) Slog.v(ActivityThread.TAG, "Class path: " + zip + ", JNI path: " + librarySearchPath); - boolean needToSetupJitProfiles = false; + boolean registerAppInfoToArt = false; if (mDefaultClassLoader == null) { // Temporarily disable logging of disk reads on the Looper thread // as this is early and necessary. @@ -902,7 +902,7 @@ public final class LoadedApk { setThreadPolicy(oldPolicy); // Setup the class loader paths for profiling. - needToSetupJitProfiles = true; + registerAppInfoToArt = true; } if (!libPaths.isEmpty()) { @@ -919,7 +919,7 @@ public final class LoadedApk { final String add = TextUtils.join(File.pathSeparator, addedPaths); ApplicationLoaders.getDefault().addPath(mDefaultClassLoader, add); // Setup the new code paths for profiling. - needToSetupJitProfiles = true; + registerAppInfoToArt = true; } // Setup jit profile support. @@ -933,8 +933,8 @@ public final class LoadedApk { // loads code from) so we explicitly disallow it there. // // It is not ok to call this in a zygote context where mActivityThread is null. - if (needToSetupJitProfiles && !ActivityThread.isSystem() && mActivityThread != null) { - setupJitProfileSupport(); + if (registerAppInfoToArt && !ActivityThread.isSystem() && mActivityThread != null) { + registerAppInfoToArt(); } // Call AppComponentFactory to select/create the main class loader of this app. @@ -984,12 +984,8 @@ public final class LoadedApk { } } - private void setupJitProfileSupport() { - if (!SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false)) { - return; - } - - // If we use profiles, setup the dex reporter to notify package manager + private void registerAppInfoToArt() { + // Setup the dex reporter to notify package manager // of any relevant dex loads. The idle maintenance job will use the information // reported to optimize the loaded dex files. // Note that we only need one global reporter per app. @@ -1022,9 +1018,19 @@ public final class LoadedApk { for (int i = codePaths.size() - 1; i >= 0; i--) { String splitName = i == 0 ? null : mApplicationInfo.splitNames[i - 1]; - String profileFile = ArtManager.getCurrentProfilePath( + String curProfileFile = ArtManager.getCurrentProfilePath( + mPackageName, UserHandle.myUserId(), splitName); + String refProfileFile = ArtManager.getReferenceProfilePath( mPackageName, UserHandle.myUserId(), splitName); - VMRuntime.registerAppInfo(profileFile, new String[] {codePaths.get(i)}); + int codePathType = codePaths.get(i).equals(mApplicationInfo.sourceDir) + ? VMRuntime.CODE_PATH_TYPE_PRIMARY_APK + : VMRuntime.CODE_PATH_TYPE_SPLIT_APK; + VMRuntime.registerAppInfo( + mPackageName, + curProfileFile, + refProfileFile, + new String[] {codePaths.get(i)}, + codePathType); } // Register the app data directory with the reporter. It will diff --git a/core/java/android/app/RESOURCES_OWNERS b/core/java/android/app/RESOURCES_OWNERS index 21c39a8828ad..558280396348 100644 --- a/core/java/android/app/RESOURCES_OWNERS +++ b/core/java/android/app/RESOURCES_OWNERS @@ -1,2 +1,3 @@ rtmitchell@google.com toddke@google.com +patb@google.com diff --git a/core/java/android/app/compat/CompatChanges.java b/core/java/android/app/compat/CompatChanges.java index 8ca43c4a8e70..24ca72c66ab4 100644 --- a/core/java/android/app/compat/CompatChanges.java +++ b/core/java/android/app/compat/CompatChanges.java @@ -100,9 +100,10 @@ public final class CompatChanges { } /** - * Adds app compat overrides for a given package. This will check whether the caller is allowed - * to perform this operation on the given apk and build. Only the installer package is allowed - * to set overrides on a non-debuggable final build and a non-test apk. + * Associates app compat overrides with the given package and their respective change IDs. + * This will check whether the caller is allowed to perform this operation on the given apk and + * build. Only the installer package is allowed to set overrides on a non-debuggable final + * build and a non-test apk. * * <p>Note that calling this method doesn't remove previously added overrides for the given * package if their change ID isn't in the given map, only replaces those that have the same @@ -112,7 +113,7 @@ public final class CompatChanges { * @param overrides A map from change ID to the override applied for this change ID. */ @RequiresPermission(android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD) - public static void addPackageOverrides(@NonNull String packageName, + public static void putPackageOverrides(@NonNull String packageName, @NonNull Map<Long, PackageOverride> overrides) { IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface( ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE)); @@ -125,7 +126,7 @@ public final class CompatChanges { } /** - * Removes app compat overrides for a given package. This will check whether the caller is + * Removes app compat overrides for the given package. This will check whether the caller is * allowed to perform this operation on the given apk and build. Only the installer package is * allowed to clear overrides on a non-debuggable final build and a non-test apk. * diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 9f1132b605ef..fe99f8532aaa 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -644,7 +644,10 @@ public class NetworkStatsManager { : NetworkTemplate.buildTemplateMobileAll(subscriberId); break; case ConnectivityManager.TYPE_WIFI: - template = NetworkTemplate.buildTemplateWifiWildcard(); + template = subscriberId == null + ? NetworkTemplate.buildTemplateWifiWildcard() + : NetworkTemplate.buildTemplateWifi(NetworkTemplate.WIFI_NETWORKID_ALL, + subscriberId); break; default: throw new IllegalArgumentException("Cannot create template for network type " @@ -655,14 +658,14 @@ public class NetworkStatsManager { } /** - * Notify {@code NetworkStatsService} about network status changed. + * Notify {@code NetworkStatsService} about network status changed. * - * Notifies NetworkStatsService of network state changes for data usage accounting purposes. + * Notifies NetworkStatsService of network state changes for data usage accounting purposes. * - * To avoid races that attribute data usage to wrong network, such as new network with - * the same interface after SIM hot-swap, this function will not return until - * {@code NetworkStatsService} finishes its work of retrieving traffic statistics from - * all data sources. + * To avoid races that attribute data usage to wrong network, such as new network with + * the same interface after SIM hot-swap, this function will not return until + * {@code NetworkStatsService} finishes its work of retrieving traffic statistics from + * all data sources. * * @param defaultNetworks the list of all networks that could be used by network traffic that * does not explicitly select a network. @@ -689,8 +692,7 @@ public class NetworkStatsManager { Objects.requireNonNull(defaultNetworks); Objects.requireNonNull(networkStateSnapshots); Objects.requireNonNull(underlyingNetworkInfos); - // TODO: Change internal namings after the name is decided. - mService.forceUpdateIfaces(defaultNetworks.toArray(new Network[0]), + mService.notifyNetworkStatus(defaultNetworks.toArray(new Network[0]), networkStateSnapshots.toArray(new NetworkStateSnapshot[0]), activeIface, underlyingNetworkInfos.toArray(new UnderlyingNetworkInfo[0])); } catch (RemoteException e) { diff --git a/core/java/android/content/pm/dex/ArtManager.java b/core/java/android/content/pm/dex/ArtManager.java index b0970f4878db..009ebb9b4b96 100644 --- a/core/java/android/content/pm/dex/ArtManager.java +++ b/core/java/android/content/pm/dex/ArtManager.java @@ -201,6 +201,16 @@ public class ArtManager { } /** + * Return the path to the current profile corresponding to given package and split. + * + * @hide + */ + public static String getReferenceProfilePath(String packageName, int userId, String splitName) { + File profileDir = Environment.getDataRefProfilesDePackageDirectory(packageName); + return new File(profileDir, getProfileName(splitName)).getAbsolutePath(); + } + + /** * Return the snapshot profile file for the given package and profile name. * * KEEP in sync with installd dexopt.cpp. diff --git a/core/java/android/content/pm/parsing/result/ParseTypeImpl.java b/core/java/android/content/pm/parsing/result/ParseTypeImpl.java index 14992fb2a4d1..3740ef7d5a92 100644 --- a/core/java/android/content/pm/parsing/result/ParseTypeImpl.java +++ b/core/java/android/content/pm/parsing/result/ParseTypeImpl.java @@ -119,6 +119,7 @@ public class ParseTypeImpl implements ParseInput, ParseResult<Object> { // how many APKs they're going through. mDeferredErrors.erase(); } + mTargetSdkVersion = null; return this; } diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index dc3b88a7c3be..12937b5cb2c7 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -65,8 +65,8 @@ interface INetworkStatsService { /** Increment data layer count of operations performed for UID and tag. */ void incrementOperationCount(int uid, int tag, int operationCount); - /** Force update of ifaces. */ - void forceUpdateIfaces( + /** Notify {@code NetworkStatsService} about network status changed. */ + void notifyNetworkStatus( in Network[] defaultNetworks, in NetworkStateSnapshot[] snapshots, in String activeIface, diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 01d1aa533a8f..c10680761ff1 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -810,7 +810,9 @@ public final class IpSecManager { * * @param underlyingNetwork the new {@link Network} that will carry traffic for this tunnel. * This network MUST never be the network exposing this IpSecTunnelInterface, otherwise - * this method will throw an {@link IllegalArgumentException}. + * this method will throw an {@link IllegalArgumentException}. If the + * IpSecTunnelInterface is later added to this network, all outbound traffic will be + * blackholed. */ // TODO: b/169171001 Update the documentation when transform migration is supported. // The purpose of making updating network and applying transforms separate is to leave open diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index 3bde6fa6913d..1d07a0330bc5 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -26,8 +26,10 @@ import android.service.NetworkIdentityProto; import android.telephony.Annotation.NetworkType; import android.util.proto.ProtoOutputStream; +import com.android.net.module.util.NetworkCapabilitiesUtils; import com.android.net.module.util.NetworkIdentityUtils; +import java.util.ArrayList; import java.util.Objects; /** @@ -121,11 +123,37 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> { } builder.append(", metered=").append(mMetered); builder.append(", defaultNetwork=").append(mDefaultNetwork); - // TODO(180557699): Print a human readable string for OEM managed state. - builder.append(", oemManaged=").append(mOemManaged); + builder.append(", oemManaged=").append(getOemManagedNames(mOemManaged)); return builder.append("}").toString(); } + /** + * Get the human readable representation of a bitfield representing the OEM managed state of a + * network. + */ + static String getOemManagedNames(int oemManaged) { + if (oemManaged == OEM_NONE) { + return "OEM_NONE"; + } + final int[] bitPositions = NetworkCapabilitiesUtils.unpackBits(oemManaged); + final ArrayList<String> oemManagedNames = new ArrayList<String>(); + for (int position : bitPositions) { + oemManagedNames.add(nameOfOemManaged(1 << position)); + } + return String.join(",", oemManagedNames); + } + + private static String nameOfOemManaged(int oemManagedBit) { + switch (oemManagedBit) { + case OEM_PAID: + return "OEM_PAID"; + case OEM_PRIVATE: + return "OEM_PRIVATE"; + default: + return "Invalid(" + oemManagedBit + ")"; + } + } + public void dumpDebug(ProtoOutputStream proto, long tag) { final long start = proto.start(tag); diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index d3c89574944f..352f2e99aa5e 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -274,11 +274,14 @@ public class NetworkTemplate implements Parcelable { } /** - * Template to match all carrier networks with the given IMSI. + * Template to match all metered carrier networks with the given IMSI. */ - public static NetworkTemplate buildTemplateCarrier(@NonNull String subscriberId) { + public static NetworkTemplate buildTemplateCarrierMetered(@NonNull String subscriberId) { Objects.requireNonNull(subscriberId); - return new NetworkTemplate(MATCH_CARRIER, subscriberId, null); + return new NetworkTemplate(MATCH_CARRIER, subscriberId, + new String[] { subscriberId }, null /* networkId */, METERED_YES, ROAMING_ALL, + DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL, + SUBSCRIBER_ID_MATCH_RULE_EXACT); } private final int mMatchRule; @@ -424,7 +427,7 @@ public class NetworkTemplate implements Parcelable { builder.append(", subType=").append(mSubType); } if (mOemManaged != OEM_MANAGED_ALL) { - builder.append(", oemManaged=").append(mOemManaged); + builder.append(", oemManaged=").append(getOemManagedNames(mOemManaged)); } builder.append(", subscriberIdMatchRule=") .append(subscriberIdMatchRuleToString(mSubscriberIdMatchRule)); @@ -774,6 +777,19 @@ public class NetworkTemplate implements Parcelable { } } + private static String getOemManagedNames(int oemManaged) { + switch (oemManaged) { + case OEM_MANAGED_ALL: + return "OEM_MANAGED_ALL"; + case OEM_MANAGED_NO: + return "OEM_MANAGED_NO"; + case OEM_MANAGED_YES: + return "OEM_MANAGED_YES"; + default: + return NetworkIdentity.getOemManagedNames(oemManaged); + } + } + /** * Examine the given template and normalize if it refers to a "merged" * mobile subscriber. We pick the "lowest" merged subscriber as the primary diff --git a/core/java/android/net/UnderlyingNetworkInfo.java b/core/java/android/net/UnderlyingNetworkInfo.java index 459fdacef816..33f9375c03bf 100644 --- a/core/java/android/net/UnderlyingNetworkInfo.java +++ b/core/java/android/net/UnderlyingNetworkInfo.java @@ -71,13 +71,13 @@ public final class UnderlyingNetworkInfo implements Parcelable { /** Get the interface name of this network. */ @NonNull - public String getIface() { + public String getInterface() { return mIface; } /** Get the names of the interfaces underlying this network. */ @NonNull - public List<String> getUnderlyingIfaces() { + public List<String> getUnderlyingInterfaces() { return mUnderlyingIfaces; } @@ -124,8 +124,8 @@ public final class UnderlyingNetworkInfo implements Parcelable { if (!(o instanceof UnderlyingNetworkInfo)) return false; final UnderlyingNetworkInfo that = (UnderlyingNetworkInfo) o; return mOwnerUid == that.getOwnerUid() - && Objects.equals(mIface, that.getIface()) - && Objects.equals(mUnderlyingIfaces, that.getUnderlyingIfaces()); + && Objects.equals(mIface, that.getInterface()) + && Objects.equals(mUnderlyingIfaces, that.getUnderlyingInterfaces()); } @Override diff --git a/core/java/android/net/vcn/OWNERS b/core/java/android/net/vcn/OWNERS index 33b9f0f75f81..2441e772468c 100644 --- a/core/java/android/net/vcn/OWNERS +++ b/core/java/android/net/vcn/OWNERS @@ -3,5 +3,5 @@ set noparent benedictwong@google.com ckesting@google.com evitayan@google.com +junyin@google.com nharold@google.com -jchalard@google.com
\ No newline at end of file diff --git a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java index 2df3e6c7ecd6..d59ad6f88864 100644 --- a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java +++ b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java @@ -161,9 +161,6 @@ public final class VcnGatewayConnectionConfig { private static final String EXPOSED_CAPABILITIES_KEY = "mExposedCapabilities"; @NonNull private final SortedSet<Integer> mExposedCapabilities; - private static final String UNDERLYING_CAPABILITIES_KEY = "mUnderlyingCapabilities"; - @NonNull private final SortedSet<Integer> mUnderlyingCapabilities; - private static final String MAX_MTU_KEY = "mMaxMtu"; private final int mMaxMtu; @@ -175,13 +172,11 @@ public final class VcnGatewayConnectionConfig { @NonNull String gatewayConnectionName, @NonNull IkeTunnelConnectionParams tunnelConnectionParams, @NonNull Set<Integer> exposedCapabilities, - @NonNull Set<Integer> underlyingCapabilities, @NonNull long[] retryIntervalsMs, @IntRange(from = MIN_MTU_V6) int maxMtu) { mGatewayConnectionName = gatewayConnectionName; mTunnelConnectionParams = tunnelConnectionParams; mExposedCapabilities = new TreeSet(exposedCapabilities); - mUnderlyingCapabilities = new TreeSet(underlyingCapabilities); mRetryIntervalsMs = retryIntervalsMs; mMaxMtu = maxMtu; @@ -198,16 +193,12 @@ public final class VcnGatewayConnectionConfig { final PersistableBundle exposedCapsBundle = in.getPersistableBundle(EXPOSED_CAPABILITIES_KEY); - final PersistableBundle underlyingCapsBundle = - in.getPersistableBundle(UNDERLYING_CAPABILITIES_KEY); mGatewayConnectionName = in.getString(GATEWAY_CONNECTION_NAME_KEY); mTunnelConnectionParams = TunnelConnectionParamsUtils.fromPersistableBundle(tunnelConnectionParamsBundle); mExposedCapabilities = new TreeSet<>(PersistableBundleUtils.toList( exposedCapsBundle, PersistableBundleUtils.INTEGER_DESERIALIZER)); - mUnderlyingCapabilities = new TreeSet<>(PersistableBundleUtils.toList( - underlyingCapsBundle, PersistableBundleUtils.INTEGER_DESERIALIZER)); mRetryIntervalsMs = in.getLongArray(RETRY_INTERVAL_MS_KEY); mMaxMtu = in.getInt(MAX_MTU_KEY); @@ -307,36 +298,6 @@ public final class VcnGatewayConnectionConfig { } /** - * Returns all capabilities required of underlying networks. - * - * <p>The returned integer-value capabilities will be sorted in ascending numerical order. - * - * @see Builder#addRequiredUnderlyingCapability(int) - * @see Builder#removeRequiredUnderlyingCapability(int) - * @hide - */ - // TODO(b/182219992): Remove, and add when per-transport capabilities are supported - @NonNull - public int[] getRequiredUnderlyingCapabilities() { - // Sorted set guarantees ordering - return ArrayUtils.convertToIntArray(new ArrayList<>(mUnderlyingCapabilities)); - } - - /** - * Returns all capabilities required of underlying networks. - * - * <p>Left to prevent the need to make major changes while changes are actively in flight. - * - * @deprecated use getRequiredUnderlyingCapabilities() instead - * @hide - */ - @Deprecated - @NonNull - public Set<Integer> getAllUnderlyingCapabilities() { - return Collections.unmodifiableSet(mUnderlyingCapabilities); - } - - /** * Retrieves the configured retry intervals. * * @see Builder#setRetryIntervalsMillis(long[]) @@ -372,15 +333,10 @@ public final class VcnGatewayConnectionConfig { PersistableBundleUtils.fromList( new ArrayList<>(mExposedCapabilities), PersistableBundleUtils.INTEGER_SERIALIZER); - final PersistableBundle underlyingCapsBundle = - PersistableBundleUtils.fromList( - new ArrayList<>(mUnderlyingCapabilities), - PersistableBundleUtils.INTEGER_SERIALIZER); result.putString(GATEWAY_CONNECTION_NAME_KEY, mGatewayConnectionName); result.putPersistableBundle(TUNNEL_CONNECTION_PARAMS_KEY, tunnelConnectionParamsBundle); result.putPersistableBundle(EXPOSED_CAPABILITIES_KEY, exposedCapsBundle); - result.putPersistableBundle(UNDERLYING_CAPABILITIES_KEY, underlyingCapsBundle); result.putLongArray(RETRY_INTERVAL_MS_KEY, mRetryIntervalsMs); result.putInt(MAX_MTU_KEY, mMaxMtu); @@ -392,7 +348,6 @@ public final class VcnGatewayConnectionConfig { return Objects.hash( mGatewayConnectionName, mExposedCapabilities, - mUnderlyingCapabilities, Arrays.hashCode(mRetryIntervalsMs), mMaxMtu); } @@ -406,7 +361,6 @@ public final class VcnGatewayConnectionConfig { final VcnGatewayConnectionConfig rhs = (VcnGatewayConnectionConfig) other; return mGatewayConnectionName.equals(rhs.mGatewayConnectionName) && mExposedCapabilities.equals(rhs.mExposedCapabilities) - && mUnderlyingCapabilities.equals(rhs.mUnderlyingCapabilities) && Arrays.equals(mRetryIntervalsMs, rhs.mRetryIntervalsMs) && mMaxMtu == rhs.mMaxMtu; } @@ -418,7 +372,6 @@ public final class VcnGatewayConnectionConfig { @NonNull private final String mGatewayConnectionName; @NonNull private final IkeTunnelConnectionParams mTunnelConnectionParams; @NonNull private final Set<Integer> mExposedCapabilities = new ArraySet(); - @NonNull private final Set<Integer> mUnderlyingCapabilities = new ArraySet(); @NonNull private long[] mRetryIntervalsMs = DEFAULT_RETRY_INTERVALS_MS; private int mMaxMtu = DEFAULT_MAX_MTU; @@ -490,51 +443,6 @@ public final class VcnGatewayConnectionConfig { } /** - * Require a capability for Networks underlying this VCN Gateway Connection. - * - * @param underlyingCapability the capability that a network MUST have in order to be an - * underlying network for this VCN Gateway Connection. - * @return this {@link Builder} instance, for chaining - * @see VcnGatewayConnectionConfig for a list of capabilities may be required of underlying - * networks - * @hide - */ - // TODO(b/182219992): Remove, and add when per-transport capabilities are supported - @NonNull - public Builder addRequiredUnderlyingCapability( - @VcnSupportedCapability int underlyingCapability) { - checkValidCapability(underlyingCapability); - - mUnderlyingCapabilities.add(underlyingCapability); - return this; - } - - /** - * Remove a requirement of a capability for Networks underlying this VCN Gateway Connection. - * - * <p>Calling this method will allow Networks that do NOT have this capability to be - * selected as an underlying network for this VCN Gateway Connection. However, underlying - * networks MAY still have the removed capability. - * - * @param underlyingCapability the capability that a network DOES NOT need to have in order - * to be an underlying network for this VCN Gateway Connection. - * @return this {@link Builder} instance, for chaining - * @see VcnGatewayConnectionConfig for a list of capabilities may be required of underlying - * networks - * @hide - */ - // TODO(b/182219992): Remove, and add when per-transport capabilities are supported - @NonNull - @SuppressLint("BuilderSetStyle") // For consistency with NetCaps.Builder add/removeCap - public Builder removeRequiredUnderlyingCapability( - @VcnSupportedCapability int underlyingCapability) { - checkValidCapability(underlyingCapability); - - mUnderlyingCapabilities.remove(underlyingCapability); - return this; - } - - /** * Set the retry interval between VCN establishment attempts upon successive failures. * * <p>The last retry interval will be repeated until safe mode is entered, or a connection @@ -598,7 +506,6 @@ public final class VcnGatewayConnectionConfig { mGatewayConnectionName, mTunnelConnectionParams, mExposedCapabilities, - mUnderlyingCapabilities, mRetryIntervalsMs, mMaxMtu); } diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java index 9d1c1ff898e7..390c3b9453c2 100644 --- a/core/java/android/net/vcn/VcnManager.java +++ b/core/java/android/net/vcn/VcnManager.java @@ -74,6 +74,36 @@ import java.util.concurrent.Executor; public class VcnManager { @NonNull private static final String TAG = VcnManager.class.getSimpleName(); + /** + * Key for WiFi entry RSSI thresholds + * + * <p>The VCN will only migrate to a Carrier WiFi network that has a signal strength greater + * than, or equal to this threshold. + * + * <p>WARNING: The VCN does not listen for changes to this key made after VCN startup. + * + * @hide + */ + @NonNull + public static final String VCN_NETWORK_SELECTION_WIFI_ENTRY_RSSI_THRESHOLD_KEY = + "vcn_network_selection_wifi_entry_rssi_threshold"; + + /** + * Key for WiFi entry RSSI thresholds + * + * <p>If the VCN's selected Carrier WiFi network has a signal strength less than this threshold, + * the VCN will attempt to migrate away from the Carrier WiFi network. + * + * <p>WARNING: The VCN does not listen for changes to this key made after VCN startup. + * + * @hide + */ + @NonNull + public static final String VCN_NETWORK_SELECTION_WIFI_EXIT_RSSI_THRESHOLD_KEY = + "vcn_network_selection_wifi_exit_rssi_threshold"; + + // TODO: Add separate signal strength thresholds for 2.4 GHz and 5GHz + private static final Map< VcnNetworkPolicyChangeListener, VcnUnderlyingNetworkPolicyListenerBinder> REGISTERED_POLICY_LISTENERS = new ConcurrentHashMap<>(); diff --git a/core/java/android/net/vcn/VcnTransportInfo.java b/core/java/android/net/vcn/VcnTransportInfo.java index 0e9ccf144c2e..1f1818420b56 100644 --- a/core/java/android/net/vcn/VcnTransportInfo.java +++ b/core/java/android/net/vcn/VcnTransportInfo.java @@ -16,23 +16,17 @@ package android.net.vcn; -import static android.net.NetworkCapabilities.REDACT_ALL; -import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS; +import static android.net.NetworkCapabilities.REDACT_NONE; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; -import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE; - import android.annotation.NonNull; import android.annotation.Nullable; -import android.net.NetworkCapabilities; import android.net.TransportInfo; import android.net.wifi.WifiInfo; import android.os.Parcel; import android.os.Parcelable; import android.telephony.SubscriptionManager; -import com.android.internal.annotations.VisibleForTesting; - import java.util.Objects; /** @@ -55,32 +49,17 @@ public class VcnTransportInfo implements TransportInfo, Parcelable { @Nullable private final WifiInfo mWifiInfo; private final int mSubId; - /** - * The redaction scheme to use when parcelling. - * - * <p>The TransportInfo/NetworkCapabilities redaction mechanisms rely on redaction being - * performed at parcelling time. This means that the redaction scheme must be stored for later - * use. - * - * <p>Since the redaction scheme itself is not parcelled, this field is listed as a transient. - * - * <p>Defaults to REDACT_ALL when constructed using public constructors, or creating from - * parcels. - */ - private final transient long mRedactions; - public VcnTransportInfo(@NonNull WifiInfo wifiInfo) { - this(wifiInfo, INVALID_SUBSCRIPTION_ID, REDACT_ALL); + this(wifiInfo, INVALID_SUBSCRIPTION_ID); } public VcnTransportInfo(int subId) { - this(null /* wifiInfo */, subId, REDACT_ALL); + this(null /* wifiInfo */, subId); } - private VcnTransportInfo(@Nullable WifiInfo wifiInfo, int subId, long redactions) { + private VcnTransportInfo(@Nullable WifiInfo wifiInfo, int subId) { mWifiInfo = wifiInfo; mSubId = subId; - mRedactions = redactions; } /** @@ -102,25 +81,14 @@ public class VcnTransportInfo implements TransportInfo, Parcelable { * SubscriptionManager#INVALID_SUBSCRIPTION_ID}. * * @return the Subscription ID if a cellular underlying Network is present, else {@link - * android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID}. + * android.telephony.SubscriptionManager#INVALID_SUBSCRIPTION_ID}. */ public int getSubId() { return mSubId; } - /** - * Gets the redaction scheme - * - * @hide - */ - @VisibleForTesting(visibility = PRIVATE) - public long getRedaction() { - return mRedactions; - } - @Override public int hashCode() { - // mRedactions not hashed, as it is a transient, for control of parcelling return Objects.hash(mWifiInfo, mSubId); } @@ -128,8 +96,6 @@ public class VcnTransportInfo implements TransportInfo, Parcelable { public boolean equals(Object o) { if (!(o instanceof VcnTransportInfo)) return false; final VcnTransportInfo that = (VcnTransportInfo) o; - - // mRedactions not compared, as it is a transient, for control of parcelling return Objects.equals(mWifiInfo, that.mWifiInfo) && mSubId == that.mSubId; } @@ -143,31 +109,19 @@ public class VcnTransportInfo implements TransportInfo, Parcelable { @NonNull public TransportInfo makeCopy(long redactions) { return new VcnTransportInfo( - mWifiInfo == null ? null : mWifiInfo.makeCopy(redactions), mSubId, redactions); + (mWifiInfo == null) ? null : mWifiInfo.makeCopy(redactions), mSubId); } @Override public long getApplicableRedactions() { - long redactions = REDACT_FOR_NETWORK_SETTINGS; - - // Add additional wifi redactions if necessary - if (mWifiInfo != null) { - redactions |= mWifiInfo.getApplicableRedactions(); - } - - return redactions; - } - - private boolean shouldParcelNetworkSettingsFields() { - return (mRedactions & NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS) == 0; + return (mWifiInfo == null) ? REDACT_NONE : mWifiInfo.getApplicableRedactions(); } /** {@inheritDoc} */ @Override public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeInt(shouldParcelNetworkSettingsFields() ? mSubId : INVALID_SUBSCRIPTION_ID); - dest.writeParcelable( - shouldParcelNetworkSettingsFields() ? (Parcelable) mWifiInfo : null, flags); + dest.writeInt(mSubId); + dest.writeParcelable(mWifiInfo, flags); } @Override @@ -181,17 +135,7 @@ public class VcnTransportInfo implements TransportInfo, Parcelable { public VcnTransportInfo createFromParcel(Parcel in) { final int subId = in.readInt(); final WifiInfo wifiInfo = in.readParcelable(null); - - // If all fields are their null values, return null TransportInfo to avoid - // leaking information about this being a VCN Network (instead of macro - // cellular, etc) - if (wifiInfo == null && subId == INVALID_SUBSCRIPTION_ID) { - return null; - } - - // Prevent further forwarding by redacting everything in future parcels from - // this VcnTransportInfo - return new VcnTransportInfo(wifiInfo, subId, REDACT_ALL); + return new VcnTransportInfo(wifiInfo, subId); } public VcnTransportInfo[] newArray(int size) { diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS index d9665953dceb..cd02d297270a 100644 --- a/core/java/android/os/OWNERS +++ b/core/java/android/os/OWNERS @@ -63,3 +63,6 @@ per-file *Zygote* = file:/ZYGOTE_OWNERS # RecoverySystem per-file *Recovery* = file:/services/core/java/com/android/server/recoverysystem/OWNERS + +# Bugreporting +per-file Bugreport* = file:/platform/frameworks/native:/cmds/dumpstate/OWNERS diff --git a/core/java/android/os/PersistableBundle.java b/core/java/android/os/PersistableBundle.java index 7a837e167fb0..339371b5047c 100644 --- a/core/java/android/os/PersistableBundle.java +++ b/core/java/android/os/PersistableBundle.java @@ -302,7 +302,7 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa new MyReadMapCallback())); } } - return EMPTY; + return new PersistableBundle(); // An empty mutable PersistableBundle } @Override diff --git a/core/java/android/os/incremental/OWNERS b/core/java/android/os/incremental/OWNERS index 3795493b861f..47eee6406206 100644 --- a/core/java/android/os/incremental/OWNERS +++ b/core/java/android/os/incremental/OWNERS @@ -3,3 +3,4 @@ alexbuy@google.com schfan@google.com toddke@google.com zyy@google.com +patb@google.com diff --git a/core/java/com/android/internal/app/procstats/OWNERS b/core/java/com/android/internal/app/procstats/OWNERS new file mode 100644 index 000000000000..72c0a9e6e90c --- /dev/null +++ b/core/java/com/android/internal/app/procstats/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/am/OWNERS diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index c34b9f09ecaa..dd2940f8c110 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -40,6 +40,7 @@ import android.net.Uri; import android.net.wifi.WifiManager; import android.os.BatteryManager; import android.os.BatteryStats; +import android.os.Binder; import android.os.Build; import android.os.Handler; import android.os.IBatteryPropertiesRegistrar; @@ -71,6 +72,7 @@ import android.telephony.SignalStrength; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.ArrayMap; +import android.util.ArraySet; import android.util.AtomicFile; import android.util.IntArray; import android.util.KeyValueListParser; @@ -122,6 +124,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collection; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -6126,6 +6129,18 @@ public class BatteryStatsImpl extends BatteryStats { } } + /** + * Records timing data related to an incoming Binder call in order to attribute + * the power consumption to the calling app. + */ + public void noteBinderCallStats(int workSourceUid, long incrementalCallCount, + Collection<BinderCallsStats.CallStat> callStats) { + synchronized (this) { + getUidStatsLocked(workSourceUid).noteBinderCallStatsLocked(incrementalCallCount, + callStats); + } + } + public String[] getWifiIfaces() { synchronized (mWifiNetworkLock) { return mWifiIfaces; @@ -6569,6 +6584,65 @@ public class BatteryStatsImpl extends BatteryStats { } /** + * Accumulates stats for a specific binder transaction. + */ + @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) + protected static class BinderCallStats { + static final Comparator<BinderCallStats> COMPARATOR = + Comparator.comparing(BinderCallStats::getClassName) + .thenComparing(BinderCallStats::getMethodName); + + public Class<? extends Binder> binderClass; + public int transactionCode; + public String methodName; + + public long callCount; + public long recordedCallCount; + public long recordedCpuTimeMicros; + + + @Override + public int hashCode() { + return binderClass.hashCode() * 31 + transactionCode; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof BinderCallStats)) { + return false; + } + BinderCallStats bcsk = (BinderCallStats) obj; + return binderClass.equals(bcsk.binderClass) && transactionCode == bcsk.transactionCode; + } + + public String getClassName() { + return binderClass.getName(); + } + + public String getMethodName() { + return methodName; + } + + @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) + public void ensureMethodName(BinderTransactionNameResolver resolver) { + if (methodName == null) { + methodName = resolver.getMethodName(binderClass, transactionCode); + } + } + + @Override + public String toString() { + return "BinderCallStats{" + + binderClass + + " transaction=" + transactionCode + + " callCount=" + callCount + + " recordedCallCount=" + recordedCallCount + + " recorderCpuTimeMicros=" + recordedCpuTimeMicros + + "}"; + } + } + + /** * The statistics associated with a particular uid. */ public static class Uid extends BatteryStats.Uid { @@ -6741,6 +6815,16 @@ public class BatteryStatsImpl extends BatteryStats { */ final SparseArray<Pid> mPids = new SparseArray<>(); + /** + * Grand total of system server binder calls made by this uid. + */ + private long mBinderCallCount; + + /** + * Detailed information about system server binder calls made by this uid. + */ + private final ArraySet<BinderCallStats> mBinderCallStats = new ArraySet<>(); + public Uid(BatteryStatsImpl bsi, int uid) { mBsi = bsi; mUid = uid; @@ -6849,6 +6933,14 @@ public class BatteryStatsImpl extends BatteryStats { return nullIfAllZeros(mProcStateScreenOffTimeMs[procState], which); } + public long getBinderCallCount() { + return mBinderCallCount; + } + + public ArraySet<BinderCallStats> getBinderCallStats() { + return mBinderCallStats; + } + public void addIsolatedUid(int isolatedUid) { if (mChildUids == null) { mChildUids = new IntArray(); @@ -7937,6 +8029,9 @@ public class BatteryStatsImpl extends BatteryStats { } mPackageStats.clear(); + mBinderCallCount = 0; + mBinderCallStats.clear(); + mLastStepUserTime = mLastStepSystemTime = 0; mCurStepUserTime = mCurStepSystemTime = 0; @@ -8692,6 +8787,40 @@ public class BatteryStatsImpl extends BatteryStats { } } + // Reusable object used as a key to lookup values in mBinderCallStats + private static BinderCallStats sTempBinderCallStats = new BinderCallStats(); + + /** + * Notes incoming binder call stats associated with this work source UID. + */ + public void noteBinderCallStatsLocked(long incrementalCallCount, + Collection<BinderCallsStats.CallStat> callStats) { + if (DEBUG) { + Slog.d(TAG, "noteBinderCalls() workSourceUid = [" + mUid + "], " + + " incrementalCallCount: " + incrementalCallCount + " callStats = [" + + new ArrayList<>(callStats) + "]"); + } + mBinderCallCount += incrementalCallCount; + for (BinderCallsStats.CallStat stat : callStats) { + BinderCallStats bcs; + sTempBinderCallStats.binderClass = stat.binderClass; + sTempBinderCallStats.transactionCode = stat.transactionCode; + int index = mBinderCallStats.indexOf(sTempBinderCallStats); + if (index >= 0) { + bcs = mBinderCallStats.valueAt(index); + } else { + bcs = new BinderCallStats(); + bcs.binderClass = stat.binderClass; + bcs.transactionCode = stat.transactionCode; + mBinderCallStats.add(bcs); + } + + bcs.callCount += stat.incrementalCallCount; + bcs.recordedCallCount = stat.recordedCallCount; + bcs.recordedCpuTimeMicros = stat.cpuTimeMicros; + } + } + /** * The statistics associated with a particular wake lock. */ @@ -13213,6 +13342,45 @@ public class BatteryStatsImpl extends BatteryStats { pw.print(uid.getUserCpuTimeUs(STATS_SINCE_CHARGED) / 1000); pw.print(" "); pw.println(uid.getSystemCpuTimeUs(STATS_SINCE_CHARGED) / 1000); } + pw.println("Per UID system service calls:"); + BinderTransactionNameResolver nameResolver = new BinderTransactionNameResolver(); + for (int i = 0; i < size; i++) { + int u = mUidStats.keyAt(i); + Uid uid = mUidStats.get(u); + long binderCallCount = uid.getBinderCallCount(); + if (binderCallCount != 0) { + pw.print(" "); + pw.print(u); + pw.print(" system service calls: "); + pw.print(binderCallCount); + ArraySet<BinderCallStats> binderCallStats = uid.getBinderCallStats(); + if (!binderCallStats.isEmpty()) { + pw.println(", including"); + BinderCallStats[] bcss = new BinderCallStats[binderCallStats.size()]; + binderCallStats.toArray(bcss); + for (BinderCallStats bcs : bcss) { + bcs.ensureMethodName(nameResolver); + } + Arrays.sort(bcss, BinderCallStats.COMPARATOR); + for (BinderCallStats callStats : bcss) { + pw.print(" "); + pw.print(callStats.getClassName()); + pw.print('#'); + pw.print(callStats.getMethodName()); + pw.print(" calls: "); + pw.print(callStats.callCount); + if (callStats.recordedCallCount != 0) { + pw.print(" time: "); + pw.print(callStats.callCount * callStats.recordedCpuTimeMicros + / callStats.recordedCallCount / 1000); + } + pw.println(); + } + } else { + pw.println(); + } + } + } pw.println("Per UID CPU active time in ms:"); for (int i = 0; i < size; i++) { int u = mUidStats.keyAt(i); diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java index dbba469dda1a..a3dbd30d089e 100644 --- a/core/java/com/android/internal/os/BinderCallsStats.java +++ b/core/java/com/android/internal/os/BinderCallsStats.java @@ -19,10 +19,14 @@ package com.android.internal.os; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Binder; +import android.os.Handler; +import android.os.Looper; import android.os.Process; import android.os.SystemClock; +import android.os.UserHandle; import android.text.format.DateFormat; import android.util.ArrayMap; +import android.util.ArraySet; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; @@ -32,13 +36,10 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.BinderInternal.CallSession; import java.io.PrintWriter; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.List; -import java.util.Map; import java.util.Queue; import java.util.Random; import java.util.concurrent.ConcurrentLinkedQueue; @@ -95,7 +96,38 @@ public class BinderCallsStats implements BinderInternal.Observer { private CachedDeviceState.Readonly mDeviceState; private CachedDeviceState.TimeInStateStopwatch mBatteryStopwatch; + private static final int CALL_STATS_OBSERVER_DEBOUNCE_MILLIS = 5000; private BinderLatencyObserver mLatencyObserver; + private BinderInternal.CallStatsObserver mCallStatsObserver; + private ArraySet<Integer> mSendUidsToObserver = new ArraySet<>(32); + private final Handler mCallStatsObserverHandler; + private Runnable mCallStatsObserverRunnable = new Runnable() { + @Override + public void run() { + if (mCallStatsObserver == null) { + return; + } + + noteCallsStatsDelayed(); + + synchronized (mLock) { + int size = mSendUidsToObserver.size(); + for (int i = 0; i < size; i++) { + UidEntry uidEntry = mUidEntries.get(mSendUidsToObserver.valueAt(i)); + if (uidEntry != null) { + ArrayMap<CallStatKey, CallStat> callStats = uidEntry.mCallStats; + mCallStatsObserver.noteCallStats(uidEntry.workSourceUid, + uidEntry.incrementalCallCount, callStats.values()); + uidEntry.incrementalCallCount = 0; + for (int j = callStats.size() - 1; j >= 0; j--) { + callStats.valueAt(j).incrementalCallCount = 0; + } + } + } + mSendUidsToObserver.clear(); + } + } + }; /** Injector for {@link BinderCallsStats}. */ public static class Injector { @@ -103,6 +135,10 @@ public class BinderCallsStats implements BinderInternal.Observer { return new Random(); } + public Handler getHandler() { + return new Handler(Looper.getMainLooper()); + } + public BinderLatencyObserver getLatencyObserver() { return new BinderLatencyObserver(new BinderLatencyObserver.Injector()); } @@ -110,6 +146,7 @@ public class BinderCallsStats implements BinderInternal.Observer { public BinderCallsStats(Injector injector) { this.mRandom = injector.getRandomGenerator(); + this.mCallStatsObserverHandler = injector.getHandler(); this.mLatencyObserver = injector.getLatencyObserver(); } @@ -121,6 +158,24 @@ public class BinderCallsStats implements BinderInternal.Observer { mBatteryStopwatch = deviceState.createTimeOnBatteryStopwatch(); } + /** + * Registers an observer for call stats, which is invoked periodically with accumulated + * binder call stats. + */ + public void setCallStatsObserver( + BinderInternal.CallStatsObserver callStatsObserver) { + mCallStatsObserver = callStatsObserver; + noteCallsStatsDelayed(); + } + + private void noteCallsStatsDelayed() { + mCallStatsObserverHandler.removeCallbacks(mCallStatsObserverRunnable); + if (mCallStatsObserver != null) { + mCallStatsObserverHandler.postDelayed(mCallStatsObserverRunnable, + CALL_STATS_OBSERVER_DEBOUNCE_MILLIS); + } + } + @Override @Nullable public CallSession callStarted(Binder binder, int code, int workSourceUid) { @@ -195,6 +250,7 @@ public class BinderCallsStats implements BinderInternal.Observer { final UidEntry uidEntry = getUidEntry(workSourceUid); uidEntry.callCount++; + uidEntry.incrementalCallCount++; if (recordCall) { uidEntry.cpuTimeMicros += duration; @@ -210,6 +266,7 @@ public class BinderCallsStats implements BinderInternal.Observer { } callStat.callCount++; + callStat.incrementalCallCount++; callStat.recordedCallCount++; callStat.cpuTimeMicros += duration; callStat.maxCpuTimeMicros = Math.max(callStat.maxCpuTimeMicros, duration); @@ -231,8 +288,12 @@ public class BinderCallsStats implements BinderInternal.Observer { screenInteractive); if (callStat != null) { callStat.callCount++; + callStat.incrementalCallCount++; } } + if (mCallStatsObserver != null && !UserHandle.isCore(workSourceUid)) { + mSendUidsToObserver.add(workSourceUid); + } } } @@ -266,29 +327,6 @@ public class BinderCallsStats implements BinderInternal.Observer { } } - @Nullable - private Method getDefaultTransactionNameMethod(Class<? extends Binder> binder) { - try { - return binder.getMethod("getDefaultTransactionName", int.class); - } catch (NoSuchMethodException e) { - // The method might not be present for stubs not generated with AIDL. - return null; - } - } - - @Nullable - private String resolveTransactionCode(Method getDefaultTransactionName, int transactionCode) { - if (getDefaultTransactionName == null) { - return null; - } - - try { - return (String) getDefaultTransactionName.invoke(null, transactionCode); - } catch (IllegalAccessException | InvocationTargetException | ClassCastException e) { - throw new RuntimeException(e); - } - } - /** * This method is expensive to call. */ @@ -327,31 +365,23 @@ public class BinderCallsStats implements BinderInternal.Observer { // Resolve codes outside of the lock since it can be slow. ExportedCallStat previous = null; - // Cache the previous method/transaction code. - Method getDefaultTransactionName = null; String previousMethodName = null; resultCallStats.sort(BinderCallsStats::compareByBinderClassAndCode); + BinderTransactionNameResolver resolver = new BinderTransactionNameResolver(); for (ExportedCallStat exported : resultCallStats) { final boolean isClassDifferent = previous == null || !previous.className.equals(exported.className); - if (isClassDifferent) { - getDefaultTransactionName = getDefaultTransactionNameMethod(exported.binderClass); - } - final boolean isCodeDifferent = previous == null || previous.transactionCode != exported.transactionCode; final String methodName; if (isClassDifferent || isCodeDifferent) { - String resolvedCode = resolveTransactionCode( - getDefaultTransactionName, exported.transactionCode); - methodName = resolvedCode == null - ? String.valueOf(exported.transactionCode) - : resolvedCode; + methodName = resolver.getMethodName(exported.binderClass, exported.transactionCode); } else { methodName = previousMethodName; } previousMethodName = methodName; exported.methodName = methodName; + previous = exported; } // Debug entries added to help validate the data. @@ -649,14 +679,32 @@ public class BinderCallsStats implements BinderInternal.Observer { public long maxRequestSizeBytes; public long maxReplySizeBytes; public long exceptionCount; + // Call count since reset + public long incrementalCallCount; - CallStat(int callingUid, Class<? extends Binder> binderClass, int transactionCode, + public CallStat(int callingUid, Class<? extends Binder> binderClass, int transactionCode, boolean screenInteractive) { this.callingUid = callingUid; this.binderClass = binderClass; this.transactionCode = transactionCode; this.screenInteractive = screenInteractive; } + + @Override + public String toString() { + // This is expensive, but CallStat.toString() is only used for debugging. + String methodName = new BinderTransactionNameResolver().getMethodName(binderClass, + transactionCode); + return "CallStat{" + + "callingUid=" + callingUid + + ", transaction=" + binderClass.getSimpleName() + '.' + methodName + + ", callCount=" + callCount + + ", incrementalCallCount=" + incrementalCallCount + + ", recordedCallCount=" + recordedCallCount + + ", cpuTimeMicros=" + cpuTimeMicros + + ", latencyMicros=" + latencyMicros + + '}'; + } } /** Key used to store CallStat object in a Map. */ @@ -704,13 +752,15 @@ public class BinderCallsStats implements BinderInternal.Observer { // Approximate total CPU usage can be computed by // cpuTimeMicros * callCount / recordedCallCount public long cpuTimeMicros; + // Call count that gets reset after delivery to BatteryStats + public long incrementalCallCount; UidEntry(int uid) { this.workSourceUid = uid; } // Aggregate time spent per each call name: call_desc -> cpu_time_micros - private Map<CallStatKey, CallStat> mCallStats = new ArrayMap<>(); + private ArrayMap<CallStatKey, CallStat> mCallStats = new ArrayMap<>(); private CallStatKey mTempKey = new CallStatKey(); @Nullable diff --git a/core/java/com/android/internal/os/BinderInternal.java b/core/java/com/android/internal/os/BinderInternal.java index 95c36ca8429e..feb5aab94adc 100644 --- a/core/java/com/android/internal/os/BinderInternal.java +++ b/core/java/com/android/internal/os/BinderInternal.java @@ -31,6 +31,7 @@ import dalvik.system.VMRuntime; import java.lang.ref.WeakReference; import java.util.ArrayList; +import java.util.Collection; /** * Private and debugging Binder APIs. @@ -134,6 +135,17 @@ public class BinderInternal { } /** + * Allows to track observe incoming binder call stats. + */ + public interface CallStatsObserver { + /** + * Notes incoming binder call stats associated with this work source UID. + */ + void noteCallStats(int workSourceUid, long incrementalCallCount, + Collection<BinderCallsStats.CallStat> callStats); + } + + /** * Add the calling thread to the IPC thread pool. This function does * not return until the current process is exiting. */ diff --git a/core/java/com/android/internal/os/BinderLatencyBuckets.java b/core/java/com/android/internal/os/BinderLatencyBuckets.java index bdee4ca8a6b8..d7d2d6a8f9dd 100644 --- a/core/java/com/android/internal/os/BinderLatencyBuckets.java +++ b/core/java/com/android/internal/os/BinderLatencyBuckets.java @@ -20,8 +20,7 @@ import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; -import java.util.ArrayList; -import java.util.Collections; +import java.util.Arrays; /** * Generates the bucket thresholds (with a custom logarithmic scale) for a histogram to store @@ -29,7 +28,7 @@ import java.util.Collections; */ public class BinderLatencyBuckets { private static final String TAG = "BinderLatencyBuckets"; - private ArrayList<Integer> mBuckets; + private final int[] mBuckets; /** * @param bucketCount the number of buckets the histogram should have @@ -37,12 +36,11 @@ public class BinderLatencyBuckets { * @param scaleFactor the rate in which each consecutive bucket increases (before rounding) */ public BinderLatencyBuckets(int bucketCount, int firstBucketSize, float scaleFactor) { - mBuckets = new ArrayList<>(bucketCount - 1); - mBuckets.add(firstBucketSize); + int[] buffer = new int[bucketCount - 1]; + buffer[0] = firstBucketSize; // Last value and the target are disjoint as we never want to create buckets smaller than 1. double lastTarget = firstBucketSize; - int lastValue = firstBucketSize; // First bucket is already created and the last bucket is anything greater than the final // bucket in the list, so create 'bucketCount' - 2 buckets. @@ -50,29 +48,29 @@ public class BinderLatencyBuckets { // Increase the target bucket limit value by the scale factor. double nextTarget = lastTarget * scaleFactor; - if (nextTarget > Integer.MAX_VALUE || lastValue == Integer.MAX_VALUE) { + if (nextTarget > Integer.MAX_VALUE) { // Do not throw an exception here as this should not affect binder calls. Slog.w(TAG, "Attempted to create a bucket larger than maxint"); + mBuckets = Arrays.copyOfRange(buffer, 0, i); return; } - if ((int) nextTarget > lastValue) { + if ((int) nextTarget > buffer[i - 1]) { // Convert the target bucket limit value to an integer. - mBuckets.add((int) nextTarget); - lastValue = (int) nextTarget; + buffer[i] = (int) nextTarget; } else { // Avoid creating redundant buckets, so bucket size should be 1 at a minimum. - mBuckets.add(lastValue + 1); - lastValue = lastValue + 1; + buffer[i] = buffer[i - 1] + 1; } lastTarget = nextTarget; } + mBuckets = buffer; } /** Gets the bucket index to insert the provided sample in. */ public int sampleToBucket(int sample) { - if (sample > mBuckets.get(mBuckets.size() - 1)) { - return mBuckets.size(); + if (sample >= mBuckets[mBuckets.length - 1]) { + return mBuckets.length; } // Binary search returns the element index if it is contained in the list - in this case the @@ -80,12 +78,12 @@ public class BinderLatencyBuckets { // Otherwise, it returns (-(insertion point) - 1), where insertion point is the point where // to insert the element so that the array remains sorted - in this case the bucket index // is the insertion point. - int searchResult = Collections.binarySearch(mBuckets, sample); + int searchResult = Arrays.binarySearch(mBuckets, sample); return searchResult < 0 ? -(1 + searchResult) : searchResult + 1; } @VisibleForTesting - public ArrayList<Integer> getBuckets() { + public int[] getBuckets() { return mBuckets; } } diff --git a/core/java/com/android/internal/os/BinderTransactionNameResolver.java b/core/java/com/android/internal/os/BinderTransactionNameResolver.java new file mode 100644 index 000000000000..5f6f427d344c --- /dev/null +++ b/core/java/com/android/internal/os/BinderTransactionNameResolver.java @@ -0,0 +1,89 @@ +/* + * 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.Binder; + +import com.android.internal.annotations.VisibleForTesting; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.HashMap; + +/** + * Maps a binder class and transaction code to the default transaction name. Since this + * resolution is class-based as opposed to instance-based, any custom implementation of + * {@link Binder#getTransactionName} will be ignored. + * + * The class is NOT thread safe + * + * @hide + */ +@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) +public class BinderTransactionNameResolver { + private static final Method NO_GET_DEFAULT_TRANSACTION_NAME_METHOD; + + /** + * Generates the default transaction method name, which is just the transaction code. + * Used when the binder does not define a static "getDefaultTransactionName" method. + * + * @hide + */ + public static String noDefaultTransactionName(int transactionCode) { + return String.valueOf(transactionCode); + } + + static { + try { + NO_GET_DEFAULT_TRANSACTION_NAME_METHOD = BinderTransactionNameResolver.class.getMethod( + "noDefaultTransactionName", int.class); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + private final HashMap<Class<? extends Binder>, Method> + mGetDefaultTransactionNameMethods = new HashMap<>(); + + /** + * Given a binder class name and transaction code, returns the corresponding method name. + * + * @hide + */ + public String getMethodName(Class<? extends Binder> binderClass, int transactionCode) { + Method method = mGetDefaultTransactionNameMethods.get(binderClass); + if (method == null) { + try { + method = binderClass.getMethod("getDefaultTransactionName", int.class); + } catch (NoSuchMethodException e) { + method = NO_GET_DEFAULT_TRANSACTION_NAME_METHOD; + } + if (method.getReturnType() != String.class + || !Modifier.isStatic(method.getModifiers())) { + method = NO_GET_DEFAULT_TRANSACTION_NAME_METHOD; + } + mGetDefaultTransactionNameMethods.put(binderClass, method); + } + + try { + return (String) method.invoke(null, transactionCode); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } +} diff --git a/core/java/com/android/internal/os/WrapperInit.java b/core/java/com/android/internal/os/WrapperInit.java index 6860759eea8a..508782b9f3dc 100644 --- a/core/java/com/android/internal/os/WrapperInit.java +++ b/core/java/com/android/internal/os/WrapperInit.java @@ -21,8 +21,8 @@ import android.os.Trace; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; -import android.system.StructCapUserData; -import android.system.StructCapUserHeader; +import android.system.StructUserCapData; +import android.system.StructUserCapHeader; import android.util.Slog; import android.util.TimingsTraceLog; @@ -187,9 +187,9 @@ public class WrapperInit { * capabilities, which may make it crash, but not exceed its allowances. */ private static void preserveCapabilities() { - StructCapUserHeader header = new StructCapUserHeader( + StructUserCapHeader header = new StructUserCapHeader( OsConstants._LINUX_CAPABILITY_VERSION_3, 0); - StructCapUserData[] data; + StructUserCapData[] data; try { data = Os.capget(header); } catch (ErrnoException e) { @@ -199,9 +199,9 @@ public class WrapperInit { if (data[0].permitted != data[0].inheritable || data[1].permitted != data[1].inheritable) { - data[0] = new StructCapUserData(data[0].effective, data[0].permitted, + data[0] = new StructUserCapData(data[0].effective, data[0].permitted, data[0].permitted); - data[1] = new StructCapUserData(data[1].effective, data[1].permitted, + data[1] = new StructUserCapData(data[1].effective, data[1].permitted, data[1].permitted); try { Os.capset(header, data); diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index a54108957775..cb6008bfa961 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -45,8 +45,8 @@ import android.security.keystore2.AndroidKeyStoreProvider; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; -import android.system.StructCapUserData; -import android.system.StructCapUserHeader; +import android.system.StructUserCapData; +import android.system.StructUserCapHeader; import android.text.Hyphenator; import android.util.EventLog; import android.util.Log; @@ -586,10 +586,18 @@ public class ZygoteInit { codePaths[0], /*dexMetadata*/ null); - File profileDir = Environment.getDataProfilesDePackageDirectory( + File curProfileDir = Environment.getDataProfilesDePackageDirectory( UserHandle.USER_SYSTEM, systemServerPackageName); - String profilePath = new File(profileDir, systemServerProfileName).getAbsolutePath(); - VMRuntime.registerAppInfo(profilePath, codePaths); + String curProfilePath = new File(curProfileDir, systemServerProfileName).getAbsolutePath(); + File refProfileDir = Environment.getDataProfilesDePackageDirectory( + UserHandle.USER_SYSTEM, systemServerPackageName); + String refProfilePath = new File(refProfileDir, systemServerProfileName).getAbsolutePath(); + VMRuntime.registerAppInfo( + systemServerPackageName, + curProfilePath, + refProfilePath, + codePaths, + VMRuntime.CODE_PATH_TYPE_PRIMARY_APK); } /** @@ -742,9 +750,9 @@ public class ZygoteInit { OsConstants.CAP_BLOCK_SUSPEND ); /* Containers run without some capabilities, so drop any caps that are not available. */ - StructCapUserHeader header = new StructCapUserHeader( + StructUserCapHeader header = new StructUserCapHeader( OsConstants._LINUX_CAPABILITY_VERSION_3, 0); - StructCapUserData[] data; + StructUserCapData[] data; try { data = Os.capget(header); } catch (ErrnoException ex) { diff --git a/core/java/com/android/internal/util/OWNERS b/core/java/com/android/internal/util/OWNERS index a0454510b30b..5b68159888cc 100644 --- a/core/java/com/android/internal/util/OWNERS +++ b/core/java/com/android/internal/util/OWNERS @@ -1,5 +1,6 @@ per-file AsyncChannel* = lorenzo@google.com, satk@google.com, etancohen@google.com per-file MessageUtils*, Protocol*, RingBuffer*, TokenBucket* = jchalard@google.com, lorenzo@google.com, satk@google.com +per-file *Notification* = file:/services/core/java/com/android/server/notification/OWNERS per-file Protocol* = etancohen@google.com, lorenzo@google.com per-file State* = jchalard@google.com, lorenzo@google.com, satk@google.com per-file DataClass* = eugenesusla@google.com
\ No newline at end of file diff --git a/core/java/com/android/server/OWNERS b/core/java/com/android/server/OWNERS index 1262925447b9..554e27890476 100644 --- a/core/java/com/android/server/OWNERS +++ b/core/java/com/android/server/OWNERS @@ -1 +1 @@ -per-file SystemConfig.java = toddke@google.com +per-file SystemConfig.java = toddke@google.com,patb@google.com diff --git a/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp index 24fef4881e4c..5fe96ede202e 100644 --- a/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp +++ b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp @@ -402,7 +402,7 @@ jboolean com_android_internal_os_ZygoteCommandBuffer_nativeForkRepeatedly( socklen_t cred_size = sizeof credentials; if (getsockopt(n_buffer->getFd(), SOL_SOCKET, SO_PEERCRED, &credentials, &cred_size) == -1 || cred_size != sizeof credentials) { - fail_fn_1("ForkMany failed to get initial credentials, %s", strerror(errno)); + fail_fn_1(CREATE_ERROR("ForkMany failed to get initial credentials, %s", strerror(errno))); } bool first_time = true; @@ -453,7 +453,7 @@ jboolean com_android_internal_os_ZygoteCommandBuffer_nativeForkRepeatedly( close(session_socket); int new_fd = accept(zygote_socket_fd, nullptr, nullptr); if (new_fd == -1) { - fail_fn_z("Accept(%d) failed: %s", zygote_socket_fd, strerror(errno)); + fail_fn_z(CREATE_ERROR("Accept(%d) failed: %s", zygote_socket_fd, strerror(errno))); } if (new_fd != session_socket) { // Move new_fd back to the old value, so that we don't have to change Java-level data diff --git a/core/proto/OWNERS b/core/proto/OWNERS index e62b5c102a59..44ea23fdf685 100644 --- a/core/proto/OWNERS +++ b/core/proto/OWNERS @@ -14,9 +14,10 @@ per-file settings_enums.proto=tmfang@google.com # Frameworks ogunwale@google.com jjaggi@google.com +kwekua@google.com roosa@google.com -per-file package_item_info.proto = toddke@google.com -per-file usagestatsservice.proto, usagestatsservice_v2.proto = mwachens@google.com +per-file package_item_info.proto = toddke@google.com,patb@google.com +per-file usagestatsservice.proto, usagestatsservice_v2.proto = file:/core/java/android/app/usage/OWNERS per-file apphibernationservice.proto = file:/core/java/android/apphibernation/OWNERS # Biometrics diff --git a/core/res/OWNERS b/core/res/OWNERS index 9d739b90bcc5..7a8da36d8a7d 100644 --- a/core/res/OWNERS +++ b/core/res/OWNERS @@ -1,6 +1,7 @@ adamp@google.com alanv@google.com asc@google.com +cinek@google.com dsandler@android.com dsandler@google.com dupin@google.com @@ -8,6 +9,7 @@ hackbod@android.com hackbod@google.com ilyamaty@google.com jaggies@google.com +jdemeulenaere@google.com jsharkey@android.com jsharkey@google.com juliacr@google.com @@ -17,7 +19,9 @@ nandana@google.com narayan@google.com ogunwale@google.com patb@google.com +shanh@google.com svetoslavganov@android.com svetoslavganov@google.com toddke@google.com +tsuji@google.com yamasani@google.com diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsBinderCallStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsBinderCallStatsTest.java new file mode 100644 index 000000000000..3e67b8bffa63 --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsBinderCallStatsTest.java @@ -0,0 +1,93 @@ +/* + * 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.Binder; +import android.os.Process; +import android.util.ArraySet; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import junit.framework.TestCase; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * Test cases for android.os.BatteryStats, system server Binder call stats. + */ +@RunWith(AndroidJUnit4.class) +@SmallTest +public class BatteryStatsBinderCallStatsTest extends TestCase { + + private static final int TRANSACTION_CODE = 100; + + /** + * Test BatteryStatsImpl.Uid.noteBinderCallStats. + */ + @Test + public void testNoteBinderCallStats() throws Exception { + final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms + MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks); + + int callingUid = Process.FIRST_APPLICATION_UID + 1; + int workSourceUid = Process.FIRST_APPLICATION_UID + 1; + + Collection<BinderCallsStats.CallStat> callStats = new ArrayList<>(); + BinderCallsStats.CallStat stat1 = new BinderCallsStats.CallStat(callingUid, + MockBinder.class, TRANSACTION_CODE, true /*screenInteractive */); + stat1.incrementalCallCount = 21; + stat1.recordedCallCount = 5; + stat1.cpuTimeMicros = 1000; + callStats.add(stat1); + + bi.noteBinderCallStats(workSourceUid, 42, callStats); + + callStats.clear(); + BinderCallsStats.CallStat stat2 = new BinderCallsStats.CallStat(callingUid, + MockBinder.class, TRANSACTION_CODE, true /*screenInteractive */); + stat2.incrementalCallCount = 9; + stat2.recordedCallCount = 8; + stat2.cpuTimeMicros = 500; + callStats.add(stat2); + + bi.noteBinderCallStats(workSourceUid, 8, callStats); + + BatteryStatsImpl.Uid uid = bi.getUidStatsLocked(workSourceUid); + assertEquals(42 + 8, uid.getBinderCallCount()); + + BinderTransactionNameResolver resolver = new BinderTransactionNameResolver(); + ArraySet<BatteryStatsImpl.BinderCallStats> stats = uid.getBinderCallStats(); + assertEquals(1, stats.size()); + BatteryStatsImpl.BinderCallStats value = stats.valueAt(0); + value.ensureMethodName(resolver); + assertEquals("testMethod", value.getMethodName()); + assertEquals(21 + 9, value.callCount); + assertEquals(8, value.recordedCallCount); + assertEquals(500, value.recordedCpuTimeMicros); + } + + private static class MockBinder extends Binder { + public static String getDefaultTransactionName(int txCode) { + return txCode == TRANSACTION_CODE ? "testMethod" : "unknown"; + } + } +} 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 2ad8e18741f9..7807f019914e 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java @@ -23,6 +23,7 @@ import org.junit.runners.Suite; @Suite.SuiteClasses({ BatteryStatsCpuTimesTest.class, BatteryStatsBackgroundStatsTest.class, + BatteryStatsBinderCallStatsTest.class, BatteryStatsCounterTest.class, BatteryStatsDualTimerTest.class, BatteryStatsDurationTimerTest.class, diff --git a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java index cec62164e57a..68c68704a1b3 100644 --- a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java @@ -16,10 +16,16 @@ package com.android.internal.os; +import static com.google.common.truth.Truth.assertThat; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import android.os.Binder; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.Process; import android.os.SystemClock; import android.platform.test.annotations.Presubmit; import android.util.ArrayMap; @@ -46,11 +52,12 @@ import java.util.Random; @RunWith(AndroidJUnit4.class) @Presubmit public class BinderCallsStatsTest { - private static final int WORKSOURCE_UID = 1; + private static final int WORKSOURCE_UID = Process.FIRST_APPLICATION_UID; private static final int CALLING_UID = 2; private static final int REQUEST_SIZE = 2; private static final int REPLY_SIZE = 3; private final CachedDeviceState mDeviceState = new CachedDeviceState(false, true); + private final TestHandler mHandler = new TestHandler(); @Test public void testDetailedOff() { @@ -754,6 +761,53 @@ public class BinderCallsStatsTest { } @Test + public void testCallStatsObserver() { + TestBinderCallsStats bcs = new TestBinderCallsStats(); + bcs.setSamplingInterval(1); + bcs.setTrackScreenInteractive(false); + + final ArrayList<BinderCallsStats.CallStat> callStatsList = new ArrayList<>(); + bcs.setCallStatsObserver( + (workSourceUid, incrementalCallCount, callStats) -> callStatsList.addAll( + callStats)); + + Binder binder = new Binder(); + + CallSession callSession = bcs.callStarted(binder, 1, WORKSOURCE_UID); + bcs.time += 10; + bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID); + + callSession = bcs.callStarted(binder, 1, WORKSOURCE_UID); + bcs.time += 20; + bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID); + + callSession = bcs.callStarted(binder, 2, WORKSOURCE_UID); + bcs.time += 30; + bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID); + + for (Runnable runnable: mHandler.mRunnables) { + // Execute all pending runnables. Ignore the delay. + runnable.run(); + } + + assertThat(callStatsList).hasSize(2); + for (int i = 0; i < 2; i++) { + BinderCallsStats.CallStat callStats = callStatsList.get(i); + if (callStats.transactionCode == 1) { + assertEquals(2, callStats.callCount); + assertEquals(2, callStats.recordedCallCount); + assertEquals(30, callStats.cpuTimeMicros); + assertEquals(20, callStats.maxCpuTimeMicros); + } else { + assertEquals(1, callStats.callCount); + assertEquals(1, callStats.recordedCallCount); + assertEquals(30, callStats.cpuTimeMicros); + assertEquals(30, callStats.maxCpuTimeMicros); + } + } + } + + @Test public void testLatencyCollectionEnabled() { TestBinderCallsStats bcs = new TestBinderCallsStats(); bcs.setCollectLatencyData(true); @@ -781,6 +835,20 @@ public class BinderCallsStatsTest { assertEquals(0, bcs.getLatencyObserver().getLatencyHistograms().size()); } + private static class TestHandler extends Handler { + ArrayList<Runnable> mRunnables = new ArrayList<>(); + + TestHandler() { + super(Looper.getMainLooper()); + } + + @Override + public boolean sendMessageAtTime(Message msg, long uptimeMillis) { + mRunnables.add(msg.getCallback()); + return true; + } + } + class TestBinderCallsStats extends BinderCallsStats { public int callingUid = CALLING_UID; public long time = 1234; @@ -803,6 +871,10 @@ public class BinderCallsStatsTest { }; } + public Handler getHandler() { + return mHandler; + } + public BinderLatencyObserver getLatencyObserver() { return new BinderLatencyObserverTest.TestBinderLatencyObserver(); } diff --git a/core/tests/coretests/src/com/android/internal/os/BinderLatencyBucketsTest.java b/core/tests/coretests/src/com/android/internal/os/BinderLatencyBucketsTest.java index 00443a967c79..b2054f1ee9ad 100644 --- a/core/tests/coretests/src/com/android/internal/os/BinderLatencyBucketsTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BinderLatencyBucketsTest.java @@ -36,6 +36,7 @@ public class BinderLatencyBucketsTest { public void testBucketThresholds() { BinderLatencyBuckets latencyBuckets = new BinderLatencyBuckets(10, 2, 1.45f); assertThat(latencyBuckets.getBuckets()) + .asList() .containsExactly(2, 3, 4, 6, 8, 12, 18, 26, 39) .inOrder(); } @@ -58,6 +59,7 @@ public class BinderLatencyBucketsTest { public void testMaxIntBuckets() { BinderLatencyBuckets latencyBuckets = new BinderLatencyBuckets(5, Integer.MAX_VALUE / 2, 2); assertThat(latencyBuckets.getBuckets()) + .asList() .containsExactly(Integer.MAX_VALUE / 2, Integer.MAX_VALUE - 1) .inOrder(); diff --git a/core/tests/utiltests/src/com/android/internal/util/FileRotatorTest.java b/core/tests/utiltests/src/com/android/internal/util/FileRotatorTest.java index 3f9e62e7b180..952721320c90 100644 --- a/core/tests/utiltests/src/com/android/internal/util/FileRotatorTest.java +++ b/core/tests/utiltests/src/com/android/internal/util/FileRotatorTest.java @@ -29,6 +29,8 @@ import android.util.Log; import com.android.internal.util.FileRotator.Reader; import com.android.internal.util.FileRotator.Writer; +import com.android.internal.util.test.FsUtil; + import com.google.android.collect.Lists; import java.io.DataInputStream; @@ -38,15 +40,10 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.net.ProtocolException; import java.util.ArrayList; import java.util.Arrays; import java.util.Random; -import junit.framework.Assert; - -import libcore.io.IoUtils; - /** * Tests for {@link FileRotator}. */ @@ -67,7 +64,7 @@ public class FileRotatorTest extends AndroidTestCase { super.setUp(); mBasePath = getContext().getFilesDir(); - IoUtils.deleteContents(mBasePath); + FsUtil.deleteContents(mBasePath); } public void testEmpty() throws Exception { diff --git a/data/etc/OWNERS b/data/etc/OWNERS index 5aacfddab28c..ea23aba16d12 100644 --- a/data/etc/OWNERS +++ b/data/etc/OWNERS @@ -10,6 +10,7 @@ svetoslavganov@android.com svetoslavganov@google.com toddke@android.com toddke@google.com +patb@google.com yamasani@google.com per-file preinstalled-packages* = file:/MULTIUSER_OWNERS diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index 62e11b9baca2..ee2387b167a2 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -444,6 +444,7 @@ applications that come with the platform <permission name="android.permission.MANAGE_DEBUGGING" /> <!-- Permissions required for CTS test - TimeManagerTest --> <permission name="android.permission.MANAGE_TIME_AND_ZONE_DETECTION" /> + <permission name="android.permission.SUGGEST_EXTERNAL_TIME" /> <!-- Permissions required for CTS test - CtsHdmiCecHostTestCases --> <permission name="android.permission.HDMI_CEC"/> <!-- Permission required for CTS test - MediaPlayerTest --> diff --git a/data/keyboards/Vendor_0171_Product_0419.kl b/data/keyboards/Vendor_0171_Product_0419.kl new file mode 100644 index 000000000000..05a25f0210c8 --- /dev/null +++ b/data/keyboards/Vendor_0171_Product_0419.kl @@ -0,0 +1,55 @@ +# Copyright (C) 2021 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# +# Amazon Luna Controller +# + +key 304 BUTTON_A +key 305 BUTTON_B +key 307 BUTTON_X +key 308 BUTTON_Y +key 310 BUTTON_L1 +key 311 BUTTON_R1 + +key 317 BUTTON_THUMBL +key 318 BUTTON_THUMBR + +# Left and right stick. +axis 0x00 X flat 4096 +axis 0x01 Y flat 4096 +axis 0x02 Z flat 4096 +axis 0x05 RZ flat 4096 + +# Triggers. +axis 0x0a LTRIGGER +axis 0x09 RTRIGGER + +# Hat. +axis 0x10 HAT_X +axis 0x11 HAT_Y + +# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt + +# Action button (circle icon, left of the Home button) +key 158 BUTTON_SELECT + +# Home button (branded button in the center of the controller) +key 172 BUTTON_MODE + +# Menu button (hamburger icon, right of the Home button) +key 315 BUTTON_START + +# Alexa Push-To-Talk button (microphone icon, below the Home button) +key 217 MEDIA_RECORD diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java index fe05989c3846..97592b44ba2e 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java @@ -252,7 +252,9 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { blockModes, userAuthenticationRequired, (int) userAuthenticationValidityDurationSeconds, - keymasterHwEnforcedUserAuthenticators, + userAuthenticationRequirementEnforcedBySecureHardware + ? keymasterHwEnforcedUserAuthenticators + : keymasterSwEnforcedUserAuthenticators, userAuthenticationRequirementEnforcedBySecureHardware, userAuthenticationValidWhileOnBody, trustedUserPresenceRequired, diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java index 3e2fb94f0387..f3cfcf18dec1 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java @@ -41,6 +41,8 @@ import android.system.keystore2.KeyMetadata; import android.system.keystore2.ResponseCode; import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; + import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; @@ -974,7 +976,6 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi { } private Set<String> getUniqueAliases() { - try { final KeyDescriptor[] keys = mKeyStore.list( getTargetDomain(), @@ -987,7 +988,7 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi { return aliases; } catch (android.security.KeyStoreException e) { Log.e(TAG, "Failed to list keystore entries.", e); - return null; + return new HashSet<>(); } } @@ -1099,6 +1100,17 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi { return caAlias; } + /** + * Used by Tests to initialize with a fake KeyStore2. + * @hide + * @param keystore + */ + @VisibleForTesting + public void initForTesting(KeyStore2 keystore) { + mKeyStore = keystore; + mNamespace = KeyProperties.NAMESPACE_APPLICATION; + } + @Override public void engineStore(OutputStream stream, char[] password) throws IOException, NoSuchAlgorithmException, CertificateException { diff --git a/keystore/tests/Android.bp b/keystore/tests/Android.bp index 2315a8568c64..7de45233494b 100644 --- a/keystore/tests/Android.bp +++ b/keystore/tests/Android.bp @@ -28,6 +28,7 @@ android_test { static_libs: [ "androidx.test.rules", "hamcrest-library", + "mockito-target-minus-junit4", ], platform_apis: true, libs: ["android.test.runner"], diff --git a/keystore/tests/src/android/security/ParcelableKeyGenParameterSpecTest.java b/keystore/tests/src/android/security/ParcelableKeyGenParameterSpecTest.java index b7d72fce6eba..2ae61ab3b38d 100644 --- a/keystore/tests/src/android/security/ParcelableKeyGenParameterSpecTest.java +++ b/keystore/tests/src/android/security/ParcelableKeyGenParameterSpecTest.java @@ -43,7 +43,6 @@ public final class ParcelableKeyGenParameterSpecTest { static final String ALIAS = "keystore-alias"; static final String ANOTHER_ALIAS = "another-keystore-alias"; static final int KEY_PURPOSES = KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY; - static final int UID = 1230; static final int KEYSIZE = 2048; static final X500Principal SUBJECT = new X500Principal("CN=subject"); static final BigInteger SERIAL = new BigInteger("1234567890"); @@ -61,7 +60,7 @@ public final class ParcelableKeyGenParameterSpecTest { public static KeyGenParameterSpec configureDefaultSpec() { return new KeyGenParameterSpec.Builder(ALIAS, KEY_PURPOSES) - .setUid(UID) + .setNamespace(KeyProperties.NAMESPACE_WIFI) .setKeySize(KEYSIZE) .setCertificateSubject(SUBJECT) .setCertificateSerialNumber(SERIAL) @@ -88,10 +87,11 @@ public final class ParcelableKeyGenParameterSpecTest { .build(); } - public static void validateSpecValues(KeyGenParameterSpec spec, int uid, String alias) { + public static void validateSpecValues(KeyGenParameterSpec spec, + @KeyProperties.Namespace int namespace, String alias) { assertThat(spec.getKeystoreAlias(), is(alias)); assertThat(spec.getPurposes(), is(KEY_PURPOSES)); - assertThat(spec.getUid(), is(uid)); + assertThat(spec.getNamespace(), is(namespace)); assertThat(spec.getKeySize(), is(KEYSIZE)); assertThat(spec.getCertificateSubject(), is(SUBJECT)); assertThat(spec.getCertificateSerialNumber(), is(SERIAL)); @@ -134,7 +134,7 @@ public final class ParcelableKeyGenParameterSpecTest { Parcel parcel = parcelForReading(spec); ParcelableKeyGenParameterSpec fromParcel = ParcelableKeyGenParameterSpec.CREATOR.createFromParcel(parcel); - validateSpecValues(fromParcel.getSpec(), UID, ALIAS); + validateSpecValues(fromParcel.getSpec(), KeyProperties.NAMESPACE_WIFI, ALIAS); assertThat(parcel.dataAvail(), is(0)); } diff --git a/keystore/tests/src/android/security/keystore/KeyGenParameterSpecTest.java b/keystore/tests/src/android/security/keystore/KeyGenParameterSpecTest.java index b2edfd05d13f..ddbb1d8c097c 100644 --- a/keystore/tests/src/android/security/keystore/KeyGenParameterSpecTest.java +++ b/keystore/tests/src/android/security/keystore/KeyGenParameterSpecTest.java @@ -21,8 +21,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import android.security.ParcelableKeyGenParameterSpecTest; -import android.security.keystore.KeyGenParameterSpec; -import android.security.keystore.KeyProperties; import androidx.test.runner.AndroidJUnit4; @@ -41,7 +39,7 @@ public final class KeyGenParameterSpecTest { KeyGenParameterSpec copiedSpec = new KeyGenParameterSpec.Builder(spec).build(); ParcelableKeyGenParameterSpecTest.validateSpecValues( - copiedSpec, spec.getUid(), spec.getKeystoreAlias()); + copiedSpec, spec.getNamespace(), spec.getKeystoreAlias()); } @Test diff --git a/keystore/tests/src/android/security/keystore2/AndroidKeyStoreSpiTest.java b/keystore/tests/src/android/security/keystore2/AndroidKeyStoreSpiTest.java new file mode 100644 index 000000000000..1bd3069f483a --- /dev/null +++ b/keystore/tests/src/android/security/keystore2/AndroidKeyStoreSpiTest.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.keystore2; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.anyLong; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.security.KeyStore2; +import android.security.KeyStoreException; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +public class AndroidKeyStoreSpiTest { + + @Mock + private KeyStore2 mKeystore2; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testEngineAliasesReturnsEmptySetOnKeyStoreError() throws Exception { + when(mKeystore2.list(anyInt(), anyLong())) + .thenThrow(new KeyStoreException(6, "Some Error")); + AndroidKeyStoreSpi spi = new AndroidKeyStoreSpi(); + spi.initForTesting(mKeystore2); + + assertThat("Empty collection expected", !spi.engineAliases().hasMoreElements()); + + verify(mKeystore2).list(anyInt(), anyLong()); + } + +} diff --git a/libs/androidfw/OWNERS b/libs/androidfw/OWNERS index bc056df23a36..610fd80fe73c 100644 --- a/libs/androidfw/OWNERS +++ b/libs/androidfw/OWNERS @@ -1,6 +1,7 @@ set noparent toddke@google.com rtmitchell@google.com +patb@google.com per-file CursorWindow.cpp=omakoto@google.com per-file LocaleDataTables.cpp=vichang@google.com,ngeoffray@google.com,nikitai@google.com diff --git a/packages/Connectivity/framework/api/module-lib-current.txt b/packages/Connectivity/framework/api/module-lib-current.txt index 78dff21b6c68..6c454bcd4cd7 100644 --- a/packages/Connectivity/framework/api/module-lib-current.txt +++ b/packages/Connectivity/framework/api/module-lib-current.txt @@ -48,6 +48,7 @@ package android.net { public class ConnectivitySettingsManager { method public static void clearGlobalProxy(@NonNull android.content.Context); + method @NonNull public static java.util.Set<java.lang.String> getAppsAllowedOnRestrictedNetworks(@NonNull android.content.Context); method @Nullable public static String getCaptivePortalHttpUrl(@NonNull android.content.Context); method public static int getCaptivePortalMode(@NonNull android.content.Context, int); method @NonNull public static java.time.Duration getConnectivityKeepPendingIntentDuration(@NonNull android.content.Context, @NonNull java.time.Duration); @@ -57,7 +58,7 @@ package android.net { method @Nullable public static android.net.ProxyInfo getGlobalProxy(@NonNull android.content.Context); method @NonNull public static java.time.Duration getMobileDataActivityTimeout(@NonNull android.content.Context, @NonNull java.time.Duration); method public static boolean getMobileDataAlwaysOn(@NonNull android.content.Context, boolean); - method @Nullable public static String getMobileDataPreferredApps(@NonNull android.content.Context); + method @NonNull public static java.util.Set<java.lang.Integer> getMobileDataPreferredUids(@NonNull android.content.Context); method public static int getNetworkAvoidBadWifi(@NonNull android.content.Context); method @Nullable public static String getNetworkMeteredMultipathPreference(@NonNull android.content.Context); method public static int getNetworkSwitchNotificationMaximumDailyCount(@NonNull android.content.Context, int); @@ -67,6 +68,7 @@ package android.net { method public static int getPrivateDnsMode(@NonNull android.content.Context); method public static boolean getWifiAlwaysRequested(@NonNull android.content.Context, boolean); method @NonNull public static java.time.Duration getWifiDataActivityTimeout(@NonNull android.content.Context, @NonNull java.time.Duration); + method public static void setAppsAllowedOnRestrictedNetworks(@NonNull android.content.Context, @NonNull java.util.Set<java.lang.String>); method public static void setCaptivePortalHttpUrl(@NonNull android.content.Context, @Nullable String); method public static void setCaptivePortalMode(@NonNull android.content.Context, int); method public static void setConnectivityKeepPendingIntentDuration(@NonNull android.content.Context, @NonNull java.time.Duration); @@ -76,7 +78,7 @@ package android.net { method public static void setGlobalProxy(@NonNull android.content.Context, @NonNull android.net.ProxyInfo); method public static void setMobileDataActivityTimeout(@NonNull android.content.Context, @NonNull java.time.Duration); method public static void setMobileDataAlwaysOn(@NonNull android.content.Context, boolean); - method public static void setMobileDataPreferredApps(@NonNull android.content.Context, @Nullable String); + method public static void setMobileDataPreferredUids(@NonNull android.content.Context, @NonNull java.util.Set<java.lang.Integer>); method public static void setNetworkAvoidBadWifi(@NonNull android.content.Context, int); method public static void setNetworkMeteredMultipathPreference(@NonNull android.content.Context, @NonNull String); method public static void setNetworkSwitchNotificationMaximumDailyCount(@NonNull android.content.Context, @IntRange(from=0) int); diff --git a/packages/Connectivity/framework/api/system-current.txt b/packages/Connectivity/framework/api/system-current.txt index 5750845c5863..27bf114b5229 100644 --- a/packages/Connectivity/framework/api/system-current.txt +++ b/packages/Connectivity/framework/api/system-current.txt @@ -294,7 +294,6 @@ package android.net { method @NonNull public android.net.NetworkCapabilities.Builder addCapability(int); method @NonNull public android.net.NetworkCapabilities.Builder addTransportType(int); method @NonNull public android.net.NetworkCapabilities build(); - method @NonNull public android.net.NetworkCapabilities.Builder clearAll(); method @NonNull public android.net.NetworkCapabilities.Builder removeCapability(int); method @NonNull public android.net.NetworkCapabilities.Builder removeTransportType(int); method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setAdministratorUids(@NonNull int[]); @@ -308,6 +307,7 @@ package android.net { method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setSsid(@Nullable String); method @NonNull public android.net.NetworkCapabilities.Builder setSubscriptionIds(@NonNull java.util.Set<java.lang.Integer>); method @NonNull public android.net.NetworkCapabilities.Builder setTransportInfo(@Nullable android.net.TransportInfo); + method @NonNull public static android.net.NetworkCapabilities.Builder withoutDefaultCapabilities(); } public class NetworkProvider { @@ -381,6 +381,7 @@ package android.net { public abstract class QosFilter { method @NonNull public abstract android.net.Network getNetwork(); method public abstract boolean matchesLocalAddress(@NonNull java.net.InetAddress, int, int); + method public abstract boolean matchesRemoteAddress(@NonNull java.net.InetAddress, int, int); } public final class QosSession implements android.os.Parcelable { @@ -403,6 +404,7 @@ package android.net { method public int describeContents(); method @NonNull public java.net.InetSocketAddress getLocalSocketAddress(); method @NonNull public android.net.Network getNetwork(); + method @Nullable public java.net.InetSocketAddress getRemoteSocketAddress(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.net.QosSocketInfo> CREATOR; } diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityDiagnosticsManager.java b/packages/Connectivity/framework/src/android/net/ConnectivityDiagnosticsManager.java index 3598ebc70118..dcc8a5eacd13 100644 --- a/packages/Connectivity/framework/src/android/net/ConnectivityDiagnosticsManager.java +++ b/packages/Connectivity/framework/src/android/net/ConnectivityDiagnosticsManager.java @@ -713,7 +713,9 @@ public class ConnectivityDiagnosticsManager { * <p>Callbacks registered by apps not meeting the above criteria will not be invoked. * * <p>If a registering app loses its relevant permissions, any callbacks it registered will - * silently stop receiving callbacks. + * silently stop receiving callbacks. Note that registering apps must also have location + * permissions to receive callbacks as some Networks may be location-bound (such as WiFi + * networks). * * <p>Each register() call <b>MUST</b> use a ConnectivityDiagnosticsCallback instance that is * not currently registered. If a ConnectivityDiagnosticsCallback instance is registered with diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java index 0a3e23123702..1a6b37bfdb42 100644 --- a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java +++ b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java @@ -3337,7 +3337,60 @@ public class ConnectivityManager { provider.setProviderId(NetworkProvider.ID_NONE); } + /** + * Register or update a network offer with ConnectivityService. + * + * ConnectivityService keeps track of offers made by the various providers and matches + * them to networking requests made by apps or the system. The provider supplies a score + * and the capabilities of the network it might be able to bring up ; these act as filters + * used by ConnectivityService to only send those requests that can be fulfilled by the + * provider. + * + * The provider is under no obligation to be able to bring up the network it offers at any + * given time. Instead, this mechanism is meant to limit requests received by providers + * to those they actually have a chance to fulfill, as providers don't have a way to compare + * the quality of the network satisfying a given request to their own offer. + * + * An offer can be updated by calling this again with the same callback object. This is + * similar to calling unofferNetwork and offerNetwork again, but will only update the + * provider with the changes caused by the changes in the offer. + * + * @param provider The provider making this offer. + * @param score The prospective score of the network. + * @param caps The prospective capabilities of the network. + * @param callback The callback to call when this offer is needed or unneeded. + * @hide + */ + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_FACTORY}) + public void offerNetwork(@NonNull final NetworkProvider provider, + @NonNull final NetworkScore score, @NonNull final NetworkCapabilities caps, + @NonNull final INetworkOfferCallback callback) { + try { + mService.offerNetwork(Objects.requireNonNull(provider.getMessenger(), "null messenger"), + Objects.requireNonNull(score, "null score"), + Objects.requireNonNull(caps, "null caps"), + Objects.requireNonNull(callback, "null callback")); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** + * Withdraw a network offer made with {@link #offerNetwork}. + * + * @param callback The callback passed at registration time. This must be the same object + * that was passed to {@link #offerNetwork} + * @hide + */ + public void unofferNetwork(@NonNull final INetworkOfferCallback callback) { + try { + mService.unofferNetwork(Objects.requireNonNull(callback)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } /** @hide exposed via the NetworkProvider class. */ @RequiresPermission(anyOf = { NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, diff --git a/packages/Connectivity/framework/src/android/net/ConnectivitySettingsManager.java b/packages/Connectivity/framework/src/android/net/ConnectivitySettingsManager.java index 31e1fb058187..762f24f7e79a 100644 --- a/packages/Connectivity/framework/src/android/net/ConnectivitySettingsManager.java +++ b/packages/Connectivity/framework/src/android/net/ConnectivitySettingsManager.java @@ -28,8 +28,11 @@ import android.annotation.SystemApi; import android.content.ContentResolver; import android.content.Context; import android.net.ConnectivityManager.MultipathPreference; +import android.os.Process; +import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; +import android.util.ArraySet; import android.util.Range; import com.android.net.module.util.ProxyUtils; @@ -38,6 +41,8 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.time.Duration; import java.util.List; +import java.util.Set; +import java.util.StringJoiner; /** * A manager class for connectivity module settings. @@ -330,12 +335,12 @@ public class ConnectivitySettingsManager { "network_metered_multipath_preference"; /** - * A list of apps that should go on cellular networks in preference even when higher-priority + * A list of uids that should go on cellular networks in preference even when higher-priority * networks are connected. * * @hide */ - public static final String MOBILE_DATA_PREFERRED_APPS = "mobile_data_preferred_apps"; + public static final String MOBILE_DATA_PREFERRED_UIDS = "mobile_data_preferred_uids"; /** * One of the private DNS modes that indicates the private DNS mode is off. @@ -369,6 +374,14 @@ public class ConnectivitySettingsManager { private static final String PRIVATE_DNS_MODE_PROVIDER_HOSTNAME_STRING = "hostname"; /** + * A list of apps that is allowed on restricted networks. + * + * @hide + */ + public static final String APPS_ALLOWED_ON_RESTRICTED_NETWORKS = + "apps_allowed_on_restricted_networks"; + + /** * Get mobile data activity timeout from {@link Settings}. * * @param context The {@link Context} to query the setting. @@ -991,27 +1004,84 @@ public class ConnectivitySettingsManager { } /** - * Get the list of apps(from {@link Settings}) that should go on cellular networks in preference + * Get the list of uids(from {@link Settings}) that should go on cellular networks in preference * even when higher-priority networks are connected. * * @param context The {@link Context} to query the setting. - * @return A list of apps that should go on cellular networks in preference even when + * @return A list of uids that should go on cellular networks in preference even when * higher-priority networks are connected or null if no setting value. */ - @Nullable - public static String getMobileDataPreferredApps(@NonNull Context context) { - return Settings.Secure.getString(context.getContentResolver(), MOBILE_DATA_PREFERRED_APPS); + @NonNull + public static Set<Integer> getMobileDataPreferredUids(@NonNull Context context) { + final String uidList = Settings.Secure.getString( + context.getContentResolver(), MOBILE_DATA_PREFERRED_UIDS); + final Set<Integer> uids = new ArraySet<>(); + if (TextUtils.isEmpty(uidList)) { + return uids; + } + for (String uid : uidList.split(";")) { + uids.add(Integer.valueOf(uid)); + } + return uids; } /** - * Set the list of apps(to {@link Settings}) that should go on cellular networks in preference + * Set the list of uids(to {@link Settings}) that should go on cellular networks in preference * even when higher-priority networks are connected. * * @param context The {@link Context} to set the setting. - * @param list A list of apps that should go on cellular networks in preference even when + * @param uidList A list of uids that should go on cellular networks in preference even when * higher-priority networks are connected. */ - public static void setMobileDataPreferredApps(@NonNull Context context, @Nullable String list) { - Settings.Secure.putString(context.getContentResolver(), MOBILE_DATA_PREFERRED_APPS, list); + public static void setMobileDataPreferredUids(@NonNull Context context, + @NonNull Set<Integer> uidList) { + final StringJoiner joiner = new StringJoiner(";"); + for (Integer uid : uidList) { + if (uid < 0 || UserHandle.getAppId(uid) > Process.LAST_APPLICATION_UID) { + throw new IllegalArgumentException("Invalid uid"); + } + joiner.add(uid.toString()); + } + Settings.Secure.putString( + context.getContentResolver(), MOBILE_DATA_PREFERRED_UIDS, joiner.toString()); + } + + /** + * Get the list of apps(from {@link Settings}) that is allowed on restricted networks. + * + * @param context The {@link Context} to query the setting. + * @return A list of apps that is allowed on restricted networks or null if no setting + * value. + */ + @NonNull + public static Set<String> getAppsAllowedOnRestrictedNetworks(@NonNull Context context) { + final String appList = Settings.Secure.getString( + context.getContentResolver(), APPS_ALLOWED_ON_RESTRICTED_NETWORKS); + if (TextUtils.isEmpty(appList)) { + return new ArraySet<>(); + } + return new ArraySet<>(appList.split(";")); + } + + /** + * Set the list of apps(from {@link Settings}) that is allowed on restricted networks. + * + * Note: Please refer to android developer guidelines for valid app(package name). + * https://developer.android.com/guide/topics/manifest/manifest-element.html#package + * + * @param context The {@link Context} to set the setting. + * @param list A list of apps that is allowed on restricted networks. + */ + public static void setAppsAllowedOnRestrictedNetworks(@NonNull Context context, + @NonNull Set<String> list) { + final StringJoiner joiner = new StringJoiner(";"); + for (String app : list) { + if (app == null || app.contains(";")) { + throw new IllegalArgumentException("Invalid app(package name)"); + } + joiner.add(app); + } + Settings.Secure.putString(context.getContentResolver(), APPS_ALLOWED_ON_RESTRICTED_NETWORKS, + joiner.toString()); } } diff --git a/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl b/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl index a7cb618f9790..d937c9cd78c0 100644 --- a/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl +++ b/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl @@ -23,6 +23,7 @@ import android.net.IConnectivityDiagnosticsCallback; import android.net.INetworkAgent; import android.net.IOnCompleteListener; import android.net.INetworkActivityListener; +import android.net.INetworkOfferCallback; import android.net.IQosCallback; import android.net.ISocketKeepaliveCallback; import android.net.LinkProperties; @@ -221,4 +222,8 @@ interface IConnectivityManager in IOnCompleteListener listener); int getRestrictBackgroundStatusByCaller(); + + void offerNetwork(in Messenger messenger, in NetworkScore score, + in NetworkCapabilities caps, in INetworkOfferCallback callback); + void unofferNetwork(in INetworkOfferCallback callback); } diff --git a/packages/Connectivity/framework/src/android/net/INetworkOfferCallback.aidl b/packages/Connectivity/framework/src/android/net/INetworkOfferCallback.aidl new file mode 100644 index 000000000000..67d2d405dbed --- /dev/null +++ b/packages/Connectivity/framework/src/android/net/INetworkOfferCallback.aidl @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.net.NetworkRequest; + +/** + * A callback registered with connectivity by network providers together with + * a NetworkOffer. + * + * When the offer is needed to satisfy some application or system component, + * connectivity will call onOfferNeeded on this callback. When this happens, + * the provider should try and bring up the network. + * + * When the offer is no longer needed, for example because the application has + * withdrawn the request or if the request is being satisfied by a network + * that this offer will never be able to beat, connectivity calls + * onOfferUnneeded. When this happens, the provider should stop trying to + * bring up the network, or tear it down if it has already been brought up. + * + * When NetworkProvider#offerNetwork is called, the provider can expect to + * immediately receive all requests that can be fulfilled by that offer and + * are not already satisfied by a better network. It is possible no such + * request is currently outstanding, because no requests have been made that + * can be satisfied by this offer, or because all such requests are already + * satisfied by a better network. + * onOfferNeeded can be called at any time after registration and until the + * offer is withdrawn with NetworkProvider#unofferNetwork is called. This + * typically happens when a new network request is filed by an application, + * or when the network satisfying a request disconnects and this offer now + * stands a chance to be the best network for it. + * + * @hide + */ +oneway interface INetworkOfferCallback { + /** + * Informs the registrant that the offer is needed to fulfill this request. + * @param networkRequest the request to satisfy + * @param providerId the ID of the provider currently satisfying + * this request, or NetworkProvider.ID_NONE if none. + */ + void onOfferNeeded(in NetworkRequest networkRequest, int providerId); + + /** + * Informs the registrant that the offer is no longer needed to fulfill this request. + */ + void onOfferUnneeded(in NetworkRequest networkRequest); +} diff --git a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java index 4a99d290f38c..90d821bd3b1e 100644 --- a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java +++ b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java @@ -139,19 +139,13 @@ public final class NetworkCapabilities implements Parcelable { */ private String mRequestorPackageName; - /** - * Indicates what fields should be redacted from this instance. - */ - private final @RedactionType long mRedactions; - public NetworkCapabilities() { - mRedactions = REDACT_ALL; clearAll(); mNetworkCapabilities = DEFAULT_CAPABILITIES; } public NetworkCapabilities(NetworkCapabilities nc) { - this(nc, REDACT_ALL); + this(nc, REDACT_NONE); } /** @@ -163,10 +157,12 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ public NetworkCapabilities(@Nullable NetworkCapabilities nc, @RedactionType long redactions) { - mRedactions = redactions; if (nc != null) { set(nc); } + if (mTransportInfo != null) { + mTransportInfo = nc.mTransportInfo.makeCopy(redactions); + } } /** @@ -175,14 +171,6 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ public void clearAll() { - // Ensures that the internal copies maintained by the connectivity stack does not set it to - // anything other than |REDACT_ALL|. - if (mRedactions != REDACT_ALL) { - // This is needed because the current redaction mechanism relies on redaction while - // parceling. - throw new UnsupportedOperationException( - "Cannot clear NetworkCapabilities when mRedactions is set"); - } mNetworkCapabilities = mTransportTypes = mForbiddenNetworkCapabilities = 0; mLinkUpBandwidthKbps = mLinkDownBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED; mNetworkSpecifier = null; @@ -211,7 +199,7 @@ public final class NetworkCapabilities implements Parcelable { mLinkDownBandwidthKbps = nc.mLinkDownBandwidthKbps; mNetworkSpecifier = nc.mNetworkSpecifier; if (nc.getTransportInfo() != null) { - setTransportInfo(nc.getTransportInfo().makeCopy(mRedactions)); + setTransportInfo(nc.getTransportInfo()); } else { setTransportInfo(null); } @@ -2411,6 +2399,11 @@ public final class NetworkCapabilities implements Parcelable { return mTransportInfo.getApplicableRedactions(); } + private NetworkCapabilities removeDefaultCapabilites() { + mNetworkCapabilities &= ~DEFAULT_CAPABILITIES; + return this; + } + /** * Builder class for NetworkCapabilities. * @@ -2447,6 +2440,16 @@ public final class NetworkCapabilities implements Parcelable { } /** + * Creates a new Builder without the default capabilities. + */ + @NonNull + public static Builder withoutDefaultCapabilities() { + final NetworkCapabilities nc = new NetworkCapabilities(); + nc.removeDefaultCapabilites(); + return new Builder(nc); + } + + /** * Adds the given transport type. * * Multiple transports may be added. Note that when searching for a network to satisfy a @@ -2507,17 +2510,6 @@ public final class NetworkCapabilities implements Parcelable { } /** - * Completely clears the contents of this object, removing even the capabilities that are - * set by default when the object is constructed. - * @return this builder - */ - @NonNull - public Builder clearAll() { - mCaps.clearAll(); - return this; - } - - /** * Sets the owner UID. * * The default value is {@link Process#INVALID_UID}. Pass this value to reset. diff --git a/packages/Connectivity/framework/src/android/net/NetworkProvider.java b/packages/Connectivity/framework/src/android/net/NetworkProvider.java index 14cb51c85d06..8f93047cf850 100644 --- a/packages/Connectivity/framework/src/android/net/NetworkProvider.java +++ b/packages/Connectivity/framework/src/android/net/NetworkProvider.java @@ -28,6 +28,11 @@ import android.os.Message; import android.os.Messenger; import android.util.Log; +import com.android.internal.annotations.GuardedBy; + +import java.util.ArrayList; +import java.util.concurrent.Executor; + /** * Base class for network providers such as telephony or Wi-Fi. NetworkProviders connect the device * to networks and makes them available to the core network stack by creating @@ -78,7 +83,9 @@ public class NetworkProvider { */ @SystemApi public NetworkProvider(@NonNull Context context, @NonNull Looper looper, @NonNull String name) { - Handler handler = new Handler(looper) { + // TODO (b/174636568) : this class should be able to cache an instance of + // ConnectivityManager so it doesn't have to fetch it again every time. + final Handler handler = new Handler(looper) { @Override public void handleMessage(Message m) { switch (m.what) { @@ -159,4 +166,148 @@ public class NetworkProvider { public void declareNetworkRequestUnfulfillable(@NonNull NetworkRequest request) { ConnectivityManager.from(mContext).declareNetworkRequestUnfulfillable(request); } + + /** @hide */ + // TODO : make @SystemApi when the impl is complete + public interface NetworkOfferCallback { + /** Called by the system when this offer is needed to satisfy some networking request. */ + void onOfferNeeded(@NonNull NetworkRequest request, int providerId); + /** Called by the system when this offer is no longer needed. */ + void onOfferUnneeded(@NonNull NetworkRequest request); + } + + private class NetworkOfferCallbackProxy extends INetworkOfferCallback.Stub { + @NonNull public final NetworkOfferCallback callback; + @NonNull private final Executor mExecutor; + + NetworkOfferCallbackProxy(@NonNull final NetworkOfferCallback callback, + @NonNull final Executor executor) { + this.callback = callback; + this.mExecutor = executor; + } + + @Override + public void onOfferNeeded(final @NonNull NetworkRequest request, + final int providerId) { + mExecutor.execute(() -> callback.onOfferNeeded(request, providerId)); + } + + @Override + public void onOfferUnneeded(final @NonNull NetworkRequest request) { + mExecutor.execute(() -> callback.onOfferUnneeded(request)); + } + } + + @GuardedBy("mProxies") + @NonNull private final ArrayList<NetworkOfferCallbackProxy> mProxies = new ArrayList<>(); + + // Returns the proxy associated with this callback, or null if none. + @Nullable + private NetworkOfferCallbackProxy findProxyForCallback(@NonNull final NetworkOfferCallback cb) { + synchronized (mProxies) { + for (final NetworkOfferCallbackProxy p : mProxies) { + if (p.callback == cb) return p; + } + } + return null; + } + + /** + * Register or update an offer for network with the passed caps and score. + * + * A NetworkProvider's job is to provide networks. This function is how a provider tells the + * connectivity stack what kind of network it may provide. The score and caps arguments act + * as filters that the connectivity stack uses to tell when the offer is necessary. When an + * offer might be advantageous over existing networks, the provider will receive a call to + * the associated callback's {@link NetworkOfferCallback#onOfferNeeded} method. The provider + * should then try to bring up this network. When an offer is no longer needed, the stack + * will inform the provider by calling {@link NetworkOfferCallback#onOfferUnneeded}. The + * provider should stop trying to bring up such a network, or disconnect it if it already has + * one. + * + * The stack determines what offers are needed according to what networks are currently + * available to the system, and what networking requests are made by applications. If an + * offer looks like it could be a better choice than any existing network for any particular + * request, that's when the stack decides the offer is needed. If the current networking + * requests are all satisfied by networks that this offer can't possibly be a better match + * for, that's when the offer is unneeded. An offer starts off as unneeded ; the provider + * should not try to bring up the network until {@link NetworkOfferCallback#onOfferNeeded} + * is called. + * + * Note that the offers are non-binding to the providers, in particular because providers + * often don't know if they will be able to bring up such a network at any given time. For + * example, no wireless network may be in range when the offer is needed. This is fine and + * expected ; the provider should simply continue to try to bring up the network and do so + * if/when it becomes possible. In the mean time, the stack will continue to satisfy requests + * with the best network currently available, or if none, keep the apps informed that no + * network can currently satisfy this request. When/if the provider can bring up the network, + * the connectivity stack will match it against requests, and inform interested apps of the + * availability of this network. This may, in turn, render the offer of some other provider + * unneeded if all requests it used to satisfy are now better served by this network. + * + * A network can become unneeded for a reason like the above : whether the provider managed + * to bring up the offered network after it became needed or not, some other provider may + * bring up a better network than this one, making this offer unneeded. A network may also + * become unneeded if the application making the request withdrew it (for example, after it + * is done transferring data, or if the user canceled an operation). + * + * The capabilities and score act as filters as to what requests the provider will see. + * They are not promises, but for best performance, the providers should strive to put + * as much known information as possible in the offer. For capabilities in particular, it + * should put all NetworkAgent-managed capabilities a network may have, even if it doesn't + * have them at first. This applies to INTERNET, for example ; if a provider thinks the + * network it can bring up for this offer may offer Internet access it should include the + * INTERNET bit. It's fine if the brought up network ends up not actually having INTERNET. + * + * TODO : in the future, to avoid possible infinite loops, there should be constraints on + * what can be put in capabilities of networks brought up for an offer. If a provider might + * bring up a network with or without INTERNET, then it should file two offers : this will + * let it know precisely what networks are needed, so it can avoid bringing up networks that + * won't actually satisfy requests and remove the risk for bring-up-bring-down loops. + * + * @hide + */ + // TODO : make @SystemApi when the impl is complete + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + public void offerNetwork(@NonNull final NetworkScore score, + @NonNull final NetworkCapabilities caps, @NonNull final Executor executor, + @NonNull final NetworkOfferCallback callback) { + NetworkOfferCallbackProxy proxy = null; + synchronized (mProxies) { + for (final NetworkOfferCallbackProxy existingProxy : mProxies) { + if (existingProxy.callback == callback) { + proxy = existingProxy; + break; + } + } + if (null == proxy) { + proxy = new NetworkOfferCallbackProxy(callback, executor); + mProxies.add(proxy); + } + } + mContext.getSystemService(ConnectivityManager.class).offerNetwork(this, score, caps, proxy); + } + + /** + * Withdraw a network offer previously made to the networking stack. + * + * If a provider can no longer provide a network they offered, it should call this method. + * An example of usage could be if the hardware necessary to bring up the network was turned + * off in UI by the user. Note that because offers are never binding, the provider might + * alternatively decide not to withdraw this offer and simply refuse to bring up the network + * even when it's needed. However, withdrawing the request is slightly more resource-efficient + * because the networking stack won't have to compare this offer to exiting networks to see + * if it could beat any of them, and may be advantageous to the provider's implementation that + * can rely on no longer receiving callbacks for a network that they can't bring up anyways. + * + * @hide + */ + // TODO : make @SystemApi when the impl is complete + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + public void unofferNetwork(final @NonNull NetworkOfferCallback callback) { + final NetworkOfferCallbackProxy proxy = findProxyForCallback(callback); + if (null == proxy) return; + mProxies.remove(proxy); + mContext.getSystemService(ConnectivityManager.class).unofferNetwork(proxy); + } } diff --git a/packages/Connectivity/framework/src/android/net/NetworkRequest.java b/packages/Connectivity/framework/src/android/net/NetworkRequest.java index dd88c5a5c94e..e6a96ef74869 100644 --- a/packages/Connectivity/framework/src/android/net/NetworkRequest.java +++ b/packages/Connectivity/framework/src/android/net/NetworkRequest.java @@ -200,8 +200,9 @@ public class NetworkRequest implements Parcelable { private final NetworkCapabilities mNetworkCapabilities; - // A boolean that represents the user modified NOT_VCN_MANAGED capability. - private boolean mModifiedNotVcnManaged = false; + // A boolean that represents whether the NOT_VCN_MANAGED capability should be deduced when + // the NetworkRequest object is built. + private boolean mShouldDeduceNotVcnManaged = true; /** * Default constructor for Builder. @@ -223,7 +224,7 @@ public class NetworkRequest implements Parcelable { // If the caller constructed the builder from a request, it means the user // might explicitly want the capabilities from the request. Thus, the NOT_VCN_MANAGED // capabilities should not be touched later. - mModifiedNotVcnManaged = true; + mShouldDeduceNotVcnManaged = false; } /** @@ -254,7 +255,7 @@ public class NetworkRequest implements Parcelable { public Builder addCapability(@NetworkCapabilities.NetCapability int capability) { mNetworkCapabilities.addCapability(capability); if (capability == NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) { - mModifiedNotVcnManaged = true; + mShouldDeduceNotVcnManaged = false; } return this; } @@ -268,7 +269,7 @@ public class NetworkRequest implements Parcelable { public Builder removeCapability(@NetworkCapabilities.NetCapability int capability) { mNetworkCapabilities.removeCapability(capability); if (capability == NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) { - mModifiedNotVcnManaged = true; + mShouldDeduceNotVcnManaged = false; } return this; } @@ -352,7 +353,7 @@ public class NetworkRequest implements Parcelable { mNetworkCapabilities.clearAll(); // If the caller explicitly clear all capabilities, the NOT_VCN_MANAGED capabilities // should not be add back later. - mModifiedNotVcnManaged = true; + mShouldDeduceNotVcnManaged = false; return this; } @@ -453,6 +454,9 @@ public class NetworkRequest implements Parcelable { throw new IllegalArgumentException("A MatchAllNetworkSpecifier is not permitted"); } mNetworkCapabilities.setNetworkSpecifier(networkSpecifier); + // Do not touch NOT_VCN_MANAGED if the caller needs to access to a very specific + // Network. + mShouldDeduceNotVcnManaged = false; return this; } @@ -486,12 +490,13 @@ public class NetworkRequest implements Parcelable { * {@link #VCN_SUPPORTED_CAPABILITIES}, add the NET_CAPABILITY_NOT_VCN_MANAGED to * allow the callers automatically utilize VCN networks if available. * 2. For the requests that explicitly add or remove NET_CAPABILITY_NOT_VCN_MANAGED, + * or has clear intention of tracking specific network, * do not alter them to allow user fire request that suits their need. * * @hide */ private void deduceNotVcnManagedCapability(final NetworkCapabilities nc) { - if (mModifiedNotVcnManaged) return; + if (!mShouldDeduceNotVcnManaged) return; for (final int cap : nc.getCapabilities()) { if (!VCN_SUPPORTED_CAPABILITIES.contains(cap)) return; } diff --git a/packages/Connectivity/framework/src/android/net/QosFilter.java b/packages/Connectivity/framework/src/android/net/QosFilter.java index ab55002e02b3..957c867f206d 100644 --- a/packages/Connectivity/framework/src/android/net/QosFilter.java +++ b/packages/Connectivity/framework/src/android/net/QosFilter.java @@ -71,5 +71,16 @@ public abstract class QosFilter { */ public abstract boolean matchesLocalAddress(@NonNull InetAddress address, int startPort, int endPort); + + /** + * Determines whether or not the parameters is a match for the filter. + * + * @param address the remote address + * @param startPort the start of the port range + * @param endPort the end of the port range + * @return whether the parameters match the remote address of the filter + */ + public abstract boolean matchesRemoteAddress(@NonNull InetAddress address, + int startPort, int endPort); } diff --git a/packages/Connectivity/framework/src/android/net/QosSocketFilter.java b/packages/Connectivity/framework/src/android/net/QosSocketFilter.java index 2080e68f5fba..69da7f440185 100644 --- a/packages/Connectivity/framework/src/android/net/QosSocketFilter.java +++ b/packages/Connectivity/framework/src/android/net/QosSocketFilter.java @@ -138,13 +138,26 @@ public class QosSocketFilter extends QosFilter { if (mQosSocketInfo.getLocalSocketAddress() == null) { return false; } + return matchesAddress(mQosSocketInfo.getLocalSocketAddress(), address, startPort, + endPort); + } - return matchesLocalAddress(mQosSocketInfo.getLocalSocketAddress(), address, startPort, + /** + * @inheritDoc + */ + @Override + public boolean matchesRemoteAddress(@NonNull final InetAddress address, final int startPort, + final int endPort) { + if (mQosSocketInfo.getRemoteSocketAddress() == null) { + return false; + } + return matchesAddress(mQosSocketInfo.getRemoteSocketAddress(), address, startPort, endPort); } /** - * Called from {@link QosSocketFilter#matchesLocalAddress(InetAddress, int, int)} with the + * Called from {@link QosSocketFilter#matchesLocalAddress(InetAddress, int, int)} + * and {@link QosSocketFilter#matchesRemoteAddress(InetAddress, int, int)} with the * filterSocketAddress coming from {@link QosSocketInfo#getLocalSocketAddress()}. * <p> * This method exists for testing purposes since {@link QosSocketInfo} couldn't be mocked @@ -156,7 +169,7 @@ public class QosSocketFilter extends QosFilter { * @param endPort the end of the port range to check */ @VisibleForTesting - public static boolean matchesLocalAddress(@NonNull final InetSocketAddress filterSocketAddress, + public static boolean matchesAddress(@NonNull final InetSocketAddress filterSocketAddress, @NonNull final InetAddress address, final int startPort, final int endPort) { return startPort <= filterSocketAddress.getPort() diff --git a/packages/Connectivity/framework/src/android/net/QosSocketInfo.java b/packages/Connectivity/framework/src/android/net/QosSocketInfo.java index 53d966937a70..a45d5075d6c7 100644 --- a/packages/Connectivity/framework/src/android/net/QosSocketInfo.java +++ b/packages/Connectivity/framework/src/android/net/QosSocketInfo.java @@ -17,6 +17,7 @@ package android.net; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.ParcelFileDescriptor; @@ -32,7 +33,8 @@ import java.util.Objects; /** * Used in conjunction with * {@link ConnectivityManager#registerQosCallback} - * in order to receive Qos Sessions related to the local address and port of a bound {@link Socket}. + * in order to receive Qos Sessions related to the local address and port of a bound {@link Socket} + * and/or remote address and port of a connected {@link Socket}. * * @hide */ @@ -48,6 +50,9 @@ public final class QosSocketInfo implements Parcelable { @NonNull private final InetSocketAddress mLocalSocketAddress; + @Nullable + private final InetSocketAddress mRemoteSocketAddress; + /** * The {@link Network} the socket is on. * @@ -81,6 +86,18 @@ public final class QosSocketInfo implements Parcelable { } /** + * The remote address of the socket passed into {@link QosSocketInfo(Network, Socket)}. + * The value does not reflect any changes that occur to the socket after it is first set + * in the constructor. + * + * @return the remote address of the socket if socket is connected, null otherwise + */ + @Nullable + public InetSocketAddress getRemoteSocketAddress() { + return mRemoteSocketAddress; + } + + /** * Creates a {@link QosSocketInfo} given a {@link Network} and bound {@link Socket}. The * {@link Socket} must remain bound in order to receive {@link QosSession}s. * @@ -95,6 +112,12 @@ public final class QosSocketInfo implements Parcelable { mParcelFileDescriptor = ParcelFileDescriptor.fromSocket(socket); mLocalSocketAddress = new InetSocketAddress(socket.getLocalAddress(), socket.getLocalPort()); + + if (socket.isConnected()) { + mRemoteSocketAddress = (InetSocketAddress) socket.getRemoteSocketAddress(); + } else { + mRemoteSocketAddress = null; + } } /* Parcelable methods */ @@ -102,11 +125,15 @@ public final class QosSocketInfo implements Parcelable { mNetwork = Objects.requireNonNull(Network.CREATOR.createFromParcel(in)); mParcelFileDescriptor = ParcelFileDescriptor.CREATOR.createFromParcel(in); - final int addressLength = in.readInt(); - mLocalSocketAddress = readSocketAddress(in, addressLength); + final int localAddressLength = in.readInt(); + mLocalSocketAddress = readSocketAddress(in, localAddressLength); + + final int remoteAddressLength = in.readInt(); + mRemoteSocketAddress = remoteAddressLength == 0 ? null + : readSocketAddress(in, remoteAddressLength); } - private InetSocketAddress readSocketAddress(final Parcel in, final int addressLength) { + private @NonNull InetSocketAddress readSocketAddress(final Parcel in, final int addressLength) { final byte[] address = new byte[addressLength]; in.readByteArray(address); final int port = in.readInt(); @@ -130,10 +157,19 @@ public final class QosSocketInfo implements Parcelable { mNetwork.writeToParcel(dest, 0); mParcelFileDescriptor.writeToParcel(dest, 0); - final byte[] address = mLocalSocketAddress.getAddress().getAddress(); - dest.writeInt(address.length); - dest.writeByteArray(address); + final byte[] localAddress = mLocalSocketAddress.getAddress().getAddress(); + dest.writeInt(localAddress.length); + dest.writeByteArray(localAddress); dest.writeInt(mLocalSocketAddress.getPort()); + + if (mRemoteSocketAddress == null) { + dest.writeInt(0); + } else { + final byte[] remoteAddress = mRemoteSocketAddress.getAddress().getAddress(); + dest.writeInt(remoteAddress.length); + dest.writeByteArray(remoteAddress); + dest.writeInt(mRemoteSocketAddress.getPort()); + } } @NonNull diff --git a/packages/Connectivity/framework/src/android/net/apf/ApfCapabilities.java b/packages/Connectivity/framework/src/android/net/apf/ApfCapabilities.java index 85b24713f256..663c1b3d2dc9 100644 --- a/packages/Connectivity/framework/src/android/net/apf/ApfCapabilities.java +++ b/packages/Connectivity/framework/src/android/net/apf/ApfCapabilities.java @@ -131,43 +131,21 @@ public final class ApfCapabilities implements Parcelable { * @return Whether the APF Filter in the device should filter out IEEE 802.3 Frames. */ public static boolean getApfDrop8023Frames() { - // TODO(b/183076074): remove reading resources from system resources + // TODO: deprecate/remove this method (now unused in the platform), as the resource was + // moved to NetworkStack. final Resources systemRes = Resources.getSystem(); final int id = systemRes.getIdentifier("config_apfDrop802_3Frames", "bool", "android"); return systemRes.getBoolean(id); } /** - * @return Whether the APF Filter in the device should filter out IEEE 802.3 Frames. - * @hide - */ - public static boolean getApfDrop8023Frames(@NonNull Context context) { - final ConnectivityResources res = getResources(context); - // TODO(b/183076074): use R.bool.config_apfDrop802_3Frames directly - final int id = res.get().getIdentifier("config_apfDrop802_3Frames", "bool", - res.getResourcesContext().getPackageName()); - return res.get().getBoolean(id); - } - - /** * @return An array of denylisted EtherType, packets with EtherTypes within it will be dropped. */ public static @NonNull int[] getApfEtherTypeBlackList() { - // TODO(b/183076074): remove reading resources from system resources + // TODO: deprecate/remove this method (now unused in the platform), as the resource was + // moved to NetworkStack. final Resources systemRes = Resources.getSystem(); final int id = systemRes.getIdentifier("config_apfEthTypeBlackList", "array", "android"); return systemRes.getIntArray(id); } - - /** - * @return An array of denylisted EtherType, packets with EtherTypes within it will be dropped. - * @hide - */ - public static @NonNull int[] getApfEtherTypeDenyList(@NonNull Context context) { - final ConnectivityResources res = getResources(context); - // TODO(b/183076074): use R.array.config_apfEthTypeDenyList directly - final int id = res.get().getIdentifier("config_apfEthTypeDenyList", "array", - res.getResourcesContext().getPackageName()); - return res.get().getIntArray(id); - } } diff --git a/packages/Connectivity/service/Android.bp b/packages/Connectivity/service/Android.bp index 1330e719e774..513de1956952 100644 --- a/packages/Connectivity/service/Android.bp +++ b/packages/Connectivity/service/Android.bp @@ -52,8 +52,8 @@ cc_library_shared { java_library { name: "service-connectivity-pre-jarjar", srcs: [ + "src/**/*.java", ":framework-connectivity-shared-srcs", - ":connectivity-service-srcs", ], libs: [ "android.net.ipsec.ike", diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values/config.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values/config.xml index 9ff2a2209e76..078a9eb58202 100644 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values/config.xml +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values/config.xml @@ -52,22 +52,6 @@ <item>12,60000</item><!-- mobile_cbs --> </string-array> - <!-- Whether the APF Filter in the device should filter out IEEE 802.3 Frames - Those frames are identified by the field Eth-type having values - less than 0x600 --> - <bool translatable="false" name="config_apfDrop802_3Frames">true</bool> - - <!-- An array of Denylisted EtherType, packets with EtherTypes within this array - will be dropped - TODO: need to put proper values, these are for testing purposes only --> - <integer-array translatable="false" name="config_apfEthTypeDenyList"> - <item>0x88A2</item> - <item>0x88A4</item> - <item>0x88B8</item> - <item>0x88CD</item> - <item>0x88E3</item> - </integer-array> - <!-- Default supported concurrent socket keepalive slots per transport type, used by ConnectivityManager.createSocketKeepalive() for calculating the number of keepalive offload slots that should be reserved for privileged access. This string array should be diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values/overlayable.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values/overlayable.xml index 717d08e13e44..f0f4ae8022e0 100644 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values/overlayable.xml +++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values/overlayable.xml @@ -21,8 +21,6 @@ <item type="string" name="config_networkCaptivePortalServerUrl"/> <item type="integer" name="config_networkTransitionTimeout"/> <item type="array" name="config_wakeonlan_supported_interfaces"/> - <item type="bool" name="config_apfDrop802_3Frames"/> - <item type="array" name="config_apfEthTypeDenyList"/> <item type="integer" name="config_networkMeteredMultipathPreference"/> <item type="array" name="config_networkSupportedKeepaliveCount"/> <item type="integer" name="config_networkAvoidBadWifi"/> diff --git a/services/core/java/com/android/server/ConnectivityService.java b/packages/Connectivity/service/src/com/android/server/ConnectivityService.java index 39a990cf5d73..842ad6222e40 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/packages/Connectivity/service/src/com/android/server/ConnectivityService.java @@ -15,7 +15,6 @@ */ package com.android.server; - import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE; import static android.content.pm.PackageManager.FEATURE_BLUETOOTH; import static android.content.pm.PackageManager.FEATURE_WATCH; @@ -125,6 +124,7 @@ import android.net.INetworkActivityListener; import android.net.INetworkAgent; import android.net.INetworkMonitor; import android.net.INetworkMonitorCallbacks; +import android.net.INetworkOfferCallback; import android.net.IOnCompleteListener; import android.net.IQosCallback; import android.net.ISocketKeepaliveCallback; @@ -234,6 +234,7 @@ import com.android.net.module.util.PermissionUtils; import com.android.server.connectivity.AutodestructReference; import com.android.server.connectivity.DnsManager; import com.android.server.connectivity.DnsManager.PrivateDnsValidationUpdate; +import com.android.server.connectivity.FullScore; import com.android.server.connectivity.KeepaliveTracker; import com.android.server.connectivity.LingerMonitor; import com.android.server.connectivity.MockableSystemProperties; @@ -241,6 +242,7 @@ import com.android.server.connectivity.NetworkAgentInfo; import com.android.server.connectivity.NetworkDiagnostics; import com.android.server.connectivity.NetworkNotificationManager; import com.android.server.connectivity.NetworkNotificationManager.NotificationType; +import com.android.server.connectivity.NetworkOffer; import com.android.server.connectivity.NetworkRanker; import com.android.server.connectivity.PermissionMonitor; import com.android.server.connectivity.ProfileNetworkPreferences; @@ -604,6 +606,18 @@ public class ConnectivityService extends IConnectivityManager.Stub private static final int EVENT_UID_BLOCKED_REASON_CHANGED = 51; /** + * Event to register a new network offer + * obj = NetworkOffer + */ + private static final int EVENT_REGISTER_NETWORK_OFFER = 52; + + /** + * Event to unregister an existing network offer + * obj = INetworkOfferCallback + */ + private static final int EVENT_UNREGISTER_NETWORK_OFFER = 53; + + /** * Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification * should be shown. */ @@ -1031,14 +1045,10 @@ public class ConnectivityService extends IConnectivityManager.Stub } else { // ConnectivityService publishes binder service using publishBinderService() with // no priority assigned will be treated as NORMAL priority. Dumpsys does not send - // "--dump-priority" arguments to the service. Thus, dump both NORMAL and HIGH to - // align the legacy design. + // "--dump-priority" arguments to the service. Thus, dump NORMAL only to align the + // legacy output for dumpsys connectivity. // TODO: Integrate into signal dump. dumpNormal(fd, pw, args); - pw.println(); - pw.println("DUMP OF SERVICE HIGH connectivity"); - pw.println(); - dumpHigh(fd, pw); } } } @@ -1380,7 +1390,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // arguments like the handler or the DnsResolver. // TODO : remove this ; it is probably better handled with a sentinel request. mNoServiceNetwork = new NetworkAgentInfo(null, - new Network(NO_SERVICE_NET_ID), + new Network(INetd.UNREACHABLE_NET_ID), new NetworkInfo(TYPE_NONE, 0, "", ""), new LinkProperties(), new NetworkCapabilities(), new NetworkScore.Builder().setLegacyInt(0).build(), mContext, null, @@ -4684,6 +4694,18 @@ public class ConnectivityService extends IConnectivityManager.Stub handleUnregisterNetworkProvider((Messenger) msg.obj); break; } + case EVENT_REGISTER_NETWORK_OFFER: { + handleRegisterNetworkOffer((NetworkOffer) msg.obj); + break; + } + case EVENT_UNREGISTER_NETWORK_OFFER: { + final NetworkOfferInfo offer = + findNetworkOfferInfoByCallback((INetworkOfferCallback) msg.obj); + if (null != offer) { + handleUnregisterNetworkOffer(offer); + } + break; + } case EVENT_REGISTER_NETWORK_AGENT: { final Pair<NetworkAgentInfo, INetworkMonitor> arg = (Pair<NetworkAgentInfo, INetworkMonitor>) msg.obj; @@ -6214,12 +6236,37 @@ public class ConnectivityService extends IConnectivityManager.Stub mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_PROVIDER, messenger)); } + @Override + public void offerNetwork(@NonNull final Messenger providerMessenger, + @NonNull final NetworkScore score, @NonNull final NetworkCapabilities caps, + @NonNull final INetworkOfferCallback callback) { + final NetworkOffer offer = new NetworkOffer( + FullScore.makeProspectiveScore(score, caps), caps, callback, providerMessenger); + mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_OFFER, offer)); + } + + @Override + public void unofferNetwork(@NonNull final INetworkOfferCallback callback) { + mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_OFFER, callback)); + } + private void handleUnregisterNetworkProvider(Messenger messenger) { NetworkProviderInfo npi = mNetworkProviderInfos.remove(messenger); if (npi == null) { loge("Failed to find Messenger in unregisterNetworkProvider"); return; } + // Unregister all the offers from this provider + final ArrayList<NetworkOfferInfo> toRemove = new ArrayList<>(); + for (final NetworkOfferInfo noi : mNetworkOffers) { + if (noi.offer.provider == messenger) { + // Can't call handleUnregisterNetworkOffer here because iteration is in progress + toRemove.add(noi); + } + } + for (NetworkOfferInfo noi : toRemove) { + handleUnregisterNetworkOffer(noi); + } if (DBG) log("unregisterNetworkProvider for " + npi.name); } @@ -6258,6 +6305,10 @@ public class ConnectivityService extends IConnectivityManager.Stub // (on the handler thread). private volatile List<UidRange> mVpnBlockedUidRanges = new ArrayList<>(); + // Must only be accessed on the handler thread + @NonNull + private final ArrayList<NetworkOfferInfo> mNetworkOffers = new ArrayList<>(); + @GuardedBy("mBlockedAppUids") private final HashSet<Integer> mBlockedAppUids = new HashSet<>(); @@ -6433,8 +6484,6 @@ public class ConnectivityService extends IConnectivityManager.Stub // Request used to optionally keep vehicle internal network always active private final NetworkRequest mDefaultVehicleRequest; - // TODO replace with INetd.UNREACHABLE_NET_ID when available. - private static final int NO_SERVICE_NET_ID = 52; // Sentinel NAI used to direct apps with default networks that should have no connectivity to a // network with no service. This NAI should never be matched against, nor should any public API // ever return the associated network. For this reason, this NAI is not in the list of available @@ -6582,6 +6631,65 @@ public class ConnectivityService extends IConnectivityManager.Stub updateUids(nai, null, nai.networkCapabilities); } + private class NetworkOfferInfo implements IBinder.DeathRecipient { + @NonNull public final NetworkOffer offer; + + NetworkOfferInfo(@NonNull final NetworkOffer offer) { + this.offer = offer; + } + + @Override + public void binderDied() { + mHandler.post(() -> handleUnregisterNetworkOffer(this)); + } + } + + /** + * Register or update a network offer. + * @param newOffer The new offer. If the callback member is the same as an existing + * offer, it is an update of that offer. + */ + private void handleRegisterNetworkOffer(@NonNull final NetworkOffer newOffer) { + ensureRunningOnConnectivityServiceThread(); + if (null == mNetworkProviderInfos.get(newOffer.provider)) { + // This may actually happen if a provider updates its score or registers and then + // immediately unregisters. The offer would still be in the handler queue, but the + // provider would have been removed. + if (DBG) log("Received offer from an unregistered provider"); + return; + } + + final NetworkOfferInfo existingOffer = findNetworkOfferInfoByCallback(newOffer.callback); + if (null != existingOffer) { + handleUnregisterNetworkOffer(existingOffer); + newOffer.migrateFrom(existingOffer.offer); + } + final NetworkOfferInfo noi = new NetworkOfferInfo(newOffer); + try { + noi.offer.provider.getBinder().linkToDeath(noi, 0 /* flags */); + } catch (RemoteException e) { + noi.binderDied(); + return; + } + mNetworkOffers.add(noi); + // TODO : send requests to the provider. + } + + private void handleUnregisterNetworkOffer(@NonNull final NetworkOfferInfo noi) { + ensureRunningOnConnectivityServiceThread(); + mNetworkOffers.remove(noi); + noi.offer.provider.getBinder().unlinkToDeath(noi, 0 /* flags */); + } + + @Nullable private NetworkOfferInfo findNetworkOfferInfoByCallback( + @NonNull final INetworkOfferCallback callback) { + ensureRunningOnConnectivityServiceThread(); + for (final NetworkOfferInfo noi : mNetworkOffers) { + if (noi.offer.callback.equals(callback)) return noi; + } + return null; + } + /** * Called when receiving LinkProperties directly from a NetworkAgent. * Stores into |nai| any data coming from the agent that might also be written to the network's @@ -8476,11 +8584,7 @@ public class ConnectivityService extends IConnectivityManager.Stub final UnderlyingNetworkInfo[] underlyingNetworkInfos = getAllVpnInfo(); try { final ArrayList<NetworkStateSnapshot> snapshots = new ArrayList<>(); - // TODO: Directly use NetworkStateSnapshot when feasible. - for (final NetworkState state : getAllNetworkState()) { - final NetworkStateSnapshot snapshot = new NetworkStateSnapshot(state.network, - state.networkCapabilities, state.linkProperties, state.subscriberId, - state.legacyNetworkType); + for (final NetworkStateSnapshot snapshot : getAllNetworkStateSnapshots()) { snapshots.add(snapshot); } mStatsManager.notifyNetworkStatus(getDefaultNetworks(), @@ -8564,28 +8668,32 @@ public class ConnectivityService extends IConnectivityManager.Stub public void factoryReset() { enforceSettingsPermission(); - if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) { - return; - } - + final int uid = mDeps.getCallingUid(); final long token = Binder.clearCallingIdentity(); try { + if (mUserManager.hasUserRestrictionForUser(UserManager.DISALLOW_NETWORK_RESET, + UserHandle.getUserHandleForUid(uid))) { + return; + } + final IpMemoryStore ipMemoryStore = IpMemoryStore.getMemoryStore(mContext); ipMemoryStore.factoryReset(); - } finally { - Binder.restoreCallingIdentity(token); - } - // Turn airplane mode off - setAirplaneMode(false); + // Turn airplane mode off + setAirplaneMode(false); - // restore private DNS settings to default mode (opportunistic) - if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_PRIVATE_DNS)) { - ConnectivitySettingsManager.setPrivateDnsMode(mContext, PRIVATE_DNS_MODE_OPPORTUNISTIC); - } + // restore private DNS settings to default mode (opportunistic) + if (!mUserManager.hasUserRestrictionForUser(UserManager.DISALLOW_CONFIG_PRIVATE_DNS, + UserHandle.getUserHandleForUid(uid))) { + ConnectivitySettingsManager.setPrivateDnsMode(mContext, + PRIVATE_DNS_MODE_OPPORTUNISTIC); + } - Settings.Global.putString(mContext.getContentResolver(), - ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, null); + Settings.Global.putString(mContext.getContentResolver(), + ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, null); + } finally { + Binder.restoreCallingIdentity(token); + } } @Override @@ -9041,7 +9149,8 @@ public class ConnectivityService extends IConnectivityManager.Stub } private NetworkCapabilities getNetworkCapabilitiesWithoutUids(@NonNull NetworkCapabilities nc) { - final NetworkCapabilities sanitized = new NetworkCapabilities(nc); + final NetworkCapabilities sanitized = new NetworkCapabilities(nc, + NetworkCapabilities.REDACT_ALL); sanitized.setUids(null); sanitized.setAdministratorUids(new int[0]); sanitized.setOwnerUid(Process.INVALID_UID); @@ -9066,36 +9175,49 @@ public class ConnectivityService extends IConnectivityManager.Stub return results; } - @VisibleForTesting - boolean checkConnectivityDiagnosticsPermissions( - int callbackPid, int callbackUid, NetworkAgentInfo nai, String callbackPackageName) { - if (checkNetworkStackPermission(callbackPid, callbackUid)) { - return true; - } - + private boolean hasLocationPermission(String packageName, int uid) { // LocationPermissionChecker#checkLocationPermission can throw SecurityException if the uid // and package name don't match. Throwing on the CS thread is not acceptable, so wrap the // call in a try-catch. try { if (!mLocationPermissionChecker.checkLocationPermission( - callbackPackageName, null /* featureId */, callbackUid, null /* message */)) { + packageName, null /* featureId */, uid, null /* message */)) { return false; } } catch (SecurityException e) { return false; } + return true; + } + + private boolean ownsVpnRunningOverNetwork(int uid, Network network) { for (NetworkAgentInfo virtual : mNetworkAgentInfos) { if (virtual.supportsUnderlyingNetworks() - && virtual.networkCapabilities.getOwnerUid() == callbackUid - && CollectionUtils.contains(virtual.declaredUnderlyingNetworks, nai.network)) { + && virtual.networkCapabilities.getOwnerUid() == uid + && CollectionUtils.contains(virtual.declaredUnderlyingNetworks, network)) { return true; } } + return false; + } + + @VisibleForTesting + boolean checkConnectivityDiagnosticsPermissions( + int callbackPid, int callbackUid, NetworkAgentInfo nai, String callbackPackageName) { + if (checkNetworkStackPermission(callbackPid, callbackUid)) { + return true; + } + // Administrator UIDs also contains the Owner UID final int[] administratorUids = nai.networkCapabilities.getAdministratorUids(); - return CollectionUtils.contains(administratorUids, callbackUid); + if (!CollectionUtils.contains(administratorUids, callbackUid) + && !ownsVpnRunningOverNetwork(callbackUid, nai.network)) { + return false; + } + + return hasLocationPermission(callbackPackageName, callbackUid); } @Override diff --git a/services/core/java/com/android/server/ConnectivityServiceInitializer.java b/packages/Connectivity/service/src/com/android/server/ConnectivityServiceInitializer.java index 2465479aadd8..2465479aadd8 100644 --- a/services/core/java/com/android/server/ConnectivityServiceInitializer.java +++ b/packages/Connectivity/service/src/com/android/server/ConnectivityServiceInitializer.java diff --git a/services/core/java/com/android/server/NetIdManager.java b/packages/Connectivity/service/src/com/android/server/NetIdManager.java index 61925c80a22b..61925c80a22b 100644 --- a/services/core/java/com/android/server/NetIdManager.java +++ b/packages/Connectivity/service/src/com/android/server/NetIdManager.java diff --git a/services/core/java/com/android/server/TestNetworkService.java b/packages/Connectivity/service/src/com/android/server/TestNetworkService.java index f5662772f59f..f5662772f59f 100644 --- a/services/core/java/com/android/server/TestNetworkService.java +++ b/packages/Connectivity/service/src/com/android/server/TestNetworkService.java diff --git a/services/core/java/com/android/server/connectivity/AutodestructReference.java b/packages/Connectivity/service/src/com/android/server/connectivity/AutodestructReference.java index 009a43e58285..009a43e58285 100644 --- a/services/core/java/com/android/server/connectivity/AutodestructReference.java +++ b/packages/Connectivity/service/src/com/android/server/connectivity/AutodestructReference.java diff --git a/services/core/java/com/android/server/connectivity/ConnectivityConstants.java b/packages/Connectivity/service/src/com/android/server/connectivity/ConnectivityConstants.java index 325a2cd7bd69..325a2cd7bd69 100644 --- a/services/core/java/com/android/server/connectivity/ConnectivityConstants.java +++ b/packages/Connectivity/service/src/com/android/server/connectivity/ConnectivityConstants.java diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/packages/Connectivity/service/src/com/android/server/connectivity/DnsManager.java index 05b12bad5589..05b12bad5589 100644 --- a/services/core/java/com/android/server/connectivity/DnsManager.java +++ b/packages/Connectivity/service/src/com/android/server/connectivity/DnsManager.java diff --git a/services/core/java/com/android/server/connectivity/FullScore.java b/packages/Connectivity/service/src/com/android/server/connectivity/FullScore.java index 028cfee36593..9326d692f6e4 100644 --- a/services/core/java/com/android/server/connectivity/FullScore.java +++ b/packages/Connectivity/service/src/com/android/server/connectivity/FullScore.java @@ -16,6 +16,7 @@ package com.android.server.connectivity; +import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; import static android.net.NetworkCapabilities.TRANSPORT_VPN; @@ -116,6 +117,33 @@ public class FullScore { } /** + * Given a score supplied by the NetworkAgent, produce a prospective score for an offer. + * + * NetworkOffers have score filters that are compared to the scores of actual networks + * to see if they could possibly beat the current satisfier. Some things the agent can't + * know in advance ; a good example is the validation bit – some networks will validate, + * others won't. For comparison purposes, assume the best, so all possibly beneficial + * networks will be brought up. + * + * @param score the score supplied by the agent for this offer + * @param caps the capabilities supplied by the agent for this offer + * @return a FullScore appropriate for comparing to actual network's scores. + */ + public static FullScore makeProspectiveScore(@NonNull final NetworkScore score, + @NonNull final NetworkCapabilities caps) { + // If the network offers Internet access, it may validate. + final boolean mayValidate = caps.hasCapability(NET_CAPABILITY_INTERNET); + // VPN transports are known in advance. + final boolean vpn = caps.hasTransport(TRANSPORT_VPN); + // The network hasn't been chosen by the user (yet, at least). + final boolean everUserSelected = false; + // Don't assume the user will accept unvalidated connectivity. + final boolean acceptUnvalidated = false; + return withPolicies(score.getLegacyInt(), mayValidate, vpn, everUserSelected, + acceptUnvalidated); + } + + /** * Return a new score given updated caps and config. * * @param caps the NetworkCapabilities of the network diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/packages/Connectivity/service/src/com/android/server/connectivity/KeepaliveTracker.java index acf39f05a541..acf39f05a541 100644 --- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java +++ b/packages/Connectivity/service/src/com/android/server/connectivity/KeepaliveTracker.java diff --git a/services/core/java/com/android/server/connectivity/LingerMonitor.java b/packages/Connectivity/service/src/com/android/server/connectivity/LingerMonitor.java index 032612c6f093..032612c6f093 100644 --- a/services/core/java/com/android/server/connectivity/LingerMonitor.java +++ b/packages/Connectivity/service/src/com/android/server/connectivity/LingerMonitor.java diff --git a/services/core/java/com/android/server/connectivity/MockableSystemProperties.java b/packages/Connectivity/service/src/com/android/server/connectivity/MockableSystemProperties.java index a25b89ac039a..a25b89ac039a 100644 --- a/services/core/java/com/android/server/connectivity/MockableSystemProperties.java +++ b/packages/Connectivity/service/src/com/android/server/connectivity/MockableSystemProperties.java diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/packages/Connectivity/service/src/com/android/server/connectivity/Nat464Xlat.java index c66a280f2b02..c66a280f2b02 100644 --- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java +++ b/packages/Connectivity/service/src/com/android/server/connectivity/Nat464Xlat.java diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/packages/Connectivity/service/src/com/android/server/connectivity/NetworkAgentInfo.java index ee32fbf00dfe..ee32fbf00dfe 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/packages/Connectivity/service/src/com/android/server/connectivity/NetworkAgentInfo.java diff --git a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java b/packages/Connectivity/service/src/com/android/server/connectivity/NetworkDiagnostics.java index 2e51be39bfae..2e51be39bfae 100644 --- a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java +++ b/packages/Connectivity/service/src/com/android/server/connectivity/NetworkDiagnostics.java diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/packages/Connectivity/service/src/com/android/server/connectivity/NetworkNotificationManager.java index 0c0d45995a2b..0c0d45995a2b 100644 --- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java +++ b/packages/Connectivity/service/src/com/android/server/connectivity/NetworkNotificationManager.java diff --git a/packages/Connectivity/service/src/com/android/server/connectivity/NetworkOffer.java b/packages/Connectivity/service/src/com/android/server/connectivity/NetworkOffer.java new file mode 100644 index 000000000000..fa2d465fff1d --- /dev/null +++ b/packages/Connectivity/service/src/com/android/server/connectivity/NetworkOffer.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.connectivity; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.net.INetworkOfferCallback; +import android.net.NetworkCapabilities; +import android.net.NetworkRequest; +import android.os.Messenger; + +import java.util.Objects; + + +/** + * Represents an offer made by a NetworkProvider to create a network if a need arises. + * + * This class contains the prospective score and capabilities of the network. The provider + * is not obligated to caps able to create a network satisfying this, nor to build a network + * with the exact score and/or capabilities passed ; after all, not all providers know in + * advance what a network will look like after it's connected. Instead, this is meant as a + * filter to limit requests sent to the provider by connectivity to those that this offer stands + * a chance to fulfill. + * + * @see NetworkProvider#offerNetwork. + * + * @hide + */ +public class NetworkOffer { + @NonNull public final FullScore score; + @NonNull public final NetworkCapabilities caps; + @NonNull public final INetworkOfferCallback callback; + @NonNull public final Messenger provider; + + private static NetworkCapabilities emptyCaps() { + final NetworkCapabilities nc = new NetworkCapabilities(); + return nc; + } + + // Ideally the caps argument would be non-null, but null has historically meant no filter + // and telephony passes null. Keep backward compatibility. + public NetworkOffer(@NonNull final FullScore score, + @Nullable final NetworkCapabilities caps, + @NonNull final INetworkOfferCallback callback, + @NonNull final Messenger provider) { + this.score = Objects.requireNonNull(score); + this.caps = null != caps ? caps : emptyCaps(); + this.callback = Objects.requireNonNull(callback); + this.provider = Objects.requireNonNull(provider); + } + + /** + * Migrate from, and take over, a previous offer. + * + * When an updated offer is sent from a provider, call this method on the new offer, passing + * the old one, to take over the state. + * + * @param previousOffer + */ + public void migrateFrom(@NonNull final NetworkOffer previousOffer) { + if (!callback.equals(previousOffer.callback)) { + throw new IllegalArgumentException("Can only migrate from a previous version of" + + " the same offer"); + } + } + + /** + * Returns whether an offer can satisfy a NetworkRequest, according to its capabilities. + * @param request The request to test against. + * @return Whether this offer can satisfy the request. + */ + public final boolean canSatisfy(@NonNull final NetworkRequest request) { + return request.networkCapabilities.satisfiedByNetworkCapabilities(caps); + } + + @Override + public String toString() { + return "NetworkOffer [ Score " + score + " ]"; + } +} diff --git a/services/core/java/com/android/server/connectivity/NetworkRanker.java b/packages/Connectivity/service/src/com/android/server/connectivity/NetworkRanker.java index d0aabf95d572..d0aabf95d572 100644 --- a/services/core/java/com/android/server/connectivity/NetworkRanker.java +++ b/packages/Connectivity/service/src/com/android/server/connectivity/NetworkRanker.java diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/packages/Connectivity/service/src/com/android/server/connectivity/PermissionMonitor.java index 506cadb2b1d2..673c80417b8d 100644 --- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java +++ b/packages/Connectivity/service/src/com/android/server/connectivity/PermissionMonitor.java @@ -24,6 +24,7 @@ import static android.Manifest.permission.UPDATE_DEVICE_STATS; import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; import static android.content.pm.PackageManager.GET_PERMISSIONS; import static android.content.pm.PackageManager.MATCH_ANY_USER; +import static android.net.ConnectivitySettingsManager.APPS_ALLOWED_ON_RESTRICTED_NETWORKS; import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; import static android.os.Process.INVALID_UID; import static android.os.Process.SYSTEM_UID; @@ -39,6 +40,8 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.database.ContentObserver; +import android.net.ConnectivitySettingsManager; import android.net.INetd; import android.net.UidRange; import android.net.Uri; @@ -48,7 +51,9 @@ import android.os.ServiceSpecificException; import android.os.SystemConfigManager; import android.os.UserHandle; import android.os.UserManager; +import android.provider.Settings; import android.system.OsConstants; +import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; import android.util.SparseIntArray; @@ -66,7 +71,6 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; - /** * A utility class to inform Netd of UID permisisons. * Does a mass update at boot and then monitors for app install/remove. @@ -105,6 +109,14 @@ public class PermissionMonitor { @GuardedBy("this") private final Set<Integer> mAllApps = new HashSet<>(); + // A set of apps which are allowed to use restricted networks. These apps can't hold the + // CONNECTIVITY_USE_RESTRICTED_NETWORKS permission because they can't be signature|privileged + // apps. However, these apps should still be able to use restricted networks under certain + // conditions (e.g. government app using emergency services). So grant netd system permission + // to uids whose package name is listed in APPS_ALLOWED_ON_RESTRICTED_NETWORKS setting. + @GuardedBy("this") + private final Set<String> mAppsAllowedOnRestrictedNetworks = new ArraySet<>(); + private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -135,6 +147,22 @@ public class PermissionMonitor { public int getDeviceFirstSdkInt() { return Build.VERSION.FIRST_SDK_INT; } + + /** + * Get apps allowed to use restricted networks via ConnectivitySettingsManager. + */ + public Set<String> getAppsAllowedOnRestrictedNetworks(@NonNull Context context) { + return ConnectivitySettingsManager.getAppsAllowedOnRestrictedNetworks(context); + } + + /** + * Register ContentObserver for given Uri. + */ + public void registerContentObserver(@NonNull Context context, @NonNull Uri uri, + boolean notifyForDescendants, @NonNull ContentObserver observer) { + context.getContentResolver().registerContentObserver( + uri, notifyForDescendants, observer); + } } public PermissionMonitor(@NonNull final Context context, @NonNull final INetd netd) { @@ -157,14 +185,31 @@ public class PermissionMonitor { public synchronized void startMonitoring() { log("Monitoring"); + final Context userAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */); final IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED); intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); intentFilter.addDataScheme("package"); - mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */).registerReceiver( + userAllContext.registerReceiver( mIntentReceiver, intentFilter, null /* broadcastPermission */, null /* scheduler */); + // Register APPS_ALLOWED_ON_RESTRICTED_NETWORKS setting observer + mDeps.registerContentObserver( + userAllContext, + Settings.Secure.getUriFor(APPS_ALLOWED_ON_RESTRICTED_NETWORKS), + false /* notifyForDescendants */, + new ContentObserver(null) { + @Override + public void onChange(boolean selfChange) { + onSettingChanged(); + } + }); + + // Read APPS_ALLOWED_ON_RESTRICTED_NETWORKS setting and update + // mAppsAllowedOnRestrictedNetworks. + updateAppsAllowedOnRestrictedNetworks(mDeps.getAppsAllowedOnRestrictedNetworks(mContext)); + List<PackageInfo> apps = mPackageManager.getInstalledPackages(GET_PERMISSIONS | MATCH_ANY_USER); if (apps == null) { @@ -220,11 +265,33 @@ public class PermissionMonitor { } @VisibleForTesting + void updateAppsAllowedOnRestrictedNetworks(final Set<String> apps) { + mAppsAllowedOnRestrictedNetworks.clear(); + mAppsAllowedOnRestrictedNetworks.addAll(apps); + } + + @VisibleForTesting static boolean isVendorApp(@NonNull ApplicationInfo appInfo) { return appInfo.isVendor() || appInfo.isOem() || appInfo.isProduct(); } @VisibleForTesting + boolean isCarryoverPackage(final ApplicationInfo appInfo) { + if (appInfo == null) return false; + return (appInfo.targetSdkVersion < VERSION_Q && isVendorApp(appInfo)) + // Backward compatibility for b/114245686, on devices that launched before Q daemons + // and apps running as the system UID are exempted from this check. + || (appInfo.uid == SYSTEM_UID && mDeps.getDeviceFirstSdkInt() < VERSION_Q); + } + + @VisibleForTesting + boolean isAppAllowedOnRestrictedNetworks(@NonNull final PackageInfo app) { + // Check whether package name is in allowed on restricted networks app list. If so, this app + // can have netd system permission. + return mAppsAllowedOnRestrictedNetworks.contains(app.packageName); + } + + @VisibleForTesting boolean hasPermission(@NonNull final PackageInfo app, @NonNull final String permission) { if (app.requestedPermissions == null || app.requestedPermissionsFlags == null) { return false; @@ -241,22 +308,10 @@ public class PermissionMonitor { @VisibleForTesting boolean hasRestrictedNetworkPermission(@NonNull final PackageInfo app) { - // TODO : remove this check in the future(b/31479477). All apps should just - // request the appropriate permission for their use case since android Q. - if (app.applicationInfo != null) { - // Backward compatibility for b/114245686, on devices that launched before Q daemons - // and apps running as the system UID are exempted from this check. - if (app.applicationInfo.uid == SYSTEM_UID && mDeps.getDeviceFirstSdkInt() < VERSION_Q) { - return true; - } - - if (app.applicationInfo.targetSdkVersion < VERSION_Q - && isVendorApp(app.applicationInfo)) { - return true; - } - } - - return hasPermission(app, PERMISSION_MAINLINE_NETWORK_STACK) + // TODO : remove carryover package check in the future(b/31479477). All apps should just + // request the appropriate permission for their use case since android Q. + return isCarryoverPackage(app.applicationInfo) || isAppAllowedOnRestrictedNetworks(app) + || hasPermission(app, PERMISSION_MAINLINE_NETWORK_STACK) || hasPermission(app, NETWORK_STACK) || hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS); } @@ -410,6 +465,20 @@ public class PermissionMonitor { mAllApps.add(UserHandle.getAppId(uid)); } + private Boolean highestUidNetworkPermission(int uid) { + Boolean permission = null; + final String[] packages = mPackageManager.getPackagesForUid(uid); + if (!CollectionUtils.isEmpty(packages)) { + for (String name : packages) { + permission = highestPermissionForUid(permission, name); + if (permission == SYSTEM) { + break; + } + } + } + return permission; + } + /** * Called when a package is removed. * @@ -440,19 +509,14 @@ public class PermissionMonitor { } Map<Integer, Boolean> apps = new HashMap<>(); - Boolean permission = null; - String[] packages = mPackageManager.getPackagesForUid(uid); - if (packages != null && packages.length > 0) { - for (String name : packages) { - permission = highestPermissionForUid(permission, name); - if (permission == SYSTEM) { - // An app with this UID still has the SYSTEM permission. - // Therefore, this UID must already have the SYSTEM permission. - // Nothing to do. - return; - } - } + final Boolean permission = highestUidNetworkPermission(uid); + if (permission == SYSTEM) { + // An app with this UID still has the SYSTEM permission. + // Therefore, this UID must already have the SYSTEM permission. + // Nothing to do. + return; } + if (permission == mApps.get(uid)) { // The permissions of this UID have not changed. Nothing to do. return; @@ -705,6 +769,38 @@ public class PermissionMonitor { return mVpnUidRanges.get(iface); } + private synchronized void onSettingChanged() { + // Step1. Update apps allowed to use restricted networks and compute the set of packages to + // update. + final Set<String> packagesToUpdate = new ArraySet<>(mAppsAllowedOnRestrictedNetworks); + updateAppsAllowedOnRestrictedNetworks(mDeps.getAppsAllowedOnRestrictedNetworks(mContext)); + packagesToUpdate.addAll(mAppsAllowedOnRestrictedNetworks); + + final Map<Integer, Boolean> updatedApps = new HashMap<>(); + final Map<Integer, Boolean> removedApps = new HashMap<>(); + + // Step2. For each package to update, find out its new permission. + for (String app : packagesToUpdate) { + final PackageInfo info = getPackageInfo(app); + if (info == null || info.applicationInfo == null) continue; + + final int uid = info.applicationInfo.uid; + final Boolean permission = highestUidNetworkPermission(uid); + + if (null == permission) { + removedApps.put(uid, NETWORK); // Doesn't matter which permission is set here. + mApps.remove(uid); + } else { + updatedApps.put(uid, permission); + mApps.put(uid, permission); + } + } + + // Step3. Update or revoke permission for uids with netd. + update(mUsers, updatedApps, true /* add */); + update(mUsers, removedApps, false /* add */); + } + /** Dump info to dumpsys */ public void dump(IndentingPrintWriter pw) { pw.println("Interface filtering rules:"); diff --git a/services/core/java/com/android/server/connectivity/ProfileNetworkPreferences.java b/packages/Connectivity/service/src/com/android/server/connectivity/ProfileNetworkPreferences.java index dd2815d9e2e3..dd2815d9e2e3 100644 --- a/services/core/java/com/android/server/connectivity/ProfileNetworkPreferences.java +++ b/packages/Connectivity/service/src/com/android/server/connectivity/ProfileNetworkPreferences.java diff --git a/services/core/java/com/android/server/connectivity/ProxyTracker.java b/packages/Connectivity/service/src/com/android/server/connectivity/ProxyTracker.java index f572b46a9b58..f572b46a9b58 100644 --- a/services/core/java/com/android/server/connectivity/ProxyTracker.java +++ b/packages/Connectivity/service/src/com/android/server/connectivity/ProxyTracker.java diff --git a/services/core/java/com/android/server/connectivity/QosCallbackAgentConnection.java b/packages/Connectivity/service/src/com/android/server/connectivity/QosCallbackAgentConnection.java index 534dbe7699a7..534dbe7699a7 100644 --- a/services/core/java/com/android/server/connectivity/QosCallbackAgentConnection.java +++ b/packages/Connectivity/service/src/com/android/server/connectivity/QosCallbackAgentConnection.java diff --git a/services/core/java/com/android/server/connectivity/QosCallbackTracker.java b/packages/Connectivity/service/src/com/android/server/connectivity/QosCallbackTracker.java index b6ab47b276e3..b6ab47b276e3 100644 --- a/services/core/java/com/android/server/connectivity/QosCallbackTracker.java +++ b/packages/Connectivity/service/src/com/android/server/connectivity/QosCallbackTracker.java diff --git a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java b/packages/Connectivity/service/src/com/android/server/connectivity/TcpKeepaliveController.java index c480594b8c60..c480594b8c60 100644 --- a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java +++ b/packages/Connectivity/service/src/com/android/server/connectivity/TcpKeepaliveController.java diff --git a/tests/net/OWNERS b/packages/Connectivity/tests/OWNERS index d3836d4c6c57..d3836d4c6c57 100644 --- a/tests/net/OWNERS +++ b/packages/Connectivity/tests/OWNERS diff --git a/tests/net/TEST_MAPPING b/packages/Connectivity/tests/TEST_MAPPING index 502f885ceb78..502f885ceb78 100644 --- a/tests/net/TEST_MAPPING +++ b/packages/Connectivity/tests/TEST_MAPPING diff --git a/tests/net/common/Android.bp b/packages/Connectivity/tests/common/Android.bp index babb81c5fa34..babb81c5fa34 100644 --- a/tests/net/common/Android.bp +++ b/packages/Connectivity/tests/common/Android.bp diff --git a/tests/net/common/java/ParseExceptionTest.kt b/packages/Connectivity/tests/common/java/ParseExceptionTest.kt index b702d61a9fe1..b702d61a9fe1 100644 --- a/tests/net/common/java/ParseExceptionTest.kt +++ b/packages/Connectivity/tests/common/java/ParseExceptionTest.kt diff --git a/tests/net/common/java/android/net/CaptivePortalDataTest.kt b/packages/Connectivity/tests/common/java/android/net/CaptivePortalDataTest.kt index 18a93319b271..18a93319b271 100644 --- a/tests/net/common/java/android/net/CaptivePortalDataTest.kt +++ b/packages/Connectivity/tests/common/java/android/net/CaptivePortalDataTest.kt diff --git a/tests/net/common/java/android/net/CaptivePortalTest.java b/packages/Connectivity/tests/common/java/android/net/CaptivePortalTest.java index 15d3398d43c0..15d3398d43c0 100644 --- a/tests/net/common/java/android/net/CaptivePortalTest.java +++ b/packages/Connectivity/tests/common/java/android/net/CaptivePortalTest.java diff --git a/tests/net/common/java/android/net/DependenciesTest.java b/packages/Connectivity/tests/common/java/android/net/DependenciesTest.java index ac1c28a45462..ac1c28a45462 100644 --- a/tests/net/common/java/android/net/DependenciesTest.java +++ b/packages/Connectivity/tests/common/java/android/net/DependenciesTest.java diff --git a/tests/net/common/java/android/net/DhcpInfoTest.java b/packages/Connectivity/tests/common/java/android/net/DhcpInfoTest.java index ab4726bab573..ab4726bab573 100644 --- a/tests/net/common/java/android/net/DhcpInfoTest.java +++ b/packages/Connectivity/tests/common/java/android/net/DhcpInfoTest.java diff --git a/tests/net/common/java/android/net/IpPrefixTest.java b/packages/Connectivity/tests/common/java/android/net/IpPrefixTest.java index 50ecb428359e..50ecb428359e 100644 --- a/tests/net/common/java/android/net/IpPrefixTest.java +++ b/packages/Connectivity/tests/common/java/android/net/IpPrefixTest.java diff --git a/tests/net/common/java/android/net/KeepalivePacketDataTest.kt b/packages/Connectivity/tests/common/java/android/net/KeepalivePacketDataTest.kt index f464ec6cf0e5..f464ec6cf0e5 100644 --- a/tests/net/common/java/android/net/KeepalivePacketDataTest.kt +++ b/packages/Connectivity/tests/common/java/android/net/KeepalivePacketDataTest.kt diff --git a/tests/net/common/java/android/net/LinkAddressTest.java b/packages/Connectivity/tests/common/java/android/net/LinkAddressTest.java index 2cf3cf9c11da..2cf3cf9c11da 100644 --- a/tests/net/common/java/android/net/LinkAddressTest.java +++ b/packages/Connectivity/tests/common/java/android/net/LinkAddressTest.java diff --git a/tests/net/common/java/android/net/LinkPropertiesTest.java b/packages/Connectivity/tests/common/java/android/net/LinkPropertiesTest.java index 550953d0612d..550953d0612d 100644 --- a/tests/net/common/java/android/net/LinkPropertiesTest.java +++ b/packages/Connectivity/tests/common/java/android/net/LinkPropertiesTest.java diff --git a/tests/net/common/java/android/net/MatchAllNetworkSpecifierTest.kt b/packages/Connectivity/tests/common/java/android/net/MatchAllNetworkSpecifierTest.kt index a5e44d59fcab..a5e44d59fcab 100644 --- a/tests/net/common/java/android/net/MatchAllNetworkSpecifierTest.kt +++ b/packages/Connectivity/tests/common/java/android/net/MatchAllNetworkSpecifierTest.kt diff --git a/tests/net/common/java/android/net/NattKeepalivePacketDataTest.kt b/packages/Connectivity/tests/common/java/android/net/NattKeepalivePacketDataTest.kt index 46f39dd016fd..46f39dd016fd 100644 --- a/tests/net/common/java/android/net/NattKeepalivePacketDataTest.kt +++ b/packages/Connectivity/tests/common/java/android/net/NattKeepalivePacketDataTest.kt diff --git a/tests/net/common/java/android/net/NetworkAgentConfigTest.kt b/packages/Connectivity/tests/common/java/android/net/NetworkAgentConfigTest.kt index 2b45b3d69ce9..2b45b3d69ce9 100644 --- a/tests/net/common/java/android/net/NetworkAgentConfigTest.kt +++ b/packages/Connectivity/tests/common/java/android/net/NetworkAgentConfigTest.kt diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/packages/Connectivity/tests/common/java/android/net/NetworkCapabilitiesTest.java index b178bad7123d..d74b802c8729 100644 --- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java +++ b/packages/Connectivity/tests/common/java/android/net/NetworkCapabilitiesTest.java @@ -340,7 +340,7 @@ public class NetworkCapabilitiesTest { private void testParcelSane(NetworkCapabilities cap) { if (isAtLeastS()) { - assertParcelSane(cap, 17); + assertParcelSane(cap, 16); } else if (isAtLeastR()) { assertParcelSane(cap, 15); } else { diff --git a/tests/net/common/java/android/net/NetworkProviderTest.kt b/packages/Connectivity/tests/common/java/android/net/NetworkProviderTest.kt index 340e6f963137..340e6f963137 100644 --- a/tests/net/common/java/android/net/NetworkProviderTest.kt +++ b/packages/Connectivity/tests/common/java/android/net/NetworkProviderTest.kt diff --git a/tests/net/common/java/android/net/NetworkSpecifierTest.kt b/packages/Connectivity/tests/common/java/android/net/NetworkSpecifierTest.kt index f3409f53596f..f3409f53596f 100644 --- a/tests/net/common/java/android/net/NetworkSpecifierTest.kt +++ b/packages/Connectivity/tests/common/java/android/net/NetworkSpecifierTest.kt diff --git a/tests/net/common/java/android/net/NetworkStackTest.java b/packages/Connectivity/tests/common/java/android/net/NetworkStackTest.java index f8f9c72374ad..f8f9c72374ad 100644 --- a/tests/net/common/java/android/net/NetworkStackTest.java +++ b/packages/Connectivity/tests/common/java/android/net/NetworkStackTest.java diff --git a/tests/net/common/java/android/net/NetworkStateSnapshotTest.kt b/packages/Connectivity/tests/common/java/android/net/NetworkStateSnapshotTest.kt index 0ca4d9551f39..0ca4d9551f39 100644 --- a/tests/net/common/java/android/net/NetworkStateSnapshotTest.kt +++ b/packages/Connectivity/tests/common/java/android/net/NetworkStateSnapshotTest.kt diff --git a/tests/net/common/java/android/net/NetworkTest.java b/packages/Connectivity/tests/common/java/android/net/NetworkTest.java index 11d44b86bc50..11d44b86bc50 100644 --- a/tests/net/common/java/android/net/NetworkTest.java +++ b/packages/Connectivity/tests/common/java/android/net/NetworkTest.java diff --git a/tests/net/common/java/android/net/OemNetworkPreferencesTest.java b/packages/Connectivity/tests/common/java/android/net/OemNetworkPreferencesTest.java index fd29a9539de8..fd29a9539de8 100644 --- a/tests/net/common/java/android/net/OemNetworkPreferencesTest.java +++ b/packages/Connectivity/tests/common/java/android/net/OemNetworkPreferencesTest.java diff --git a/tests/net/common/java/android/net/RouteInfoTest.java b/packages/Connectivity/tests/common/java/android/net/RouteInfoTest.java index 71689f919726..71689f919726 100644 --- a/tests/net/common/java/android/net/RouteInfoTest.java +++ b/packages/Connectivity/tests/common/java/android/net/RouteInfoTest.java diff --git a/tests/net/common/java/android/net/StaticIpConfigurationTest.java b/packages/Connectivity/tests/common/java/android/net/StaticIpConfigurationTest.java index b5f23bf19a3c..b5f23bf19a3c 100644 --- a/tests/net/common/java/android/net/StaticIpConfigurationTest.java +++ b/packages/Connectivity/tests/common/java/android/net/StaticIpConfigurationTest.java diff --git a/tests/net/common/java/android/net/TcpKeepalivePacketDataTest.kt b/packages/Connectivity/tests/common/java/android/net/TcpKeepalivePacketDataTest.kt index 7a18bb08faa8..7a18bb08faa8 100644 --- a/tests/net/common/java/android/net/TcpKeepalivePacketDataTest.kt +++ b/packages/Connectivity/tests/common/java/android/net/TcpKeepalivePacketDataTest.kt diff --git a/tests/net/common/java/android/net/UidRangeTest.java b/packages/Connectivity/tests/common/java/android/net/UidRangeTest.java index 1b1c95431d6f..1b1c95431d6f 100644 --- a/tests/net/common/java/android/net/UidRangeTest.java +++ b/packages/Connectivity/tests/common/java/android/net/UidRangeTest.java diff --git a/tests/net/common/java/android/net/UnderlyingNetworkInfoTest.kt b/packages/Connectivity/tests/common/java/android/net/UnderlyingNetworkInfoTest.kt index 87cfb345e5e0..f23ba26d0039 100644 --- a/tests/net/common/java/android/net/UnderlyingNetworkInfoTest.kt +++ b/packages/Connectivity/tests/common/java/android/net/UnderlyingNetworkInfoTest.kt @@ -36,15 +36,15 @@ class UnderlyingNetworkInfoTest { @Test fun testParcelUnparcel() { val testInfo = UnderlyingNetworkInfo(TEST_OWNER_UID, TEST_IFACE, TEST_IFACE_LIST) - assertEquals(TEST_OWNER_UID, testInfo.ownerUid) - assertEquals(TEST_IFACE, testInfo.iface) - assertEquals(TEST_IFACE_LIST, testInfo.underlyingIfaces) + assertEquals(TEST_OWNER_UID, testInfo.getOwnerUid()) + assertEquals(TEST_IFACE, testInfo.getInterface()) + assertEquals(TEST_IFACE_LIST, testInfo.getUnderlyingInterfaces()) assertParcelSane(testInfo, 3) val emptyInfo = UnderlyingNetworkInfo(0, String(), listOf()) - assertEquals(0, emptyInfo.ownerUid) - assertEquals(String(), emptyInfo.iface) - assertEquals(listOf(), emptyInfo.underlyingIfaces) + assertEquals(0, emptyInfo.getOwnerUid()) + assertEquals(String(), emptyInfo.getInterface()) + assertEquals(listOf(), emptyInfo.getUnderlyingInterfaces()) assertParcelSane(emptyInfo, 3) } }
\ No newline at end of file diff --git a/tests/net/common/java/android/net/apf/ApfCapabilitiesTest.java b/packages/Connectivity/tests/common/java/android/net/apf/ApfCapabilitiesTest.java index d50406fd3a1c..88996d925262 100644 --- a/tests/net/common/java/android/net/apf/ApfCapabilitiesTest.java +++ b/packages/Connectivity/tests/common/java/android/net/apf/ApfCapabilitiesTest.java @@ -18,6 +18,7 @@ package android.net.apf; import static com.android.testutils.ParcelUtils.assertParcelSane; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; @@ -25,12 +26,17 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import android.content.Context; +import android.os.Build; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.android.testutils.DevSdkIgnoreRule; +import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; + import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -39,6 +45,9 @@ import java.util.Arrays; @RunWith(AndroidJUnit4.class) @SmallTest public class ApfCapabilitiesTest { + @Rule + public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule(); + private Context mContext; @Before @@ -85,6 +94,17 @@ public class ApfCapabilitiesTest { assertEquals(shouldDrop8023Frames, actual); } + @Test @IgnoreUpTo(Build.VERSION_CODES.R) + public void testGetApfDrop8023Frames_S() { + // IpClient does not call getApfDrop8023Frames() since S, so any customization of the return + // value on S+ is a configuration error as it will not be used by IpClient. + assertTrue("android.R.bool.config_apfDrop802_3Frames has been modified to false, but " + + "starting from S its value is not used by IpClient. If the modification is " + + "intentional, use a runtime resource overlay for the NetworkStack package to " + + "overlay com.android.networkstack.R.bool.config_apfDrop802_3Frames instead.", + ApfCapabilities.getApfDrop8023Frames()); + } + @Test public void testGetApfEtherTypeBlackList() { // Get com.android.internal.R.array.config_apfEthTypeBlackList. The test cannot directly @@ -96,4 +116,17 @@ public class ApfCapabilitiesTest { assertNotNull(actual); assertTrue(Arrays.equals(blacklistedEtherTypeArray, actual)); } + + @Test @IgnoreUpTo(Build.VERSION_CODES.R) + public void testGetApfEtherTypeBlackList_S() { + // IpClient does not call getApfEtherTypeBlackList() since S, so any customization of the + // return value on S+ is a configuration error as it will not be used by IpClient. + assertArrayEquals("android.R.array.config_apfEthTypeBlackList has been modified, but " + + "starting from S its value is not used by IpClient. If the modification " + + "is intentional, use a runtime resource overlay for the NetworkStack " + + "package to overlay " + + "com.android.networkstack.R.array.config_apfEthTypeDenyList instead.", + new int[] { 0x88a2, 0x88a4, 0x88b8, 0x88cd, 0x88e3 }, + ApfCapabilities.getApfEtherTypeBlackList()); + } } diff --git a/tests/net/common/java/android/net/metrics/ApfProgramEventTest.kt b/packages/Connectivity/tests/common/java/android/net/metrics/ApfProgramEventTest.kt index 0b7b74097cc6..0b7b74097cc6 100644 --- a/tests/net/common/java/android/net/metrics/ApfProgramEventTest.kt +++ b/packages/Connectivity/tests/common/java/android/net/metrics/ApfProgramEventTest.kt diff --git a/tests/net/common/java/android/net/metrics/ApfStatsTest.kt b/packages/Connectivity/tests/common/java/android/net/metrics/ApfStatsTest.kt index 46a8c8e5b509..46a8c8e5b509 100644 --- a/tests/net/common/java/android/net/metrics/ApfStatsTest.kt +++ b/packages/Connectivity/tests/common/java/android/net/metrics/ApfStatsTest.kt diff --git a/tests/net/common/java/android/net/metrics/DhcpClientEventTest.kt b/packages/Connectivity/tests/common/java/android/net/metrics/DhcpClientEventTest.kt index 8d7a9c405024..8d7a9c405024 100644 --- a/tests/net/common/java/android/net/metrics/DhcpClientEventTest.kt +++ b/packages/Connectivity/tests/common/java/android/net/metrics/DhcpClientEventTest.kt diff --git a/tests/net/common/java/android/net/metrics/DhcpErrorEventTest.kt b/packages/Connectivity/tests/common/java/android/net/metrics/DhcpErrorEventTest.kt index 236f72eafbdc..236f72eafbdc 100644 --- a/tests/net/common/java/android/net/metrics/DhcpErrorEventTest.kt +++ b/packages/Connectivity/tests/common/java/android/net/metrics/DhcpErrorEventTest.kt diff --git a/tests/net/common/java/android/net/metrics/IpConnectivityLogTest.java b/packages/Connectivity/tests/common/java/android/net/metrics/IpConnectivityLogTest.java index d4780d3a5d7b..d4780d3a5d7b 100644 --- a/tests/net/common/java/android/net/metrics/IpConnectivityLogTest.java +++ b/packages/Connectivity/tests/common/java/android/net/metrics/IpConnectivityLogTest.java diff --git a/tests/net/common/java/android/net/metrics/IpManagerEventTest.kt b/packages/Connectivity/tests/common/java/android/net/metrics/IpManagerEventTest.kt index 64be50837fc9..64be50837fc9 100644 --- a/tests/net/common/java/android/net/metrics/IpManagerEventTest.kt +++ b/packages/Connectivity/tests/common/java/android/net/metrics/IpManagerEventTest.kt diff --git a/tests/net/common/java/android/net/metrics/IpReachabilityEventTest.kt b/packages/Connectivity/tests/common/java/android/net/metrics/IpReachabilityEventTest.kt index 55b5e492dd47..55b5e492dd47 100644 --- a/tests/net/common/java/android/net/metrics/IpReachabilityEventTest.kt +++ b/packages/Connectivity/tests/common/java/android/net/metrics/IpReachabilityEventTest.kt diff --git a/tests/net/common/java/android/net/metrics/NetworkEventTest.kt b/packages/Connectivity/tests/common/java/android/net/metrics/NetworkEventTest.kt index 41430b03a1eb..41430b03a1eb 100644 --- a/tests/net/common/java/android/net/metrics/NetworkEventTest.kt +++ b/packages/Connectivity/tests/common/java/android/net/metrics/NetworkEventTest.kt diff --git a/tests/net/common/java/android/net/metrics/RaEventTest.kt b/packages/Connectivity/tests/common/java/android/net/metrics/RaEventTest.kt index d9b720332fbe..d9b720332fbe 100644 --- a/tests/net/common/java/android/net/metrics/RaEventTest.kt +++ b/packages/Connectivity/tests/common/java/android/net/metrics/RaEventTest.kt diff --git a/tests/net/common/java/android/net/metrics/ValidationProbeEventTest.kt b/packages/Connectivity/tests/common/java/android/net/metrics/ValidationProbeEventTest.kt index 51c0d41bf4d5..51c0d41bf4d5 100644 --- a/tests/net/common/java/android/net/metrics/ValidationProbeEventTest.kt +++ b/packages/Connectivity/tests/common/java/android/net/metrics/ValidationProbeEventTest.kt diff --git a/tests/net/common/java/android/net/netstats/NetworkStatsApiTest.kt b/packages/Connectivity/tests/common/java/android/net/netstats/NetworkStatsApiTest.kt index 7b22e45db90a..7b22e45db90a 100644 --- a/tests/net/common/java/android/net/netstats/NetworkStatsApiTest.kt +++ b/packages/Connectivity/tests/common/java/android/net/netstats/NetworkStatsApiTest.kt diff --git a/tests/net/common/java/android/net/util/SocketUtilsTest.kt b/packages/Connectivity/tests/common/java/android/net/util/SocketUtilsTest.kt index aaf97f36889b..aaf97f36889b 100644 --- a/tests/net/common/java/android/net/util/SocketUtilsTest.kt +++ b/packages/Connectivity/tests/common/java/android/net/util/SocketUtilsTest.kt diff --git a/tests/net/deflake/Android.bp b/packages/Connectivity/tests/deflake/Android.bp index 58ece37ef647..58ece37ef647 100644 --- a/tests/net/deflake/Android.bp +++ b/packages/Connectivity/tests/deflake/Android.bp diff --git a/tests/net/deflake/src/com/android/server/net/FrameworksNetDeflakeTest.kt b/packages/Connectivity/tests/deflake/src/com/android/server/net/FrameworksNetDeflakeTest.kt index 62855255fec2..62855255fec2 100644 --- a/tests/net/deflake/src/com/android/server/net/FrameworksNetDeflakeTest.kt +++ b/packages/Connectivity/tests/deflake/src/com/android/server/net/FrameworksNetDeflakeTest.kt diff --git a/tests/net/integration/Android.bp b/packages/Connectivity/tests/integration/Android.bp index 56f9df78c83e..56f9df78c83e 100644 --- a/tests/net/integration/Android.bp +++ b/packages/Connectivity/tests/integration/Android.bp diff --git a/tests/net/integration/AndroidManifest.xml b/packages/Connectivity/tests/integration/AndroidManifest.xml index 2e1368935759..2e1368935759 100644 --- a/tests/net/integration/AndroidManifest.xml +++ b/packages/Connectivity/tests/integration/AndroidManifest.xml diff --git a/tests/net/integration/res/values/config.xml b/packages/Connectivity/tests/integration/res/values/config.xml index 2c8046ffd781..2c8046ffd781 100644 --- a/tests/net/integration/res/values/config.xml +++ b/packages/Connectivity/tests/integration/res/values/config.xml diff --git a/tests/net/integration/src/android/net/TestNetworkStackClient.kt b/packages/Connectivity/tests/integration/src/android/net/TestNetworkStackClient.kt index 01eb514a1c81..01eb514a1c81 100644 --- a/tests/net/integration/src/android/net/TestNetworkStackClient.kt +++ b/packages/Connectivity/tests/integration/src/android/net/TestNetworkStackClient.kt diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt b/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt index b6e42743e2a3..b6e42743e2a3 100644 --- a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt +++ b/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/HttpResponse.aidl b/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/HttpResponse.aidl index 9a2bcfea7641..9a2bcfea7641 100644 --- a/tests/net/integration/src/com/android/server/net/integrationtests/HttpResponse.aidl +++ b/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/HttpResponse.aidl diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/HttpResponse.kt b/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/HttpResponse.kt index e2063138fef1..e2063138fef1 100644 --- a/tests/net/integration/src/com/android/server/net/integrationtests/HttpResponse.kt +++ b/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/HttpResponse.kt diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/INetworkStackInstrumentation.aidl b/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/INetworkStackInstrumentation.aidl index efc58add9cf5..efc58add9cf5 100644 --- a/tests/net/integration/src/com/android/server/net/integrationtests/INetworkStackInstrumentation.aidl +++ b/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/INetworkStackInstrumentation.aidl diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/NetworkStackInstrumentationService.kt b/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/NetworkStackInstrumentationService.kt index e807952cec11..e807952cec11 100644 --- a/tests/net/integration/src/com/android/server/net/integrationtests/NetworkStackInstrumentationService.kt +++ b/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/NetworkStackInstrumentationService.kt diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt b/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt index eff66584d6c1..eff66584d6c1 100644 --- a/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt +++ b/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt diff --git a/tests/net/integration/util/com/android/server/ConnectivityServiceTestUtils.kt b/packages/Connectivity/tests/integration/util/com/android/server/ConnectivityServiceTestUtils.kt index 165fd3728281..165fd3728281 100644 --- a/tests/net/integration/util/com/android/server/ConnectivityServiceTestUtils.kt +++ b/packages/Connectivity/tests/integration/util/com/android/server/ConnectivityServiceTestUtils.kt diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/packages/Connectivity/tests/integration/util/com/android/server/NetworkAgentWrapper.java index e80955014fe7..e80955014fe7 100644 --- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java +++ b/packages/Connectivity/tests/integration/util/com/android/server/NetworkAgentWrapper.java diff --git a/tests/net/integration/util/com/android/server/TestNetIdManager.kt b/packages/Connectivity/tests/integration/util/com/android/server/TestNetIdManager.kt index 938a694e8ba9..938a694e8ba9 100644 --- a/tests/net/integration/util/com/android/server/TestNetIdManager.kt +++ b/packages/Connectivity/tests/integration/util/com/android/server/TestNetIdManager.kt diff --git a/tests/net/smoketest/Android.bp b/packages/Connectivity/tests/smoketest/Android.bp index 1535f3ddcb38..1535f3ddcb38 100644 --- a/tests/net/smoketest/Android.bp +++ b/packages/Connectivity/tests/smoketest/Android.bp diff --git a/tests/net/smoketest/AndroidManifest.xml b/packages/Connectivity/tests/smoketest/AndroidManifest.xml index f1b9febb9f57..f1b9febb9f57 100644 --- a/tests/net/smoketest/AndroidManifest.xml +++ b/packages/Connectivity/tests/smoketest/AndroidManifest.xml diff --git a/tests/net/smoketest/AndroidTest.xml b/packages/Connectivity/tests/smoketest/AndroidTest.xml index ac366e4ac544..ac366e4ac544 100644 --- a/tests/net/smoketest/AndroidTest.xml +++ b/packages/Connectivity/tests/smoketest/AndroidTest.xml diff --git a/tests/net/smoketest/java/SmokeTest.java b/packages/Connectivity/tests/smoketest/java/SmokeTest.java index 7d6655fde15e..7d6655fde15e 100644 --- a/tests/net/smoketest/java/SmokeTest.java +++ b/packages/Connectivity/tests/smoketest/java/SmokeTest.java diff --git a/tests/net/Android.bp b/packages/Connectivity/tests/unit/Android.bp index e1a424f214a5..e1a424f214a5 100644 --- a/tests/net/Android.bp +++ b/packages/Connectivity/tests/unit/Android.bp diff --git a/tests/net/AndroidManifest.xml b/packages/Connectivity/tests/unit/AndroidManifest.xml index d08b2f8d40dd..d08b2f8d40dd 100644 --- a/tests/net/AndroidManifest.xml +++ b/packages/Connectivity/tests/unit/AndroidManifest.xml diff --git a/tests/net/AndroidTest.xml b/packages/Connectivity/tests/unit/AndroidTest.xml index 939ae493b280..939ae493b280 100644 --- a/tests/net/AndroidTest.xml +++ b/packages/Connectivity/tests/unit/AndroidTest.xml diff --git a/tests/net/jarjar-rules.txt b/packages/Connectivity/tests/unit/jarjar-rules.txt index ca8867206dda..ca8867206dda 100644 --- a/tests/net/jarjar-rules.txt +++ b/packages/Connectivity/tests/unit/jarjar-rules.txt diff --git a/tests/net/java/android/app/usage/NetworkStatsManagerTest.java b/packages/Connectivity/tests/unit/java/android/app/usage/NetworkStatsManagerTest.java index 899295a019d2..899295a019d2 100644 --- a/tests/net/java/android/app/usage/NetworkStatsManagerTest.java +++ b/packages/Connectivity/tests/unit/java/android/app/usage/NetworkStatsManagerTest.java diff --git a/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java b/packages/Connectivity/tests/unit/java/android/net/ConnectivityDiagnosticsManagerTest.java index 06e9405a6a79..06e9405a6a79 100644 --- a/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java +++ b/packages/Connectivity/tests/unit/java/android/net/ConnectivityDiagnosticsManagerTest.java diff --git a/tests/net/java/android/net/ConnectivityManagerTest.java b/packages/Connectivity/tests/unit/java/android/net/ConnectivityManagerTest.java index 591e0cc3504e..591e0cc3504e 100644 --- a/tests/net/java/android/net/ConnectivityManagerTest.java +++ b/packages/Connectivity/tests/unit/java/android/net/ConnectivityManagerTest.java diff --git a/tests/net/java/android/net/Ikev2VpnProfileTest.java b/packages/Connectivity/tests/unit/java/android/net/Ikev2VpnProfileTest.java index 1abd39a32bdf..1abd39a32bdf 100644 --- a/tests/net/java/android/net/Ikev2VpnProfileTest.java +++ b/packages/Connectivity/tests/unit/java/android/net/Ikev2VpnProfileTest.java diff --git a/tests/net/java/android/net/IpMemoryStoreTest.java b/packages/Connectivity/tests/unit/java/android/net/IpMemoryStoreTest.java index 0b13800bc5c9..0b13800bc5c9 100644 --- a/tests/net/java/android/net/IpMemoryStoreTest.java +++ b/packages/Connectivity/tests/unit/java/android/net/IpMemoryStoreTest.java diff --git a/tests/net/java/android/net/IpSecAlgorithmTest.java b/packages/Connectivity/tests/unit/java/android/net/IpSecAlgorithmTest.java index 3a8d6004f66f..3a8d6004f66f 100644 --- a/tests/net/java/android/net/IpSecAlgorithmTest.java +++ b/packages/Connectivity/tests/unit/java/android/net/IpSecAlgorithmTest.java diff --git a/tests/net/java/android/net/IpSecConfigTest.java b/packages/Connectivity/tests/unit/java/android/net/IpSecConfigTest.java index 25e225ef303a..25e225ef303a 100644 --- a/tests/net/java/android/net/IpSecConfigTest.java +++ b/packages/Connectivity/tests/unit/java/android/net/IpSecConfigTest.java diff --git a/tests/net/java/android/net/IpSecManagerTest.java b/packages/Connectivity/tests/unit/java/android/net/IpSecManagerTest.java index 730e2d56bd78..730e2d56bd78 100644 --- a/tests/net/java/android/net/IpSecManagerTest.java +++ b/packages/Connectivity/tests/unit/java/android/net/IpSecManagerTest.java diff --git a/tests/net/java/android/net/IpSecTransformTest.java b/packages/Connectivity/tests/unit/java/android/net/IpSecTransformTest.java index 424f23dbbaf6..424f23dbbaf6 100644 --- a/tests/net/java/android/net/IpSecTransformTest.java +++ b/packages/Connectivity/tests/unit/java/android/net/IpSecTransformTest.java diff --git a/tests/net/java/android/net/KeepalivePacketDataUtilTest.java b/packages/Connectivity/tests/unit/java/android/net/KeepalivePacketDataUtilTest.java index fc739fbfac61..fc739fbfac61 100644 --- a/tests/net/java/android/net/KeepalivePacketDataUtilTest.java +++ b/packages/Connectivity/tests/unit/java/android/net/KeepalivePacketDataUtilTest.java diff --git a/tests/net/java/android/net/MacAddressTest.java b/packages/Connectivity/tests/unit/java/android/net/MacAddressTest.java index 6de31f6b4be1..6de31f6b4be1 100644 --- a/tests/net/java/android/net/MacAddressTest.java +++ b/packages/Connectivity/tests/unit/java/android/net/MacAddressTest.java diff --git a/tests/net/java/android/net/NetworkIdentityTest.kt b/packages/Connectivity/tests/unit/java/android/net/NetworkIdentityTest.kt index eb2b85c14578..eb2b85c14578 100644 --- a/tests/net/java/android/net/NetworkIdentityTest.kt +++ b/packages/Connectivity/tests/unit/java/android/net/NetworkIdentityTest.kt diff --git a/tests/net/java/android/net/NetworkStatsHistoryTest.java b/packages/Connectivity/tests/unit/java/android/net/NetworkStatsHistoryTest.java index 13558cd51c28..13558cd51c28 100644 --- a/tests/net/java/android/net/NetworkStatsHistoryTest.java +++ b/packages/Connectivity/tests/unit/java/android/net/NetworkStatsHistoryTest.java diff --git a/tests/net/java/android/net/NetworkStatsTest.java b/packages/Connectivity/tests/unit/java/android/net/NetworkStatsTest.java index 23d5a7e5d5f8..23d5a7e5d5f8 100644 --- a/tests/net/java/android/net/NetworkStatsTest.java +++ b/packages/Connectivity/tests/unit/java/android/net/NetworkStatsTest.java diff --git a/tests/net/java/android/net/NetworkTemplateTest.kt b/packages/Connectivity/tests/unit/java/android/net/NetworkTemplateTest.kt index ab6b2f409867..cb39a0c819f2 100644 --- a/tests/net/java/android/net/NetworkTemplateTest.kt +++ b/packages/Connectivity/tests/unit/java/android/net/NetworkTemplateTest.kt @@ -40,7 +40,7 @@ import android.net.NetworkTemplate.OEM_MANAGED_YES import android.net.NetworkTemplate.SUBSCRIBER_ID_MATCH_RULE_EXACT import android.net.NetworkTemplate.buildTemplateWifi import android.net.NetworkTemplate.buildTemplateWifiWildcard -import android.net.NetworkTemplate.buildTemplateCarrier +import android.net.NetworkTemplate.buildTemplateCarrierMetered import android.net.NetworkTemplate.buildTemplateMobileWithRatType import android.telephony.TelephonyManager import com.android.testutils.assertParcelSane @@ -73,11 +73,12 @@ class NetworkTemplateTest { type: Int, subscriberId: String? = null, ssid: String? = null, - oemManaged: Int = OEM_NONE + oemManaged: Int = OEM_NONE, + metered: Boolean = true ): NetworkStateSnapshot { val lp = LinkProperties() val caps = NetworkCapabilities().apply { - setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, false) + setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, !metered) setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true) setSSID(ssid) setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID, @@ -167,25 +168,38 @@ class NetworkTemplateTest { } @Test - fun testCarrierMatches() { - val templateCarrierImsi1 = buildTemplateCarrier(TEST_IMSI1) - - val identMobile1 = buildNetworkIdentity(mockContext, buildMobileNetworkState(TEST_IMSI1), - false, TelephonyManager.NETWORK_TYPE_UMTS) - val identMobile2 = buildNetworkIdentity(mockContext, buildMobileNetworkState(TEST_IMSI2), - false, TelephonyManager.NETWORK_TYPE_UMTS) - val identWifiSsid1 = buildNetworkIdentity( - mockContext, buildWifiNetworkState(null, TEST_SSID1), true, 0) - val identCarrierWifiImsi1 = buildNetworkIdentity( - mockContext, buildWifiNetworkState(TEST_IMSI1, TEST_SSID1), true, 0) - val identCarrierWifiImsi2 = buildNetworkIdentity( - mockContext, buildWifiNetworkState(TEST_IMSI2, TEST_SSID1), true, 0) - - templateCarrierImsi1.assertMatches(identCarrierWifiImsi1) - templateCarrierImsi1.assertDoesNotMatch(identCarrierWifiImsi2) - templateCarrierImsi1.assertDoesNotMatch(identWifiSsid1) - templateCarrierImsi1.assertMatches(identMobile1) - templateCarrierImsi1.assertDoesNotMatch(identMobile2) + fun testCarrierMeteredMatches() { + val templateCarrierImsi1Metered = buildTemplateCarrierMetered(TEST_IMSI1) + + val mobileImsi1 = buildMobileNetworkState(TEST_IMSI1) + val mobileImsi1Unmetered = buildNetworkState(TYPE_MOBILE, TEST_IMSI1, null /* ssid */, + OEM_NONE, false /* metered */) + val mobileImsi2 = buildMobileNetworkState(TEST_IMSI2) + val wifiSsid1 = buildWifiNetworkState(null /* subscriberId */, TEST_SSID1) + val wifiImsi1Ssid1 = buildWifiNetworkState(TEST_IMSI1, TEST_SSID1) + val wifiImsi1Ssid1Unmetered = buildNetworkState(TYPE_WIFI, TEST_IMSI1, TEST_SSID1, + OEM_NONE, false /* metered */) + + val identMobileImsi1Metered = buildNetworkIdentity(mockContext, + mobileImsi1, false /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS) + val identMobileImsi1Unmetered = buildNetworkIdentity(mockContext, + mobileImsi1Unmetered, false /* defaultNetwork */, + TelephonyManager.NETWORK_TYPE_UMTS) + val identMobileImsi2Metered = buildNetworkIdentity(mockContext, + mobileImsi2, false /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS) + val identWifiSsid1Metered = buildNetworkIdentity( + mockContext, wifiSsid1, true /* defaultNetwork */, 0 /* subType */) + val identCarrierWifiImsi1Metered = buildNetworkIdentity( + mockContext, wifiImsi1Ssid1, true /* defaultNetwork */, 0 /* subType */) + val identCarrierWifiImsi1NonMetered = buildNetworkIdentity(mockContext, + wifiImsi1Ssid1Unmetered, true /* defaultNetwork */, 0 /* subType */) + + templateCarrierImsi1Metered.assertMatches(identMobileImsi1Metered) + templateCarrierImsi1Metered.assertDoesNotMatch(identMobileImsi1Unmetered) + templateCarrierImsi1Metered.assertDoesNotMatch(identMobileImsi2Metered) + templateCarrierImsi1Metered.assertDoesNotMatch(identWifiSsid1Metered) + templateCarrierImsi1Metered.assertMatches(identCarrierWifiImsi1Metered) + templateCarrierImsi1Metered.assertDoesNotMatch(identCarrierWifiImsi1NonMetered) } @Test diff --git a/tests/net/java/android/net/NetworkUtilsTest.java b/packages/Connectivity/tests/unit/java/android/net/NetworkUtilsTest.java index 7748288aeb05..7748288aeb05 100644 --- a/tests/net/java/android/net/NetworkUtilsTest.java +++ b/packages/Connectivity/tests/unit/java/android/net/NetworkUtilsTest.java diff --git a/tests/net/java/android/net/QosSocketFilterTest.java b/packages/Connectivity/tests/unit/java/android/net/QosSocketFilterTest.java index ad58960eaadd..40f8f1b8d09a 100644 --- a/tests/net/java/android/net/QosSocketFilterTest.java +++ b/packages/Connectivity/tests/unit/java/android/net/QosSocketFilterTest.java @@ -35,7 +35,7 @@ public class QosSocketFilterTest { public void testPortExactMatch() { final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4"); final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.4"); - assertTrue(QosSocketFilter.matchesLocalAddress( + assertTrue(QosSocketFilter.matchesAddress( new InetSocketAddress(addressA, 10), addressB, 10, 10)); } @@ -44,7 +44,7 @@ public class QosSocketFilterTest { public void testPortLessThanStart() { final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4"); final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.4"); - assertFalse(QosSocketFilter.matchesLocalAddress( + assertFalse(QosSocketFilter.matchesAddress( new InetSocketAddress(addressA, 8), addressB, 10, 10)); } @@ -52,7 +52,7 @@ public class QosSocketFilterTest { public void testPortGreaterThanEnd() { final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4"); final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.4"); - assertFalse(QosSocketFilter.matchesLocalAddress( + assertFalse(QosSocketFilter.matchesAddress( new InetSocketAddress(addressA, 18), addressB, 10, 10)); } @@ -60,7 +60,7 @@ public class QosSocketFilterTest { public void testPortBetweenStartAndEnd() { final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4"); final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.4"); - assertTrue(QosSocketFilter.matchesLocalAddress( + assertTrue(QosSocketFilter.matchesAddress( new InetSocketAddress(addressA, 10), addressB, 8, 18)); } @@ -68,7 +68,7 @@ public class QosSocketFilterTest { public void testAddressesDontMatch() { final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4"); final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.5"); - assertFalse(QosSocketFilter.matchesLocalAddress( + assertFalse(QosSocketFilter.matchesAddress( new InetSocketAddress(addressA, 10), addressB, 10, 10)); } } diff --git a/tests/net/java/android/net/TelephonyNetworkSpecifierTest.java b/packages/Connectivity/tests/unit/java/android/net/TelephonyNetworkSpecifierTest.java index 6714bb1abbe6..6714bb1abbe6 100644 --- a/tests/net/java/android/net/TelephonyNetworkSpecifierTest.java +++ b/packages/Connectivity/tests/unit/java/android/net/TelephonyNetworkSpecifierTest.java diff --git a/tests/net/java/android/net/VpnManagerTest.java b/packages/Connectivity/tests/unit/java/android/net/VpnManagerTest.java index 3135062138ac..3135062138ac 100644 --- a/tests/net/java/android/net/VpnManagerTest.java +++ b/packages/Connectivity/tests/unit/java/android/net/VpnManagerTest.java diff --git a/tests/net/java/android/net/VpnTransportInfoTest.java b/packages/Connectivity/tests/unit/java/android/net/VpnTransportInfoTest.java index ccaa5cf7e9f7..ccaa5cf7e9f7 100644 --- a/tests/net/java/android/net/VpnTransportInfoTest.java +++ b/packages/Connectivity/tests/unit/java/android/net/VpnTransportInfoTest.java diff --git a/tests/net/java/android/net/ipmemorystore/ParcelableTests.java b/packages/Connectivity/tests/unit/java/android/net/ipmemorystore/ParcelableTests.java index 603c87519532..603c87519532 100644 --- a/tests/net/java/android/net/ipmemorystore/ParcelableTests.java +++ b/packages/Connectivity/tests/unit/java/android/net/ipmemorystore/ParcelableTests.java diff --git a/tests/net/java/android/net/nsd/NsdManagerTest.java b/packages/Connectivity/tests/unit/java/android/net/nsd/NsdManagerTest.java index b0a9b8a55322..b0a9b8a55322 100644 --- a/tests/net/java/android/net/nsd/NsdManagerTest.java +++ b/packages/Connectivity/tests/unit/java/android/net/nsd/NsdManagerTest.java diff --git a/tests/net/java/android/net/nsd/NsdServiceInfoTest.java b/packages/Connectivity/tests/unit/java/android/net/nsd/NsdServiceInfoTest.java index 94dfc7515c67..94dfc7515c67 100644 --- a/tests/net/java/android/net/nsd/NsdServiceInfoTest.java +++ b/packages/Connectivity/tests/unit/java/android/net/nsd/NsdServiceInfoTest.java diff --git a/tests/net/java/android/net/util/DnsUtilsTest.java b/packages/Connectivity/tests/unit/java/android/net/util/DnsUtilsTest.java index b626db8d89e4..b626db8d89e4 100644 --- a/tests/net/java/android/net/util/DnsUtilsTest.java +++ b/packages/Connectivity/tests/unit/java/android/net/util/DnsUtilsTest.java diff --git a/tests/net/java/android/net/util/KeepaliveUtilsTest.kt b/packages/Connectivity/tests/unit/java/android/net/util/KeepaliveUtilsTest.kt index b62bdbcfb5eb..b62bdbcfb5eb 100644 --- a/tests/net/java/android/net/util/KeepaliveUtilsTest.kt +++ b/packages/Connectivity/tests/unit/java/android/net/util/KeepaliveUtilsTest.kt diff --git a/tests/net/java/android/net/util/MultinetworkPolicyTrackerTest.kt b/packages/Connectivity/tests/unit/java/android/net/util/MultinetworkPolicyTrackerTest.kt index 25aa6266577e..25aa6266577e 100644 --- a/tests/net/java/android/net/util/MultinetworkPolicyTrackerTest.kt +++ b/packages/Connectivity/tests/unit/java/android/net/util/MultinetworkPolicyTrackerTest.kt diff --git a/tests/net/java/com/android/internal/net/NetworkUtilsInternalTest.java b/packages/Connectivity/tests/unit/java/com/android/internal/net/NetworkUtilsInternalTest.java index 3cfecd552967..3cfecd552967 100644 --- a/tests/net/java/com/android/internal/net/NetworkUtilsInternalTest.java +++ b/packages/Connectivity/tests/unit/java/com/android/internal/net/NetworkUtilsInternalTest.java diff --git a/tests/net/java/com/android/internal/net/VpnProfileTest.java b/packages/Connectivity/tests/unit/java/com/android/internal/net/VpnProfileTest.java index 46597d19ef1b..46597d19ef1b 100644 --- a/tests/net/java/com/android/internal/net/VpnProfileTest.java +++ b/packages/Connectivity/tests/unit/java/com/android/internal/net/VpnProfileTest.java diff --git a/tests/net/java/com/android/internal/util/BitUtilsTest.java b/packages/Connectivity/tests/unit/java/com/android/internal/util/BitUtilsTest.java index d2fbdce9771a..d2fbdce9771a 100644 --- a/tests/net/java/com/android/internal/util/BitUtilsTest.java +++ b/packages/Connectivity/tests/unit/java/com/android/internal/util/BitUtilsTest.java diff --git a/tests/net/java/com/android/internal/util/RingBufferTest.java b/packages/Connectivity/tests/unit/java/com/android/internal/util/RingBufferTest.java index d06095a690cf..d06095a690cf 100644 --- a/tests/net/java/com/android/internal/util/RingBufferTest.java +++ b/packages/Connectivity/tests/unit/java/com/android/internal/util/RingBufferTest.java diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/packages/Connectivity/tests/unit/java/com/android/server/ConnectivityServiceTest.java index ab5079820611..1b4f8364b5be 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/packages/Connectivity/tests/unit/java/com/android/server/ConnectivityServiceTest.java @@ -19,6 +19,7 @@ package com.android.server; import static android.Manifest.permission.CHANGE_NETWORK_STATE; import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS; import static android.Manifest.permission.DUMP; +import static android.Manifest.permission.LOCAL_MAC_ADDRESS; import static android.Manifest.permission.NETWORK_FACTORY; import static android.Manifest.permission.NETWORK_SETTINGS; import static android.app.PendingIntent.FLAG_IMMUTABLE; @@ -126,6 +127,7 @@ import static com.android.testutils.MiscAsserts.assertContainsExactly; import static com.android.testutils.MiscAsserts.assertEmpty; import static com.android.testutils.MiscAsserts.assertLength; import static com.android.testutils.MiscAsserts.assertRunsInAtMost; +import static com.android.testutils.MiscAsserts.assertSameElements; import static com.android.testutils.MiscAsserts.assertThrows; import static org.junit.Assert.assertEquals; @@ -5805,20 +5807,8 @@ public class ConnectivityServiceTest { mCm.unregisterNetworkCallback(networkCallback); } - private <T> void assertSameElementsNoDuplicates(T[] expected, T[] actual) { - // Easier to implement than a proper "assertSameElements" method that also correctly deals - // with duplicates. - final String msg = Arrays.toString(expected) + " != " + Arrays.toString(actual); - assertEquals(msg, expected.length, actual.length); - Set expectedSet = new ArraySet<>(Arrays.asList(expected)); - assertEquals("expected contains duplicates", expectedSet.size(), expected.length); - // actual cannot have duplicates because it's the same length and has the same elements. - Set actualSet = new ArraySet<>(Arrays.asList(actual)); - assertEquals(expectedSet, actualSet); - } - - private void expectNetworkStatus(Network[] networks, String defaultIface, - Integer vpnUid, String vpnIfname, String[] underlyingIfaces) throws Exception { + private void expectNotifyNetworkStatus(List<Network> networks, String defaultIface, + Integer vpnUid, String vpnIfname, List<String> underlyingIfaces) throws Exception { ArgumentCaptor<List<Network>> networksCaptor = ArgumentCaptor.forClass(List.class); ArgumentCaptor<List<UnderlyingNetworkInfo>> vpnInfosCaptor = ArgumentCaptor.forClass(List.class); @@ -5826,26 +5816,24 @@ public class ConnectivityServiceTest { verify(mStatsManager, atLeastOnce()).notifyNetworkStatus(networksCaptor.capture(), any(List.class), eq(defaultIface), vpnInfosCaptor.capture()); - assertSameElementsNoDuplicates(networksCaptor.getValue().toArray(), networks); + assertSameElements(networksCaptor.getValue(), networks); - UnderlyingNetworkInfo[] infos = - vpnInfosCaptor.getValue().toArray(new UnderlyingNetworkInfo[0]); + List<UnderlyingNetworkInfo> infos = vpnInfosCaptor.getValue(); if (vpnUid != null) { - assertEquals("Should have exactly one VPN:", 1, infos.length); - UnderlyingNetworkInfo info = infos[0]; + assertEquals("Should have exactly one VPN:", 1, infos.size()); + UnderlyingNetworkInfo info = infos.get(0); assertEquals("Unexpected VPN owner:", (int) vpnUid, info.getOwnerUid()); - assertEquals("Unexpected VPN interface:", vpnIfname, info.getIface()); - assertSameElementsNoDuplicates(underlyingIfaces, - info.getUnderlyingIfaces().toArray(new String[0])); + assertEquals("Unexpected VPN interface:", vpnIfname, info.getInterface()); + assertSameElements(underlyingIfaces, info.getUnderlyingInterfaces()); } else { - assertEquals(0, infos.length); + assertEquals(0, infos.size()); return; } } - private void expectNetworkStatus( - Network[] networks, String defaultIface) throws Exception { - expectNetworkStatus(networks, defaultIface, null, null, new String[0]); + private void expectNotifyNetworkStatus( + List<Network> networks, String defaultIface) throws Exception { + expectNotifyNetworkStatus(networks, defaultIface, null, null, List.of()); } @Test @@ -5853,8 +5841,8 @@ public class ConnectivityServiceTest { mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - final Network[] onlyCell = new Network[] {mCellNetworkAgent.getNetwork()}; - final Network[] onlyWifi = new Network[] {mWiFiNetworkAgent.getNetwork()}; + final List<Network> onlyCell = List.of(mCellNetworkAgent.getNetwork()); + final List<Network> onlyWifi = List.of(mWiFiNetworkAgent.getNetwork()); LinkProperties cellLp = new LinkProperties(); cellLp.setInterfaceName(MOBILE_IFNAME); @@ -5865,7 +5853,7 @@ public class ConnectivityServiceTest { mCellNetworkAgent.connect(false); mCellNetworkAgent.sendLinkProperties(cellLp); waitForIdle(); - expectNetworkStatus(onlyCell, MOBILE_IFNAME); + expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME); reset(mStatsManager); // Default network switch should update ifaces. @@ -5873,37 +5861,37 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent.sendLinkProperties(wifiLp); waitForIdle(); assertEquals(wifiLp, mService.getActiveLinkProperties()); - expectNetworkStatus(onlyWifi, WIFI_IFNAME); + expectNotifyNetworkStatus(onlyWifi, WIFI_IFNAME); reset(mStatsManager); // Disconnect should update ifaces. mWiFiNetworkAgent.disconnect(); waitForIdle(); - expectNetworkStatus(onlyCell, MOBILE_IFNAME); + expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME); reset(mStatsManager); // Metered change should update ifaces mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); waitForIdle(); - expectNetworkStatus(onlyCell, MOBILE_IFNAME); + expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME); reset(mStatsManager); mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); waitForIdle(); - expectNetworkStatus(onlyCell, MOBILE_IFNAME); + expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME); reset(mStatsManager); // Temp metered change shouldn't update ifaces mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED); waitForIdle(); - verify(mStatsManager, never()).notifyNetworkStatus(eq(Arrays.asList(onlyCell)), + verify(mStatsManager, never()).notifyNetworkStatus(eq(onlyCell), any(List.class), eq(MOBILE_IFNAME), any(List.class)); reset(mStatsManager); // Roaming change should update ifaces mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); waitForIdle(); - expectNetworkStatus(onlyCell, MOBILE_IFNAME); + expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME); reset(mStatsManager); // Test VPNs. @@ -5913,29 +5901,29 @@ public class ConnectivityServiceTest { mMockVpn.establishForMyUid(lp); assertUidRangesUpdatedForMyUid(true); - final Network[] cellAndVpn = new Network[] { - mCellNetworkAgent.getNetwork(), mMockVpn.getNetwork()}; + final List<Network> cellAndVpn = + List.of(mCellNetworkAgent.getNetwork(), mMockVpn.getNetwork()); // A VPN with default (null) underlying networks sets the underlying network's interfaces... - expectNetworkStatus(cellAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME, - new String[]{MOBILE_IFNAME}); + expectNotifyNetworkStatus(cellAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME, + List.of(MOBILE_IFNAME)); // ...and updates them as the default network switches. mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(false); mWiFiNetworkAgent.sendLinkProperties(wifiLp); final Network[] onlyNull = new Network[]{null}; - final Network[] wifiAndVpn = new Network[] { - mWiFiNetworkAgent.getNetwork(), mMockVpn.getNetwork()}; - final Network[] cellAndWifi = new Network[] { - mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork()}; - final Network[] cellNullAndWifi = new Network[] { - mCellNetworkAgent.getNetwork(), null, mWiFiNetworkAgent.getNetwork()}; + final List<Network> wifiAndVpn = + List.of(mWiFiNetworkAgent.getNetwork(), mMockVpn.getNetwork()); + final List<Network> cellAndWifi = + List.of(mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork()); + final Network[] cellNullAndWifi = + new Network[]{mCellNetworkAgent.getNetwork(), null, mWiFiNetworkAgent.getNetwork()}; waitForIdle(); assertEquals(wifiLp, mService.getActiveLinkProperties()); - expectNetworkStatus(wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME, - new String[]{WIFI_IFNAME}); + expectNotifyNetworkStatus(wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME, + List.of(WIFI_IFNAME)); reset(mStatsManager); // A VPN that sets its underlying networks passes the underlying interfaces, and influences @@ -5944,23 +5932,23 @@ public class ConnectivityServiceTest { // MOBILE_IFNAME even though the default network is wifi. // TODO: fix this to pass in the actual default network interface. Whether or not the VPN // applies to the system server UID should not have any bearing on network stats. - mMockVpn.setUnderlyingNetworks(onlyCell); + mMockVpn.setUnderlyingNetworks(onlyCell.toArray(new Network[0])); waitForIdle(); - expectNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME, - new String[]{MOBILE_IFNAME}); + expectNotifyNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME, + List.of(MOBILE_IFNAME)); reset(mStatsManager); - mMockVpn.setUnderlyingNetworks(cellAndWifi); + mMockVpn.setUnderlyingNetworks(cellAndWifi.toArray(new Network[0])); waitForIdle(); - expectNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME, - new String[]{MOBILE_IFNAME, WIFI_IFNAME}); + expectNotifyNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME, + List.of(MOBILE_IFNAME, WIFI_IFNAME)); reset(mStatsManager); // Null underlying networks are ignored. mMockVpn.setUnderlyingNetworks(cellNullAndWifi); waitForIdle(); - expectNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME, - new String[]{MOBILE_IFNAME, WIFI_IFNAME}); + expectNotifyNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME, + List.of(MOBILE_IFNAME, WIFI_IFNAME)); reset(mStatsManager); // If an underlying network disconnects, that interface should no longer be underlying. @@ -5973,15 +5961,15 @@ public class ConnectivityServiceTest { mCellNetworkAgent.disconnect(); waitForIdle(); assertNull(mService.getLinkProperties(mCellNetworkAgent.getNetwork())); - expectNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME, - new String[]{MOBILE_IFNAME, WIFI_IFNAME}); + expectNotifyNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME, + List.of(MOBILE_IFNAME, WIFI_IFNAME)); // Confirm that we never tell NetworkStatsService that cell is no longer the underlying // network for the VPN... verify(mStatsManager, never()).notifyNetworkStatus(any(List.class), any(List.class), any() /* anyString() doesn't match null */, - argThat(infos -> infos.get(0).getUnderlyingIfaces().size() == 1 - && WIFI_IFNAME.equals(infos.get(0).getUnderlyingIfaces().get(0)))); + argThat(infos -> infos.get(0).getUnderlyingInterfaces().size() == 1 + && WIFI_IFNAME.equals(infos.get(0).getUnderlyingInterfaces().get(0)))); verifyNoMoreInteractions(mStatsManager); reset(mStatsManager); @@ -5994,8 +5982,8 @@ public class ConnectivityServiceTest { waitForIdle(); verify(mStatsManager).notifyNetworkStatus(any(List.class), any(List.class), any() /* anyString() doesn't match null */, - argThat(vpnInfos -> vpnInfos.get(0).getUnderlyingIfaces().size() == 1 - && WIFI_IFNAME.equals(vpnInfos.get(0).getUnderlyingIfaces().get(0)))); + argThat(vpnInfos -> vpnInfos.get(0).getUnderlyingInterfaces().size() == 1 + && WIFI_IFNAME.equals(vpnInfos.get(0).getUnderlyingInterfaces().get(0)))); mEthernetNetworkAgent.disconnect(); waitForIdle(); reset(mStatsManager); @@ -6008,26 +5996,26 @@ public class ConnectivityServiceTest { // Also, for the same reason as above, the active interface passed in is null. mMockVpn.setUnderlyingNetworks(new Network[0]); waitForIdle(); - expectNetworkStatus(wifiAndVpn, null); + expectNotifyNetworkStatus(wifiAndVpn, null); reset(mStatsManager); // Specifying only a null underlying network is the same as no networks. mMockVpn.setUnderlyingNetworks(onlyNull); waitForIdle(); - expectNetworkStatus(wifiAndVpn, null); + expectNotifyNetworkStatus(wifiAndVpn, null); reset(mStatsManager); // Specifying networks that are all disconnected is the same as specifying no networks. - mMockVpn.setUnderlyingNetworks(onlyCell); + mMockVpn.setUnderlyingNetworks(onlyCell.toArray(new Network[0])); waitForIdle(); - expectNetworkStatus(wifiAndVpn, null); + expectNotifyNetworkStatus(wifiAndVpn, null); reset(mStatsManager); // Passing in null again means follow the default network again. mMockVpn.setUnderlyingNetworks(null); waitForIdle(); - expectNetworkStatus(wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME, - new String[]{WIFI_IFNAME}); + expectNotifyNetworkStatus(wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME, + List.of(WIFI_IFNAME)); reset(mStatsManager); } @@ -9407,9 +9395,9 @@ public class ConnectivityServiceTest { @Override public TransportInfo makeCopy(@NetworkCapabilities.RedactionType long redactions) { return new TestTransportInfo( - (redactions & REDACT_FOR_ACCESS_FINE_LOCATION) != 0, - (redactions & REDACT_FOR_LOCAL_MAC_ADDRESS) != 0, - (redactions & REDACT_FOR_NETWORK_SETTINGS) != 0 + locationRedacted | (redactions & REDACT_FOR_ACCESS_FINE_LOCATION) != 0, + localMacAddressRedacted | (redactions & REDACT_FOR_LOCAL_MAC_ADDRESS) != 0, + settingsRedacted | (redactions & REDACT_FOR_NETWORK_SETTINGS) != 0 ); } @@ -9432,8 +9420,26 @@ public class ConnectivityServiceTest { public int hashCode() { return Objects.hash(locationRedacted, localMacAddressRedacted, settingsRedacted); } + + @Override + public String toString() { + return String.format( + "TestTransportInfo{locationRedacted=%s macRedacted=%s settingsRedacted=%s}", + locationRedacted, localMacAddressRedacted, settingsRedacted); + } + } + + private TestTransportInfo getTestTransportInfo(NetworkCapabilities nc) { + return (TestTransportInfo) nc.getTransportInfo(); + } + + private TestTransportInfo getTestTransportInfo(TestNetworkAgentWrapper n) { + final NetworkCapabilities nc = mCm.getNetworkCapabilities(n.getNetwork()); + assertNotNull(nc); + return getTestTransportInfo(nc); } + private void verifyNetworkCallbackLocationDataInclusionUsingTransportInfoAndOwnerUidInNetCaps( @NonNull TestNetworkCallback wifiNetworkCallback, int actualOwnerUid, @NonNull TransportInfo actualTransportInfo, int expectedOwnerUid, @@ -9462,7 +9468,6 @@ public class ConnectivityServiceTest { wifiNetworkCallback.expectCapabilitiesThat(mWiFiNetworkAgent, nc -> Objects.equals(expectedOwnerUid, nc.getOwnerUid()) && Objects.equals(expectedTransportInfo, nc.getTransportInfo())); - } @Test @@ -9483,6 +9488,40 @@ public class ConnectivityServiceTest { wifiNetworkCallack, ownerUid, transportInfo, INVALID_UID, sanitizedTransportInfo); } + @Test + public void testTransportInfoRedactionInSynchronousCalls() throws Exception { + final NetworkCapabilities ncTemplate = new NetworkCapabilities() + .addTransportType(TRANSPORT_WIFI) + .setTransportInfo(new TestTransportInfo()); + + mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(), + ncTemplate); + mWiFiNetworkAgent.connect(true /* validated; waits for callback */); + + // NETWORK_SETTINGS redaction is controlled by the NETWORK_SETTINGS permission + assertTrue(getTestTransportInfo(mWiFiNetworkAgent).settingsRedacted); + withPermission(NETWORK_SETTINGS, () -> { + assertFalse(getTestTransportInfo(mWiFiNetworkAgent).settingsRedacted); + }); + assertTrue(getTestTransportInfo(mWiFiNetworkAgent).settingsRedacted); + + // LOCAL_MAC_ADDRESS redaction is controlled by the LOCAL_MAC_ADDRESS permission + assertTrue(getTestTransportInfo(mWiFiNetworkAgent).localMacAddressRedacted); + withPermission(LOCAL_MAC_ADDRESS, () -> { + assertFalse(getTestTransportInfo(mWiFiNetworkAgent).localMacAddressRedacted); + }); + assertTrue(getTestTransportInfo(mWiFiNetworkAgent).localMacAddressRedacted); + + // Synchronous getNetworkCapabilities calls never return unredacted location-sensitive + // information. + assertTrue(getTestTransportInfo(mWiFiNetworkAgent).locationRedacted); + setupLocationPermissions(Build.VERSION_CODES.S, true, AppOpsManager.OPSTR_FINE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION); + assertTrue(getTestTransportInfo(mWiFiNetworkAgent).locationRedacted); + denyAllLocationPrivilegedPermissions(); + assertTrue(getTestTransportInfo(mWiFiNetworkAgent).locationRedacted); + } + private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType) throws Exception { final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE); @@ -9704,28 +9743,32 @@ public class ConnectivityServiceTest { @Test public void testCheckConnectivityDiagnosticsPermissionsWrongUidPackageName() throws Exception { - final NetworkAgentInfo naiWithoutUid = fakeMobileNai(new NetworkCapabilities()); + final int wrongUid = Process.myUid() + 1; + + final NetworkCapabilities nc = new NetworkCapabilities(); + nc.setAdministratorUids(new int[] {wrongUid}); + final NetworkAgentInfo naiWithUid = fakeMobileNai(nc); mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED); assertFalse( "Mismatched uid/package name should not pass the location permission check", mService.checkConnectivityDiagnosticsPermissions( - Process.myPid() + 1, Process.myUid() + 1, naiWithoutUid, - mContext.getOpPackageName())); + Process.myPid() + 1, wrongUid, naiWithUid, mContext.getOpPackageName())); } @Test public void testCheckConnectivityDiagnosticsPermissionsNoLocationPermission() throws Exception { - final NetworkAgentInfo naiWithoutUid = fakeMobileNai(new NetworkCapabilities()); + final NetworkCapabilities nc = new NetworkCapabilities(); + nc.setAdministratorUids(new int[] {Process.myUid()}); + final NetworkAgentInfo naiWithUid = fakeMobileNai(nc); mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED); assertFalse( "ACCESS_FINE_LOCATION permission necessary for Connectivity Diagnostics", mService.checkConnectivityDiagnosticsPermissions( - Process.myPid(), Process.myUid(), naiWithoutUid, - mContext.getOpPackageName())); + Process.myPid(), Process.myUid(), naiWithUid, mContext.getOpPackageName())); } @Test @@ -9840,12 +9883,27 @@ public class ConnectivityServiceTest { // Connect the cell agent verify that it notifies TestNetworkCallback that it is available final TestNetworkCallback callback = new TestNetworkCallback(); mCm.registerDefaultNetworkCallback(callback); - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); + + final NetworkCapabilities ncTemplate = new NetworkCapabilities() + .addTransportType(TRANSPORT_CELLULAR) + .setTransportInfo(new TestTransportInfo()); + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(), + ncTemplate); mCellNetworkAgent.connect(true); callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); callback.assertNoCallback(); } + private boolean areConnDiagCapsRedacted(NetworkCapabilities nc) { + TestTransportInfo ti = (TestTransportInfo) nc.getTransportInfo(); + return nc.getUids() == null + && nc.getAdministratorUids().length == 0 + && nc.getOwnerUid() == Process.INVALID_UID + && getTestTransportInfo(nc).locationRedacted + && getTestTransportInfo(nc).localMacAddressRedacted + && getTestTransportInfo(nc).settingsRedacted; + } + @Test public void testConnectivityDiagnosticsCallbackOnConnectivityReportAvailable() throws Exception { @@ -9856,12 +9914,7 @@ public class ConnectivityServiceTest { // Verify onConnectivityReport fired verify(mConnectivityDiagnosticsCallback).onConnectivityReportAvailable( - argThat(report -> { - final NetworkCapabilities nc = report.getNetworkCapabilities(); - return nc.getUids() == null - && nc.getAdministratorUids().length == 0 - && nc.getOwnerUid() == Process.INVALID_UID; - })); + argThat(report -> areConnDiagCapsRedacted(report.getNetworkCapabilities()))); } @Test @@ -9877,12 +9930,7 @@ public class ConnectivityServiceTest { // Verify onDataStallSuspected fired verify(mConnectivityDiagnosticsCallback).onDataStallSuspected( - argThat(report -> { - final NetworkCapabilities nc = report.getNetworkCapabilities(); - return nc.getUids() == null - && nc.getAdministratorUids().length == 0 - && nc.getOwnerUid() == Process.INVALID_UID; - })); + argThat(report -> areConnDiagCapsRedacted(report.getNetworkCapabilities()))); } @Test diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/packages/Connectivity/tests/unit/java/com/android/server/IpSecServiceParameterizedTest.java index cf2c9c783ac7..cf2c9c783ac7 100644 --- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java +++ b/packages/Connectivity/tests/unit/java/com/android/server/IpSecServiceParameterizedTest.java diff --git a/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java b/packages/Connectivity/tests/unit/java/com/android/server/IpSecServiceRefcountedResourceTest.java index 22a2c94fc194..22a2c94fc194 100644 --- a/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java +++ b/packages/Connectivity/tests/unit/java/com/android/server/IpSecServiceRefcountedResourceTest.java diff --git a/tests/net/java/com/android/server/IpSecServiceTest.java b/packages/Connectivity/tests/unit/java/com/android/server/IpSecServiceTest.java index 6232423b4f9e..6232423b4f9e 100644 --- a/tests/net/java/com/android/server/IpSecServiceTest.java +++ b/packages/Connectivity/tests/unit/java/com/android/server/IpSecServiceTest.java diff --git a/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt b/packages/Connectivity/tests/unit/java/com/android/server/LegacyTypeTrackerTest.kt index 5ec111954fcc..5ec111954fcc 100644 --- a/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt +++ b/packages/Connectivity/tests/unit/java/com/android/server/LegacyTypeTrackerTest.kt diff --git a/tests/net/java/com/android/server/NetIdManagerTest.kt b/packages/Connectivity/tests/unit/java/com/android/server/NetIdManagerTest.kt index 6f5e740d344c..6f5e740d344c 100644 --- a/tests/net/java/com/android/server/NetIdManagerTest.kt +++ b/packages/Connectivity/tests/unit/java/com/android/server/NetIdManagerTest.kt diff --git a/tests/net/java/com/android/server/NetworkManagementServiceTest.java b/packages/Connectivity/tests/unit/java/com/android/server/NetworkManagementServiceTest.java index 13516d75a50d..13516d75a50d 100644 --- a/tests/net/java/com/android/server/NetworkManagementServiceTest.java +++ b/packages/Connectivity/tests/unit/java/com/android/server/NetworkManagementServiceTest.java diff --git a/tests/net/java/com/android/server/NsdServiceTest.java b/packages/Connectivity/tests/unit/java/com/android/server/NsdServiceTest.java index a90fa6882c25..a90fa6882c25 100644 --- a/tests/net/java/com/android/server/NsdServiceTest.java +++ b/packages/Connectivity/tests/unit/java/com/android/server/NsdServiceTest.java diff --git a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/DnsManagerTest.java index 0ffeec98cf90..0ffeec98cf90 100644 --- a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java +++ b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/DnsManagerTest.java diff --git a/tests/net/java/com/android/server/connectivity/FullScoreTest.kt b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/FullScoreTest.kt index eb3b4df1a282..eb3b4df1a282 100644 --- a/tests/net/java/com/android/server/connectivity/FullScoreTest.kt +++ b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/FullScoreTest.kt diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java index 70495cced536..70495cced536 100644 --- a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java +++ b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/IpConnectivityMetricsTest.java index 8b072c49de82..8b072c49de82 100644 --- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java +++ b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/IpConnectivityMetricsTest.java diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/LingerMonitorTest.java index 116d755e30a4..116d755e30a4 100644 --- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java +++ b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/LingerMonitorTest.java diff --git a/tests/net/java/com/android/server/connectivity/MetricsTestUtil.java b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/MetricsTestUtil.java index 5064b9bd91b9..5064b9bd91b9 100644 --- a/tests/net/java/com/android/server/connectivity/MetricsTestUtil.java +++ b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/MetricsTestUtil.java diff --git a/tests/net/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java index 38f6d7f3172d..38f6d7f3172d 100644 --- a/tests/net/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java +++ b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java diff --git a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/Nat464XlatTest.java index 9b2a638f8b39..9b2a638f8b39 100644 --- a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java +++ b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/Nat464XlatTest.java diff --git a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/NetdEventListenerServiceTest.java index 50aaaee24418..50aaaee24418 100644 --- a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java +++ b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/NetdEventListenerServiceTest.java diff --git a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/NetworkNotificationManagerTest.java index 3adf08c19986..3adf08c19986 100644 --- a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java +++ b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/NetworkNotificationManagerTest.java diff --git a/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/NetworkRankerTest.kt index 86c91165f61b..86c91165f61b 100644 --- a/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt +++ b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/NetworkRankerTest.kt diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java index 02a58080fefd..c75618f43cde 100644 --- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java +++ b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java @@ -30,6 +30,8 @@ import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_REQUIRED; import static android.content.pm.PackageManager.GET_PERMISSIONS; import static android.content.pm.PackageManager.MATCH_ANY_USER; +import static android.net.ConnectivitySettingsManager.APPS_ALLOWED_ON_RESTRICTED_NETWORKS; +import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; import static android.os.Process.SYSTEM_UID; import static com.android.server.connectivity.PermissionMonitor.NETWORK; @@ -43,8 +45,10 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.AdditionalMatchers.aryEq; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; @@ -61,6 +65,7 @@ import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.database.ContentObserver; import android.net.INetd; import android.net.UidRange; import android.net.Uri; @@ -68,6 +73,7 @@ import android.os.Build; import android.os.SystemConfigManager; import android.os.UserHandle; import android.os.UserManager; +import android.util.ArraySet; import android.util.SparseIntArray; import androidx.test.InstrumentationRegistry; @@ -136,6 +142,7 @@ public class PermissionMonitorTest { final Context asUserCtx = mock(Context.class, AdditionalAnswers.delegatesTo(mContext)); doReturn(UserHandle.ALL).when(asUserCtx).getUser(); when(mContext.createContextAsUser(eq(UserHandle.ALL), anyInt())).thenReturn(asUserCtx); + when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn(new ArraySet<>()); mPermissionMonitor = spy(new PermissionMonitor(mContext, mNetdService, mDeps)); @@ -145,8 +152,15 @@ public class PermissionMonitorTest { private boolean hasRestrictedNetworkPermission(String partition, int targetSdkVersion, int uid, String... permissions) { + return hasRestrictedNetworkPermission( + partition, targetSdkVersion, "" /* packageName */, uid, permissions); + } + + private boolean hasRestrictedNetworkPermission(String partition, int targetSdkVersion, + String packageName, int uid, String... permissions) { final PackageInfo packageInfo = packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED, permissions, partition); + packageInfo.packageName = packageName; packageInfo.applicationInfo.targetSdkVersion = targetSdkVersion; packageInfo.applicationInfo.uid = uid; return mPermissionMonitor.hasRestrictedNetworkPermission(packageInfo); @@ -280,6 +294,8 @@ public class PermissionMonitorTest { PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); assertFalse(hasRestrictedNetworkPermission( PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CHANGE_WIFI_STATE)); + assertTrue(hasRestrictedNetworkPermission( + PARTITION_SYSTEM, VERSION_P, MOCK_UID1, PERMISSION_MAINLINE_NETWORK_STACK)); assertFalse(hasRestrictedNetworkPermission(PARTITION_SYSTEM, VERSION_Q, MOCK_UID1)); assertFalse(hasRestrictedNetworkPermission( @@ -324,6 +340,90 @@ public class PermissionMonitorTest { PARTITION_VENDOR, VERSION_Q, MOCK_UID1, CHANGE_NETWORK_STATE)); } + @Test + public void testHasRestrictedNetworkPermissionAppAllowedOnRestrictedNetworks() { + mPermissionMonitor.updateAppsAllowedOnRestrictedNetworks( + new ArraySet<>(new String[] { MOCK_PACKAGE1 })); + assertTrue(hasRestrictedNetworkPermission( + PARTITION_VENDOR, VERSION_Q, MOCK_PACKAGE1, MOCK_UID1)); + assertTrue(hasRestrictedNetworkPermission( + PARTITION_VENDOR, VERSION_Q, MOCK_PACKAGE1, MOCK_UID1, CHANGE_NETWORK_STATE)); + assertTrue(hasRestrictedNetworkPermission( + PARTITION_VENDOR, VERSION_Q, MOCK_PACKAGE1, MOCK_UID1, CONNECTIVITY_INTERNAL)); + + assertFalse(hasRestrictedNetworkPermission( + PARTITION_VENDOR, VERSION_Q, MOCK_PACKAGE2, MOCK_UID1)); + assertFalse(hasRestrictedNetworkPermission( + PARTITION_VENDOR, VERSION_Q, MOCK_PACKAGE2, MOCK_UID1, CHANGE_NETWORK_STATE)); + assertFalse(hasRestrictedNetworkPermission( + PARTITION_VENDOR, VERSION_Q, MOCK_PACKAGE2, MOCK_UID1, CONNECTIVITY_INTERNAL)); + + } + + private boolean wouldBeCarryoverPackage(String partition, int targetSdkVersion, int uid) { + final PackageInfo packageInfo = packageInfoWithPermissions( + REQUESTED_PERMISSION_GRANTED, new String[] {}, partition); + packageInfo.applicationInfo.targetSdkVersion = targetSdkVersion; + packageInfo.applicationInfo.uid = uid; + return mPermissionMonitor.isCarryoverPackage(packageInfo.applicationInfo); + } + + @Test + public void testIsCarryoverPackage() { + doReturn(VERSION_P).when(mDeps).getDeviceFirstSdkInt(); + assertTrue(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_P, SYSTEM_UID)); + assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_P, SYSTEM_UID)); + assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_P, MOCK_UID1)); + assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_P, MOCK_UID1)); + assertTrue(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID)); + assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_Q, SYSTEM_UID)); + assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_Q, MOCK_UID1)); + assertFalse(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_Q, MOCK_UID1)); + + doReturn(VERSION_Q).when(mDeps).getDeviceFirstSdkInt(); + assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_P, SYSTEM_UID)); + assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_P, SYSTEM_UID)); + assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_P, MOCK_UID1)); + assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_P, MOCK_UID1)); + assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID)); + assertFalse(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_Q, SYSTEM_UID)); + assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_Q, MOCK_UID1)); + assertFalse(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_Q, MOCK_UID1)); + + assertFalse(wouldBeCarryoverPackage(PARTITION_OEM, VERSION_Q, SYSTEM_UID)); + assertFalse(wouldBeCarryoverPackage(PARTITION_PRODUCT, VERSION_Q, SYSTEM_UID)); + assertFalse(wouldBeCarryoverPackage(PARTITION_OEM, VERSION_Q, MOCK_UID1)); + assertFalse(wouldBeCarryoverPackage(PARTITION_PRODUCT, VERSION_Q, MOCK_UID1)); + } + + private boolean wouldBeAppAllowedOnRestrictedNetworks(String packageName) { + final PackageInfo packageInfo = new PackageInfo(); + packageInfo.packageName = packageName; + return mPermissionMonitor.isAppAllowedOnRestrictedNetworks(packageInfo); + } + + @Test + public void testIsAppAllowedOnRestrictedNetworks() { + mPermissionMonitor.updateAppsAllowedOnRestrictedNetworks(new ArraySet<>()); + assertFalse(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE1)); + assertFalse(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE2)); + + mPermissionMonitor.updateAppsAllowedOnRestrictedNetworks( + new ArraySet<>(new String[] { MOCK_PACKAGE1 })); + assertTrue(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE1)); + assertFalse(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE2)); + + mPermissionMonitor.updateAppsAllowedOnRestrictedNetworks( + new ArraySet<>(new String[] { MOCK_PACKAGE2 })); + assertFalse(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE1)); + assertTrue(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE2)); + + mPermissionMonitor.updateAppsAllowedOnRestrictedNetworks( + new ArraySet<>(new String[] { "com.android.test" })); + assertFalse(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE1)); + assertFalse(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE2)); + } + private void assertBackgroundPermission(boolean hasPermission, String name, int uid, String... permissions) throws Exception { when(mPackageManager.getPackageInfo(eq(name), anyInt())) @@ -800,4 +900,102 @@ public class PermissionMonitorTest { mNetdServiceMonitor.expectPermission(INetd.PERMISSION_UNINSTALLED, new int[] { MOCK_UID1 }); } -} + @Test + public void testAppsAllowedOnRestrictedNetworksChanged() throws Exception { + final NetdMonitor mNetdMonitor = new NetdMonitor(mNetdService); + final ArgumentCaptor<ContentObserver> captor = + ArgumentCaptor.forClass(ContentObserver.class); + verify(mDeps, times(1)).registerContentObserver(any(), + argThat(uri -> uri.getEncodedPath().contains(APPS_ALLOWED_ON_RESTRICTED_NETWORKS)), + anyBoolean(), captor.capture()); + final ContentObserver contentObserver = captor.getValue(); + + mPermissionMonitor.onUserAdded(MOCK_USER1); + // Prepare PackageInfo for MOCK_PACKAGE1 + final PackageInfo packageInfo = buildPackageInfo( + false /* hasSystemPermission */, MOCK_UID1, MOCK_USER1); + packageInfo.packageName = MOCK_PACKAGE1; + when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE1), anyInt())).thenReturn(packageInfo); + when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{MOCK_PACKAGE1}); + // Prepare PackageInfo for MOCK_PACKAGE2 + final PackageInfo packageInfo2 = buildPackageInfo( + false /* hasSystemPermission */, MOCK_UID2, MOCK_USER1); + packageInfo2.packageName = MOCK_PACKAGE2; + when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE2), anyInt())).thenReturn(packageInfo2); + when(mPackageManager.getPackagesForUid(MOCK_UID2)).thenReturn(new String[]{MOCK_PACKAGE2}); + + // MOCK_PACKAGE1 is listed in setting that allow to use restricted networks, MOCK_UID1 + // should have SYSTEM permission. + when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn( + new ArraySet<>(new String[] { MOCK_PACKAGE1 })); + contentObserver.onChange(true /* selfChange */); + mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1}); + mNetdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID2}); + + // MOCK_PACKAGE2 is listed in setting that allow to use restricted networks, MOCK_UID2 + // should have SYSTEM permission but MOCK_UID1 should revoke permission. + when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn( + new ArraySet<>(new String[] { MOCK_PACKAGE2 })); + contentObserver.onChange(true /* selfChange */); + mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID2}); + mNetdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1}); + + // No app lists in setting, should revoke permission from all uids. + when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn(new ArraySet<>()); + contentObserver.onChange(true /* selfChange */); + mNetdMonitor.expectNoPermission( + new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1, MOCK_UID2}); + } + + @Test + public void testAppsAllowedOnRestrictedNetworksChangedWithSharedUid() throws Exception { + final NetdMonitor mNetdMonitor = new NetdMonitor(mNetdService); + final ArgumentCaptor<ContentObserver> captor = + ArgumentCaptor.forClass(ContentObserver.class); + verify(mDeps, times(1)).registerContentObserver(any(), + argThat(uri -> uri.getEncodedPath().contains(APPS_ALLOWED_ON_RESTRICTED_NETWORKS)), + anyBoolean(), captor.capture()); + final ContentObserver contentObserver = captor.getValue(); + + mPermissionMonitor.onUserAdded(MOCK_USER1); + // Prepare PackageInfo for MOCK_PACKAGE1 and MOCK_PACKAGE2 with shared uid MOCK_UID1. + final PackageInfo packageInfo = systemPackageInfoWithPermissions(CHANGE_NETWORK_STATE); + packageInfo.applicationInfo.uid = MOCK_USER1.getUid(MOCK_UID1); + packageInfo.packageName = MOCK_PACKAGE1; + final PackageInfo packageInfo2 = buildPackageInfo( + false /* hasSystemPermission */, MOCK_UID1, MOCK_USER1); + packageInfo2.packageName = MOCK_PACKAGE2; + when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE1), anyInt())).thenReturn(packageInfo); + when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE2), anyInt())).thenReturn(packageInfo2); + when(mPackageManager.getPackagesForUid(MOCK_UID1)) + .thenReturn(new String[]{MOCK_PACKAGE1, MOCK_PACKAGE2}); + + // MOCK_PACKAGE1 have CHANGE_NETWORK_STATE, MOCK_UID1 should have NETWORK permission. + addPackageForUsers(new UserHandle[]{MOCK_USER1}, MOCK_PACKAGE1, MOCK_UID1); + mNetdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1}); + + // MOCK_PACKAGE2 is listed in setting that allow to use restricted networks, MOCK_UID1 + // should upgrade to SYSTEM permission. + when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn( + new ArraySet<>(new String[] { MOCK_PACKAGE2 })); + contentObserver.onChange(true /* selfChange */); + mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1}); + + // MOCK_PACKAGE1 is listed in setting that allow to use restricted networks, MOCK_UID1 + // should still have SYSTEM permission. + when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn( + new ArraySet<>(new String[] { MOCK_PACKAGE1 })); + contentObserver.onChange(true /* selfChange */); + mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1}); + + // No app lists in setting, MOCK_UID1 should downgrade to NETWORK permission. + when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn(new ArraySet<>()); + contentObserver.onChange(true /* selfChange */); + mNetdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1}); + + // MOCK_PACKAGE1 removed, should revoke permission from MOCK_UID1. + when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{MOCK_PACKAGE2}); + removePackageForUsers(new UserHandle[]{MOCK_USER1}, MOCK_PACKAGE1, MOCK_UID1); + mNetdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1}); + } +}
\ No newline at end of file diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/VpnTest.java index b725b826b14f..b725b826b14f 100644 --- a/tests/net/java/com/android/server/connectivity/VpnTest.java +++ b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/VpnTest.java diff --git a/tests/net/java/com/android/server/net/NetworkStatsAccessTest.java b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsAccessTest.java index 8b730af76951..8b730af76951 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsAccessTest.java +++ b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsAccessTest.java diff --git a/tests/net/java/com/android/server/net/NetworkStatsBaseTest.java b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsBaseTest.java index a058a466a4ff..a058a466a4ff 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsBaseTest.java +++ b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsBaseTest.java diff --git a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsCollectionTest.java index 505ff9b6a34b..505ff9b6a34b 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java +++ b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsCollectionTest.java diff --git a/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java index f3ae9b051e7c..93599f3c376d 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java +++ b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java @@ -43,6 +43,7 @@ import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.frameworks.tests.net.R; +import com.android.internal.util.test.FsUtil; import libcore.io.IoUtils; import libcore.io.Streams; @@ -71,7 +72,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest { public void setUp() throws Exception { mTestProc = new File(InstrumentationRegistry.getContext().getFilesDir(), "proc"); if (mTestProc.exists()) { - IoUtils.deleteContents(mTestProc); + FsUtil.deleteContents(mTestProc); } // The libandroid_servers which have the native method is not available to @@ -87,7 +88,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest { mFactory = null; if (mTestProc.exists()) { - IoUtils.deleteContents(mTestProc); + FsUtil.deleteContents(mTestProc); } } diff --git a/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java index 9fa1c50423d9..9fa1c50423d9 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java +++ b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java index fd374bc9e68f..0ba5f7d8241e 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java +++ b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java @@ -112,13 +112,12 @@ import androidx.test.runner.AndroidJUnit4; import com.android.internal.util.ArrayUtils; import com.android.internal.util.test.BroadcastInterceptingContext; +import com.android.internal.util.test.FsUtil; import com.android.server.net.NetworkStatsService.NetworkStatsSettings; import com.android.server.net.NetworkStatsService.NetworkStatsSettings.Config; import com.android.testutils.HandlerUtils; import com.android.testutils.TestableNetworkStatsProviderBinder; -import libcore.io.IoUtils; - import org.junit.After; import org.junit.Before; import org.junit.Ignore; @@ -152,6 +151,8 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { private static final String TEST_SSID = "AndroidAP"; private static NetworkTemplate sTemplateWifi = buildTemplateWifi(TEST_SSID); + private static NetworkTemplate sTemplateCarrierWifi1 = + buildTemplateWifi(NetworkTemplate.WIFI_NETWORKID_ALL, IMSI_1); private static NetworkTemplate sTemplateImsi1 = buildTemplateMobileAll(IMSI_1); private static NetworkTemplate sTemplateImsi2 = buildTemplateMobileAll(IMSI_2); @@ -213,7 +214,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { mServiceContext = new MockContext(context); mStatsDir = context.getFilesDir(); if (mStatsDir.exists()) { - IoUtils.deleteContents(mStatsDir); + FsUtil.deleteContents(mStatsDir); } PowerManager powerManager = (PowerManager) mServiceContext.getSystemService( @@ -283,7 +284,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { @After public void tearDown() throws Exception { - IoUtils.deleteContents(mStatsDir); + FsUtil.deleteContents(mStatsDir); mServiceContext = null; mStatsDir = null; @@ -297,45 +298,82 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { mHandlerThread.quitSafely(); } - @Test - public void testNetworkStatsWifi() throws Exception { + private void initWifiStats(NetworkStateSnapshot snapshot) throws Exception { // pretend that wifi network comes online; service should ask about full // network state, and poll any existing interfaces before updating. expectDefaultSettings(); - NetworkStateSnapshot[] states = new NetworkStateSnapshot[] {buildWifiState()}; + NetworkStateSnapshot[] states = new NetworkStateSnapshot[] {snapshot}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), + mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states), new UnderlyingNetworkInfo[0]); + } - // verify service has empty history for wifi - assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); - - // modify some number on wifi, and trigger poll event - incrementCurrentTime(HOUR_IN_MILLIS); + private void incrementWifiStats(long durationMillis, String iface, + long rxb, long rxp, long txb, long txp) throws Exception { + incrementCurrentTime(durationMillis); expectDefaultSettings(); expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) - .insertEntry(TEST_IFACE, 1024L, 1L, 2048L, 2L)); + .insertEntry(iface, rxb, rxp, txb, txp)); expectNetworkStatsUidDetail(buildEmptyStats()); forcePollAndWaitForIdle(); + } + + @Test + public void testNetworkStatsCarrierWifi() throws Exception { + initWifiStats(buildWifiState(true, TEST_IFACE, IMSI_1)); + // verify service has empty history for carrier merged wifi and non-carrier wifi + assertNetworkTotal(sTemplateCarrierWifi1, 0L, 0L, 0L, 0L, 0); + assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); + + // modify some number on wifi, and trigger poll event + incrementWifiStats(HOUR_IN_MILLIS, TEST_IFACE, 1024L, 1L, 2048L, 2L); // verify service recorded history - assertNetworkTotal(sTemplateWifi, 1024L, 1L, 2048L, 2L, 0); + assertNetworkTotal(sTemplateCarrierWifi1, 1024L, 1L, 2048L, 2L, 0); + + // verify service recorded history for wifi with SSID filter + assertNetworkTotal(sTemplateWifi, 1024L, 1L, 2048L, 2L, 0); // and bump forward again, with counters going higher. this is // important, since polling should correctly subtract last snapshot. - incrementCurrentTime(DAY_IN_MILLIS); - expectDefaultSettings(); - expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) - .insertEntry(TEST_IFACE, 4096L, 4L, 8192L, 8L)); - expectNetworkStatsUidDetail(buildEmptyStats()); - forcePollAndWaitForIdle(); + incrementWifiStats(DAY_IN_MILLIS, TEST_IFACE, 4096L, 4L, 8192L, 8L); // verify service recorded history + assertNetworkTotal(sTemplateCarrierWifi1, 4096L, 4L, 8192L, 8L, 0); + // verify service recorded history for wifi with SSID filter assertNetworkTotal(sTemplateWifi, 4096L, 4L, 8192L, 8L, 0); + } + + @Test + public void testNetworkStatsNonCarrierWifi() throws Exception { + initWifiStats(buildWifiState()); + + // verify service has empty history for wifi + assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); + // verify service has empty history for carrier merged wifi + assertNetworkTotal(sTemplateCarrierWifi1, 0L, 0L, 0L, 0L, 0); + + // modify some number on wifi, and trigger poll event + incrementWifiStats(HOUR_IN_MILLIS, TEST_IFACE, 1024L, 1L, 2048L, 2L); + // verify service recorded history + assertNetworkTotal(sTemplateWifi, 1024L, 1L, 2048L, 2L, 0); + // verify service has empty history for carrier wifi since current network is non carrier + // wifi + assertNetworkTotal(sTemplateCarrierWifi1, 0L, 0L, 0L, 0L, 0); + + // and bump forward again, with counters going higher. this is + // important, since polling should correctly subtract last snapshot. + incrementWifiStats(DAY_IN_MILLIS, TEST_IFACE, 4096L, 4L, 8192L, 8L); + + // verify service recorded history + assertNetworkTotal(sTemplateWifi, 4096L, 4L, 8192L, 8L, 0); + // verify service has empty history for carrier wifi since current network is non carrier + // wifi + assertNetworkTotal(sTemplateCarrierWifi1, 0L, 0L, 0L, 0L, 0); } @Test @@ -349,7 +387,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), + mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states), new UnderlyingNetworkInfo[0]); // verify service has empty history for wifi @@ -423,7 +461,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), + mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states), new UnderlyingNetworkInfo[0]); // modify some number on wifi, and trigger poll event @@ -464,7 +502,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), + mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states), new UnderlyingNetworkInfo[0]); // create some traffic on first network @@ -499,7 +537,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L) .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L)); - mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), + mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states), new UnderlyingNetworkInfo[0]); forcePollAndWaitForIdle(); @@ -539,7 +577,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), + mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states), new UnderlyingNetworkInfo[0]); // create some traffic @@ -607,7 +645,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { expectNetworkStatsUidDetail(buildEmptyStats()); setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_UMTS); - mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), + mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states), new UnderlyingNetworkInfo[0]); // Create some traffic. @@ -699,7 +737,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { new int[]{NetworkCapabilities.NET_CAPABILITY_OEM_PAID})}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), + mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states), new UnderlyingNetworkInfo[0]); // Create some traffic. @@ -714,7 +752,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { new int[]{NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE})}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), + mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states), new UnderlyingNetworkInfo[0]); // Create some traffic. @@ -730,7 +768,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { NetworkCapabilities.NET_CAPABILITY_OEM_PAID})}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), + mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states), new UnderlyingNetworkInfo[0]); // Create some traffic. @@ -744,7 +782,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { states = new NetworkStateSnapshot[]{buildOemManagedMobileState(IMSI_1, false, new int[]{})}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), + mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states), new UnderlyingNetworkInfo[0]); // Create some traffic. @@ -797,7 +835,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), + mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states), new UnderlyingNetworkInfo[0]); // create some traffic for two apps @@ -856,7 +894,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), + mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states), new UnderlyingNetworkInfo[0]); NetworkStats.Entry entry1 = new NetworkStats.Entry( @@ -900,7 +938,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), + mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states), new UnderlyingNetworkInfo[0]); NetworkStats.Entry uidStats = new NetworkStats.Entry( @@ -931,7 +969,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { // mStatsFactory#readNetworkStatsDetail() has the following invocations: // 1) NetworkStatsService#systemReady from #setUp. - // 2) mService#forceUpdateIfaces in the test above. + // 2) mService#notifyNetworkStatus in the test above. // // Additionally, we should have one call from the above call to mService#getDetailedUidStats // with the augmented ifaceFilter. @@ -955,7 +993,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), + mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states), new UnderlyingNetworkInfo[0]); // create some initial traffic @@ -1013,7 +1051,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), + mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states), new UnderlyingNetworkInfo[0]); // create some initial traffic @@ -1053,7 +1091,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), + mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states), new UnderlyingNetworkInfo[0]); // Create some traffic @@ -1092,7 +1130,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), + mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states), new UnderlyingNetworkInfo[0]); // create some tethering traffic @@ -1149,7 +1187,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), + mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states), new UnderlyingNetworkInfo[0]); // verify service has empty history for wifi @@ -1255,7 +1293,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { mService.registerNetworkStatsProvider("TEST", provider); assertNotNull(cb); - mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), + mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states), new UnderlyingNetworkInfo[0]); // Verifies that one requestStatsUpdate will be called during iface update. @@ -1320,7 +1358,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { mService.registerNetworkStatsProvider("TEST", provider); assertNotNull(cb); - mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), + mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states), new UnderlyingNetworkInfo[0]); // Verifies that one requestStatsUpdate will be called during iface update. @@ -1378,7 +1416,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { expectDefaultSettings(); NetworkStateSnapshot[] states = new NetworkStateSnapshot[]{buildWifiState(true /* isMetered */, TEST_IFACE)}; - mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), + mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states), new UnderlyingNetworkInfo[0]); // Register custom provider and retrieve callback. @@ -1428,7 +1466,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { // 3G network comes online. setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_UMTS); - mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), + mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states), new UnderlyingNetworkInfo[0]); // Create some traffic. @@ -1450,7 +1488,8 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { setCombineSubtypeEnabled(true); // Call handleOnCollapsedRatTypeChanged manually to simulate the callback fired - // when stopping monitor, this is needed by NetworkStatsService to trigger updateIfaces. + // when stopping monitor, this is needed by NetworkStatsService to trigger + // handleNotifyNetworkStatus. mService.handleOnCollapsedRatTypeChanged(); HandlerUtils.waitForIdle(mHandlerThread, WAIT_TIMEOUT); // Create some traffic. @@ -1499,7 +1538,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { NetworkStateSnapshot[] states = new NetworkStateSnapshot[]{ buildWifiState(true /*isMetered*/, TEST_IFACE2), buildMobile3gState(IMSI_1)}; expectNetworkStatsUidDetail(buildEmptyStats()); - mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), + mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states), new UnderlyingNetworkInfo[0]); // Create some traffic on mobile network. @@ -1661,10 +1700,15 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { } private static NetworkStateSnapshot buildWifiState() { - return buildWifiState(false, TEST_IFACE); + return buildWifiState(false, TEST_IFACE, null); } private static NetworkStateSnapshot buildWifiState(boolean isMetered, @NonNull String iface) { + return buildWifiState(isMetered, iface, null); + } + + private static NetworkStateSnapshot buildWifiState(boolean isMetered, @NonNull String iface, + String subscriberId) { final LinkProperties prop = new LinkProperties(); prop.setInterfaceName(iface); final NetworkCapabilities capabilities = new NetworkCapabilities(); @@ -1672,7 +1716,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true); capabilities.addTransportType(NetworkCapabilities.TRANSPORT_WIFI); capabilities.setSSID(TEST_SSID); - return new NetworkStateSnapshot(WIFI_NETWORK, capabilities, prop, null, TYPE_WIFI); + return new NetworkStateSnapshot(WIFI_NETWORK, capabilities, prop, subscriberId, TYPE_WIFI); } private static NetworkStateSnapshot buildMobile3gState(String subscriberId) { diff --git a/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java index 6d2c7dc39ffd..6d2c7dc39ffd 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java +++ b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java diff --git a/tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java b/packages/Connectivity/tests/unit/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java index ebbc0ef62548..ebbc0ef62548 100644 --- a/tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java +++ b/packages/Connectivity/tests/unit/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java diff --git a/tests/net/jni/Android.bp b/packages/Connectivity/tests/unit/jni/Android.bp index 22a04f5c0945..22a04f5c0945 100644 --- a/tests/net/jni/Android.bp +++ b/packages/Connectivity/tests/unit/jni/Android.bp diff --git a/tests/net/jni/test_onload.cpp b/packages/Connectivity/tests/unit/jni/test_onload.cpp index 5194ddb0d882..5194ddb0d882 100644 --- a/tests/net/jni/test_onload.cpp +++ b/packages/Connectivity/tests/unit/jni/test_onload.cpp diff --git a/tests/net/res/raw/history_v1 b/packages/Connectivity/tests/unit/res/raw/history_v1 Binary files differindex de79491c032e..de79491c032e 100644 --- a/tests/net/res/raw/history_v1 +++ b/packages/Connectivity/tests/unit/res/raw/history_v1 diff --git a/tests/net/res/raw/net_dev_typical b/packages/Connectivity/tests/unit/res/raw/net_dev_typical index 290bf03eb9b4..290bf03eb9b4 100644 --- a/tests/net/res/raw/net_dev_typical +++ b/packages/Connectivity/tests/unit/res/raw/net_dev_typical diff --git a/tests/net/res/raw/netstats_uid_v4 b/packages/Connectivity/tests/unit/res/raw/netstats_uid_v4 Binary files differindex e75fc1ca5c2e..e75fc1ca5c2e 100644 --- a/tests/net/res/raw/netstats_uid_v4 +++ b/packages/Connectivity/tests/unit/res/raw/netstats_uid_v4 diff --git a/tests/net/res/raw/netstats_v1 b/packages/Connectivity/tests/unit/res/raw/netstats_v1 Binary files differindex e80860a6b959..e80860a6b959 100644 --- a/tests/net/res/raw/netstats_v1 +++ b/packages/Connectivity/tests/unit/res/raw/netstats_v1 diff --git a/tests/net/res/raw/xt_qtaguid_iface_fmt_typical b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_iface_fmt_typical index 656d5bb82da4..656d5bb82da4 100644 --- a/tests/net/res/raw/xt_qtaguid_iface_fmt_typical +++ b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_iface_fmt_typical diff --git a/tests/net/res/raw/xt_qtaguid_iface_typical b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_iface_typical index 610723aef2f2..610723aef2f2 100644 --- a/tests/net/res/raw/xt_qtaguid_iface_typical +++ b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_iface_typical diff --git a/tests/net/res/raw/xt_qtaguid_typical b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_typical index c1b0d259955c..c1b0d259955c 100644 --- a/tests/net/res/raw/xt_qtaguid_typical +++ b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_typical diff --git a/tests/net/res/raw/xt_qtaguid_vpn_incorrect_iface b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_incorrect_iface index fc92715253ed..fc92715253ed 100644 --- a/tests/net/res/raw/xt_qtaguid_vpn_incorrect_iface +++ b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_incorrect_iface diff --git a/tests/net/res/raw/xt_qtaguid_vpn_one_underlying b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_one_underlying index 1ef18894b669..1ef18894b669 100644 --- a/tests/net/res/raw/xt_qtaguid_vpn_one_underlying +++ b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_one_underlying diff --git a/tests/net/res/raw/xt_qtaguid_vpn_one_underlying_compression b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_one_underlying_compression index 6d6bf550bbfa..6d6bf550bbfa 100644 --- a/tests/net/res/raw/xt_qtaguid_vpn_one_underlying_compression +++ b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_one_underlying_compression diff --git a/tests/net/res/raw/xt_qtaguid_vpn_one_underlying_own_traffic b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_one_underlying_own_traffic index 2c2e5d2555f6..2c2e5d2555f6 100644 --- a/tests/net/res/raw/xt_qtaguid_vpn_one_underlying_own_traffic +++ b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_one_underlying_own_traffic diff --git a/tests/net/res/raw/xt_qtaguid_vpn_one_underlying_two_vpn b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_one_underlying_two_vpn index eb0513b10049..eb0513b10049 100644 --- a/tests/net/res/raw/xt_qtaguid_vpn_one_underlying_two_vpn +++ b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_one_underlying_two_vpn diff --git a/tests/net/res/raw/xt_qtaguid_vpn_rewrite_through_self b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_rewrite_through_self index afcdd7199026..afcdd7199026 100644 --- a/tests/net/res/raw/xt_qtaguid_vpn_rewrite_through_self +++ b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_rewrite_through_self diff --git a/tests/net/res/raw/xt_qtaguid_vpn_two_underlying_duplication b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_two_underlying_duplication index d7c7eb9f4ae8..d7c7eb9f4ae8 100644 --- a/tests/net/res/raw/xt_qtaguid_vpn_two_underlying_duplication +++ b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_two_underlying_duplication diff --git a/tests/net/res/raw/xt_qtaguid_vpn_two_underlying_split b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_two_underlying_split index 38a3dce4a834..38a3dce4a834 100644 --- a/tests/net/res/raw/xt_qtaguid_vpn_two_underlying_split +++ b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_two_underlying_split diff --git a/tests/net/res/raw/xt_qtaguid_vpn_two_underlying_split_compression b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_two_underlying_split_compression index d35244b3b4f2..d35244b3b4f2 100644 --- a/tests/net/res/raw/xt_qtaguid_vpn_two_underlying_split_compression +++ b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_two_underlying_split_compression diff --git a/tests/net/res/raw/xt_qtaguid_vpn_with_clat b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_with_clat index 0d893d515ca2..0d893d515ca2 100644 --- a/tests/net/res/raw/xt_qtaguid_vpn_with_clat +++ b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_with_clat diff --git a/tests/net/res/raw/xt_qtaguid_with_clat b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_with_clat index f04b32f08332..f04b32f08332 100644 --- a/tests/net/res/raw/xt_qtaguid_with_clat +++ b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_with_clat diff --git a/tests/net/res/raw/xt_qtaguid_with_clat_100mb_download_after b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_with_clat_100mb_download_after index 12d98ca29f57..12d98ca29f57 100644 --- a/tests/net/res/raw/xt_qtaguid_with_clat_100mb_download_after +++ b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_with_clat_100mb_download_after diff --git a/tests/net/res/raw/xt_qtaguid_with_clat_100mb_download_before b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_with_clat_100mb_download_before index ce4bcc3a3b43..ce4bcc3a3b43 100644 --- a/tests/net/res/raw/xt_qtaguid_with_clat_100mb_download_before +++ b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_with_clat_100mb_download_before diff --git a/tests/net/res/raw/xt_qtaguid_with_clat_simple b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_with_clat_simple index a1d6d411bad8..a1d6d411bad8 100644 --- a/tests/net/res/raw/xt_qtaguid_with_clat_simple +++ b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_with_clat_simple diff --git a/packages/CtsShim/OWNERS b/packages/CtsShim/OWNERS index ba9f2b97678a..94197715150d 100644 --- a/packages/CtsShim/OWNERS +++ b/packages/CtsShim/OWNERS @@ -1,2 +1,3 @@ ioffe@google.com -toddke@google.com
\ No newline at end of file +toddke@google.com +patb@google.com
\ No newline at end of file diff --git a/packages/InputDevices/res/raw/keyboard_layout_hebrew.kcm b/packages/InputDevices/res/raw/keyboard_layout_hebrew.kcm index cd3a4b959386..283cb4ef2081 100644 --- a/packages/InputDevices/res/raw/keyboard_layout_hebrew.kcm +++ b/packages/InputDevices/res/raw/keyboard_layout_hebrew.kcm @@ -89,14 +89,14 @@ key 8 { key 9 { label: '9' base: '9' - shift: '(' + shift: ')' shift+capslock: '\u05c2' } key 0 { label: '0' base: '0' - shift: ')' + shift: '(' shift+capslock: '\u05c1' } @@ -180,17 +180,17 @@ key P { } key LEFT_BRACKET { - label: '[' - base, capslock: '[' - shift: '{' -} - -key RIGHT_BRACKET { label: ']' base, capslock: ']' shift: '}' } +key RIGHT_BRACKET { + label: '[' + base, capslock: '[' + shift: '{' +} + ### ROW 3 key A { @@ -322,14 +322,14 @@ key M { key COMMA { label: ',' base: '\u05ea' - shift: '<' + shift: '>' capslock: ',' } key PERIOD { label: '.' base: '\u05e5' - shift: '>' + shift: '<' capslock: '.' } diff --git a/packages/InputDevices/res/raw/keyboard_layout_persian.kcm b/packages/InputDevices/res/raw/keyboard_layout_persian.kcm index e7dd6c6d68c8..bfe78212b1eb 100644 --- a/packages/InputDevices/res/raw/keyboard_layout_persian.kcm +++ b/packages/InputDevices/res/raw/keyboard_layout_persian.kcm @@ -292,14 +292,14 @@ key TAB { key COMMA { label, number: '\u0648' base: '\u0648' - shift: '<' + shift: '>' ctrl, alt, meta: none } key PERIOD { label, number: '.' base: '.' - shift: '>' + shift: '<' ctrl, alt, meta: none } @@ -440,14 +440,14 @@ key NUMPAD_9 { } key NUMPAD_LEFT_PAREN { - label, number: '(' - base: '(' + label, number: ')' + base: ')' ctrl, alt, meta: none } key NUMPAD_RIGHT_PAREN { - label, number: ')' - base: ')' + label, number: '(' + base: '(' ctrl, alt, meta: none } diff --git a/packages/PackageInstaller/OWNERS b/packages/PackageInstaller/OWNERS index 8e1774b0baa2..c6331133367a 100644 --- a/packages/PackageInstaller/OWNERS +++ b/packages/PackageInstaller/OWNERS @@ -1,5 +1,6 @@ svetoslavganov@google.com toddke@google.com +patb@google.com suprabh@google.com # For automotive related changes diff --git a/packages/SettingsProvider/OWNERS b/packages/SettingsProvider/OWNERS index cf9799c6a026..6c61d4b91d36 100644 --- a/packages/SettingsProvider/OWNERS +++ b/packages/SettingsProvider/OWNERS @@ -4,3 +4,4 @@ narayan@google.com svetoslavganov@google.com schfan@google.com toddke@google.com +patb@google.com diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 27df92f0832b..133a839bdc94 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -427,8 +427,9 @@ <!-- Permission needed for CTS test - DisplayTest --> <uses-permission android:name="android.permission.OVERRIDE_DISPLAY_MODE_REQUESTS" /> - <!-- Permission needed for CTS test - TimeManagerTest --> + <!-- Permissions needed for CTS test - TimeManagerTest --> <uses-permission android:name="android.permission.MANAGE_TIME_AND_ZONE_DETECTION" /> + <uses-permission android:name="android.permission.SUGGEST_EXTERNAL_TIME" /> <!-- Permission needed for CTS test - CtsHdmiCecHostTestCases --> <uses-permission android:name="android.permission.HDMI_CEC" /> @@ -467,6 +468,9 @@ <!-- Permission required for CTS test - CtsAlarmManagerTestCases --> <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" /> + <!-- Permission required for CTS test - GlobalSearchSessionPlatformCtsTests --> + <uses-permission android:name="android.permission.READ_GLOBAL_APP_SEARCH_DATA" /> + <application android:label="@string/app_label" android:theme="@android:style/Theme.DeviceDefault.DayNight" android:defaultToDeviceProtectedStorage="true" diff --git a/packages/Shell/OWNERS b/packages/Shell/OWNERS index 6d738f8d4d43..177f86b08864 100644 --- a/packages/Shell/OWNERS +++ b/packages/Shell/OWNERS @@ -7,6 +7,7 @@ svetoslavganov@google.com hackbod@google.com yamasani@google.com toddke@google.com +patb@google.com cbrubaker@google.com omakoto@google.com michaelwr@google.com diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt index 5a525974f3cb..9e603561acf1 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt @@ -114,7 +114,7 @@ class ControlsUiControllerImpl @Inject constructor ( private val onSeedingComplete = Consumer<Boolean> { accepted -> if (accepted) { - selectedStructure = controlsController.get().getFavorites().maxBy { + selectedStructure = controlsController.get().getFavorites().maxByOrNull { it.controls.size } ?: EMPTY_STRUCTURE updatePreferences(selectedStructure) diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipBuilder.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipBuilder.kt index 1d2e74703b42..eec69f98b9be 100644 --- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipBuilder.kt +++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipBuilder.kt @@ -28,7 +28,7 @@ class PrivacyChipBuilder(private val context: Context, itemsList: List<PrivacyIt appsAndTypes = itemsList.groupBy({ it.application }, { it.privacyType }) .toList() .sortedWith(compareBy({ -it.second.size }, // Sort by number of AppOps - { it.second.min() })) // Sort by "smallest" AppOpp (Location is largest) + { it.second.minOrNull() })) // Sort by "smallest" AppOpp (Location is largest) types = itemsList.map { it.privacyType }.distinct().sorted() } diff --git a/services/OWNERS b/services/OWNERS index 03e0807eea62..3b972e922e95 100644 --- a/services/OWNERS +++ b/services/OWNERS @@ -3,4 +3,4 @@ per-file Android.bp = file:platform/build/soong:/OWNERS # art-team@ manages the system server profile per-file art-profile* = calin@google.com, mathieuc@google.com, ngeoffray@google.com -per-file java/com/android/server/* = toddke@google.com +per-file java/com/android/server/* = toddke@google.com,patb@google.com diff --git a/services/core/Android.bp b/services/core/Android.bp index 0ac8f74ff831..706f738d754d 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -10,7 +10,6 @@ package { filegroup { name: "services.core-sources", srcs: ["java/**/*.java"], - exclude_srcs: [":connectivity-service-srcs"], path: "java", visibility: ["//frameworks/base/services"], } @@ -200,29 +199,3 @@ prebuilt_etc { src: ":services.core.json.gz", } -// TODO: Move connectivity service sources to independent directory. -filegroup { - name: "connectivity-service-srcs", - srcs: [ - "java/com/android/server/ConnectivityService.java", - "java/com/android/server/ConnectivityServiceInitializer.java", - "java/com/android/server/TestNetworkService.java", - "java/com/android/server/connectivity/AutodestructReference.java", - "java/com/android/server/connectivity/ConnectivityConstants.java", - "java/com/android/server/connectivity/DnsManager.java", - "java/com/android/server/connectivity/FullScore.java", - "java/com/android/server/connectivity/KeepaliveTracker.java", - "java/com/android/server/connectivity/LingerMonitor.java", - "java/com/android/server/connectivity/MockableSystemProperties.java", - "java/com/android/server/connectivity/Nat464Xlat.java", - "java/com/android/server/connectivity/NetworkAgentInfo.java", - "java/com/android/server/connectivity/NetworkDiagnostics.java", - "java/com/android/server/connectivity/NetworkNotificationManager.java", - "java/com/android/server/connectivity/NetworkRanker.java", - "java/com/android/server/connectivity/PermissionMonitor.java", - "java/com/android/server/connectivity/ProxyTracker.java", - "java/com/android/server/connectivity/QosCallbackAgentConnection.java", - "java/com/android/server/connectivity/QosCallbackTracker.java", - "java/com/android/server/connectivity/TcpKeepaliveController.java", - ], -} diff --git a/services/core/java/android/os/BatteryStatsInternal.java b/services/core/java/android/os/BatteryStatsInternal.java index 679f18e1e860..7cf5fd621f18 100644 --- a/services/core/java/android/os/BatteryStatsInternal.java +++ b/services/core/java/android/os/BatteryStatsInternal.java @@ -16,6 +16,10 @@ package android.os; +import com.android.internal.os.BinderCallsStats; + +import java.util.Collection; + /** * Battery stats local system service interface. This is used to pass internal data out of * BatteryStatsImpl, as well as make unchecked calls into BatteryStatsImpl. @@ -41,4 +45,10 @@ public abstract class BatteryStatsInternal { * @param sinceLast how long in millis has it been since a job was run */ public abstract void noteJobsDeferred(int uid, int numDeferred, long sinceLast); + + /** + * Informs battery stats of binder stats for the given work source UID. + */ + public abstract void noteBinderCallStats(int workSourceUid, long incrementalBinderCallCount, + Collection<BinderCallsStats.CallStat> callStats); } diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java index f4a8f372bc36..339ca84c93cf 100644 --- a/services/core/java/com/android/server/BinderCallsStatsService.java +++ b/services/core/java/com/android/server/BinderCallsStatsService.java @@ -26,6 +26,7 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.database.ContentObserver; import android.net.Uri; +import android.os.BatteryStatsInternal; import android.os.Binder; import android.os.Process; import android.os.SystemProperties; @@ -173,10 +174,10 @@ public class BinderCallsStatsService extends Binder { } try { - mParser.setString(Settings.Global.getString(mContext.getContentResolver(), - Settings.Global.BINDER_CALLS_STATS)); + mParser.setString(Settings.Global.getString(mContext.getContentResolver(), + Settings.Global.BINDER_CALLS_STATS)); } catch (IllegalArgumentException e) { - Slog.e(TAG, "Bad binder call stats settings", e); + Slog.e(TAG, "Bad binder call stats settings", e); } mBinderCallsStats.setDetailedTracking(mParser.getBoolean( SETTINGS_DETAILED_TRACKING_KEY, BinderCallsStats.DETAILED_TRACKING_DEFAULT)); @@ -298,6 +299,11 @@ public class BinderCallsStatsService extends Binder { CachedDeviceState.Readonly deviceState = getLocalService( CachedDeviceState.Readonly.class); mBinderCallsStats.setDeviceState(deviceState); + + BatteryStatsInternal batteryStatsInternal = getLocalService( + BatteryStatsInternal.class); + mBinderCallsStats.setCallStatsObserver(batteryStatsInternal::noteBinderCallStats); + // It needs to be called before mService.systemReady to make sure the observer is // initialized before installing it. mWorkSourceProvider.systemReady(getContext()); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 2744f11f1c4e..5122be2b10c4 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -10272,11 +10272,13 @@ public class ActivityManagerService extends IActivityManager.Stub if (lines > 0) { sb.append("\n"); - // Merge several logcat streams, and take the last N lines InputStreamReader input = null; try { java.lang.Process logcat = new ProcessBuilder( - "/system/bin/timeout", "-k", "15s", "10s", + // Time out after 10s, but kill logcat with SEGV + // so we can investigate why it didn't finish. + "/system/bin/timeout", "-s", "SEGV", "10s", + // Merge several logcat streams, and take the last N lines. "/system/bin/logcat", "-v", "threadtime", "-b", "events", "-b", "system", "-b", "main", "-b", "crash", "-t", String.valueOf(lines)) .redirectErrorStream(true).start(); diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index 226802c74f25..b45237caec26 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -66,6 +66,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.app.IBatteryStats; import com.android.internal.os.BatteryStatsHelper; import com.android.internal.os.BatteryStatsImpl; +import com.android.internal.os.BinderCallsStats; import com.android.internal.os.PowerProfile; import com.android.internal.os.RailStats; import com.android.internal.os.RpmStats; @@ -87,6 +88,7 @@ import java.nio.charset.CharsetDecoder; import java.nio.charset.CodingErrorAction; import java.nio.charset.StandardCharsets; import java.util.Arrays; +import java.util.Collection; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; @@ -304,6 +306,12 @@ public final class BatteryStatsService extends IBatteryStats.Stub if (DBG) Slog.d(TAG, "Jobs deferred " + uid + ": " + numDeferred + " " + sinceLast); BatteryStatsService.this.noteJobsDeferred(uid, numDeferred, sinceLast); } + + @Override + public void noteBinderCallStats(int workSourceUid, long incrementatCallCount, + Collection<BinderCallsStats.CallStat> callStats) { + mStats.noteBinderCallStats(workSourceUid, incrementatCallCount, callStats); + } } private static void awaitUninterruptibly(Future<?> future) { @@ -1771,5 +1779,4 @@ public final class BatteryStatsService extends IBatteryStats.Stub Binder.restoreCallingIdentity(ident); } } - } diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS index 90d940939be8..0c8114cdf2e2 100644 --- a/services/core/java/com/android/server/am/OWNERS +++ b/services/core/java/com/android/server/am/OWNERS @@ -20,6 +20,7 @@ ogunwale@google.com # Permissions & Packages svetoslavganov@google.com toddke@google.com +patb@google.com # Battery Stats joeo@google.com diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index 115899a2a518..668d290cbad3 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -2026,8 +2026,7 @@ public class InputManagerService extends IInputManager.Stub }; for (File baseDir: baseDirs) { File confFile = new File(baseDir, EXCLUDED_DEVICES_PATH); - try { - InputStream stream = new FileInputStream(confFile); + try (InputStream stream = new FileInputStream(confFile)) { names.addAll(ConfigurationProcessor.processExcludedDeviceNames(stream)); } catch (FileNotFoundException e) { // It's ok if the file does not exist. @@ -2060,8 +2059,7 @@ public class InputManagerService extends IInputManager.Stub final File baseDir = Environment.getVendorDirectory(); final File confFile = new File(baseDir, PORT_ASSOCIATIONS_PATH); - try { - final InputStream stream = new FileInputStream(confFile); + try (final InputStream stream = new FileInputStream(confFile)) { return ConfigurationProcessor.processInputPortAssociations(stream); } catch (FileNotFoundException e) { // Most of the time, file will not exist, which is expected. @@ -2173,10 +2171,10 @@ public class InputManagerService extends IInputManager.Stub @Override public void visitKeyboardLayout(Resources resources, int keyboardLayoutResId, KeyboardLayout layout) { - try { + try (final InputStreamReader stream = new InputStreamReader( + resources.openRawResource(keyboardLayoutResId))) { result[0] = layout.getDescriptor(); - result[1] = Streams.readFully(new InputStreamReader( - resources.openRawResource(keyboardLayoutResId))); + result[1] = Streams.readFully(stream); } catch (IOException ex) { } catch (NotFoundException ex) { } diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index e7c0a50163da..431b00914f02 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -382,8 +382,8 @@ public class NetworkStatsFactory { // Migrate data usage over a VPN to the TUN network. for (UnderlyingNetworkInfo info : vpnArray) { - delta.migrateTun(info.getOwnerUid(), info.getIface(), - info.getUnderlyingIfaces()); + delta.migrateTun(info.getOwnerUid(), info.getInterface(), + info.getUnderlyingInterfaces()); // Filter out debug entries as that may lead to over counting. delta.filterDebugEntries(); } diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 3c14440c6467..4ee867b7d051 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -181,7 +181,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private static final int MSG_PERFORM_POLL = 1; // Perform polling, persist network, and register the global alert again. private static final int MSG_PERFORM_POLL_REGISTER_ALERT = 2; - private static final int MSG_UPDATE_IFACES = 3; + private static final int MSG_NOTIFY_NETWORK_STATUS = 3; // A message for broadcasting ACTION_NETWORK_STATS_UPDATED in handler thread to prevent // deadlock. private static final int MSG_BROADCAST_NETWORK_STATS_UPDATED = 4; @@ -379,11 +379,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { performPoll(FLAG_PERSIST_ALL); break; } - case MSG_UPDATE_IFACES: { + case MSG_NOTIFY_NETWORK_STATUS: { // If no cached states, ignore. if (mLastNetworkStateSnapshots == null) break; // TODO (b/181642673): Protect mDefaultNetworks from concurrent accessing. - updateIfaces(mDefaultNetworks, mLastNetworkStateSnapshots, mActiveIface); + handleNotifyNetworkStatus( + mDefaultNetworks, mLastNetworkStateSnapshots, mActiveIface); break; } case MSG_PERFORM_POLL_REGISTER_ALERT: { @@ -474,7 +475,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @NonNull Looper looper, @NonNull Executor executor, @NonNull NetworkStatsService service) { // TODO: Update RatType passively in NSS, instead of querying into the monitor - // when forceUpdateIface. + // when notifyNetworkStatus. return new NetworkStatsSubscriptionsMonitor(context, looper, executor, (subscriberId, type) -> service.handleOnCollapsedRatTypeChanged()); } @@ -971,16 +972,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - public void forceUpdateIfaces( - Network[] defaultNetworks, - NetworkStateSnapshot[] networkStates, - String activeIface, - UnderlyingNetworkInfo[] underlyingNetworkInfos) { + /** + * Notify {@code NetworkStatsService} about network status changed. + */ + public void notifyNetworkStatus( + @NonNull Network[] defaultNetworks, + @NonNull NetworkStateSnapshot[] networkStates, + @Nullable String activeIface, + @NonNull UnderlyingNetworkInfo[] underlyingNetworkInfos) { checkNetworkStackPermission(mContext); final long token = Binder.clearCallingIdentity(); try { - updateIfaces(defaultNetworks, networkStates, activeIface); + handleNotifyNetworkStatus(defaultNetworks, networkStates, activeIface); } finally { Binder.restoreCallingIdentity(token); } @@ -1244,12 +1248,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @VisibleForTesting public void handleOnCollapsedRatTypeChanged() { // Protect service from frequently updating. Remove pending messages if any. - mHandler.removeMessages(MSG_UPDATE_IFACES); + mHandler.removeMessages(MSG_NOTIFY_NETWORK_STATUS); mHandler.sendMessageDelayed( - mHandler.obtainMessage(MSG_UPDATE_IFACES), mSettings.getPollDelay()); + mHandler.obtainMessage(MSG_NOTIFY_NETWORK_STATUS), mSettings.getPollDelay()); } - private void updateIfaces( + private void handleNotifyNetworkStatus( Network[] defaultNetworks, NetworkStateSnapshot[] snapshots, String activeIface) { @@ -1257,7 +1261,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mWakeLock.acquire(); try { mActiveIface = activeIface; - updateIfacesLocked(defaultNetworks, snapshots); + handleNotifyNetworkStatusLocked(defaultNetworks, snapshots); } finally { mWakeLock.release(); } @@ -1270,10 +1274,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * they are combined under a single {@link NetworkIdentitySet}. */ @GuardedBy("mStatsLock") - private void updateIfacesLocked(@NonNull Network[] defaultNetworks, + private void handleNotifyNetworkStatusLocked(@NonNull Network[] defaultNetworks, @NonNull NetworkStateSnapshot[] snapshots) { if (!mSystemReady) return; - if (LOGV) Slog.v(TAG, "updateIfacesLocked()"); + if (LOGV) Slog.v(TAG, "handleNotifyNetworkStatusLocked()"); // take one last stats snapshot before updating iface mapping. this // isn't perfect, since the kernel may already be counting traffic from diff --git a/services/core/java/com/android/server/os/OWNERS b/services/core/java/com/android/server/os/OWNERS new file mode 100644 index 000000000000..19573323e5ad --- /dev/null +++ b/services/core/java/com/android/server/os/OWNERS @@ -0,0 +1,2 @@ +# Bugreporting +per-file Bugreport* = file:/platform/frameworks/native:/cmds/dumpstate/OWNERS diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java index 77c1c1db2257..49a0a8827699 100644 --- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java +++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java @@ -31,6 +31,9 @@ import android.content.IntentFilter; import android.content.pm.PackageInfo; import android.os.BatteryManagerInternal; import android.os.Environment; +import android.os.IThermalService; +import android.os.PowerManager; +import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemProperties; import android.os.UserHandle; @@ -82,10 +85,15 @@ public class BackgroundDexOptService extends JobService { private static final int OPTIMIZE_ABORT_BY_JOB_SCHEDULER = 2; // Optimizations should be aborted. No space left on device. private static final int OPTIMIZE_ABORT_NO_SPACE_LEFT = 3; + // Optimizations should be aborted. Thermal throttling level too high. + private static final int OPTIMIZE_ABORT_THERMAL = 4; // Used for calculating space threshold for downgrading unused apps. private static final int LOW_THRESHOLD_MULTIPLIER_FOR_DOWNGRADE = 2; + // Thermal cutoff value used if one isn't defined by a system property. + private static final int THERMAL_CUTOFF_DEFAULT = PowerManager.THERMAL_STATUS_MODERATE; + /** * Set of failed packages remembered across job runs. */ @@ -107,8 +115,14 @@ public class BackgroundDexOptService extends JobService { private static final long mDowngradeUnusedAppsThresholdInMillis = getDowngradeUnusedAppsThresholdInMillis(); + private final IThermalService mThermalService = + IThermalService.Stub.asInterface( + ServiceManager.getService(Context.THERMAL_SERVICE)); + private static List<PackagesUpdatedListener> sPackagesUpdatedListeners = new ArrayList<>(); + private int mThermalStatusCutoff = THERMAL_CUTOFF_DEFAULT; + public static void schedule(Context context) { if (isBackgroundDexoptDisabled()) { return; @@ -251,12 +265,18 @@ public class BackgroundDexOptService extends JobService { Slog.w(TAG, "Idle optimizations aborted because of space constraints."); } else if (result == OPTIMIZE_ABORT_BY_JOB_SCHEDULER) { Slog.w(TAG, "Idle optimizations aborted by job scheduler."); + } else if (result == OPTIMIZE_ABORT_THERMAL) { + Slog.w(TAG, "Idle optimizations aborted by thermal throttling."); } else { Slog.w(TAG, "Idle optimizations ended with unexpected code: " + result); } - if (result != OPTIMIZE_ABORT_BY_JOB_SCHEDULER) { + + if (result == OPTIMIZE_ABORT_THERMAL) { + // Abandon our timeslice and reschedule + jobFinished(jobParams, /* wantsReschedule */ true); + } else if (result != OPTIMIZE_ABORT_BY_JOB_SCHEDULER) { // Abandon our timeslice and do not reschedule. - jobFinished(jobParams, /* reschedule */ false); + jobFinished(jobParams, /* wantsReschedule */ false); } } }.start(); @@ -542,6 +562,24 @@ public class BackgroundDexOptService extends JobService { // JobScheduler requested an early abort. return OPTIMIZE_ABORT_BY_JOB_SCHEDULER; } + + // Abort background dexopt if the device is in a moderate or stronger thermal throttling + // state. + try { + final int thermalStatus = mThermalService.getCurrentThermalStatus(); + + if (DEBUG) { + Log.i(TAG, "Thermal throttling status during bgdexopt: " + thermalStatus); + } + + if (thermalStatus >= mThermalStatusCutoff) { + return OPTIMIZE_ABORT_THERMAL; + } + } catch (RemoteException ex) { + // Because this is a intra-process Binder call it is impossible for a RemoteException + // to be raised. + } + long usableSpace = mDataDir.getUsableSpace(); if (usableSpace < lowStorageThreshold) { // Rather bail than completely fill up the disk. @@ -603,6 +641,9 @@ public class BackgroundDexOptService extends JobService { return false; } + mThermalStatusCutoff = + SystemProperties.getInt("dalvik.vm.dexopt.thermal-cutoff", THERMAL_CUTOFF_DEFAULT); + boolean result; if (params.getJobId() == JOB_POST_BOOT_UPDATE) { result = runPostBootUpdate(params, pm, pkgs); diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index fa64df5b1670..836e6150414c 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -5257,6 +5257,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { long[] pattern; switch (effectId) { case HapticFeedbackConstants.CONTEXT_CLICK: + case HapticFeedbackConstants.GESTURE_END: return VibrationEffect.get(VibrationEffect.EFFECT_TICK); case HapticFeedbackConstants.TEXT_HANDLE_MOVE: if (!mHapticTextHandleEnabled) { @@ -5269,7 +5270,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { case HapticFeedbackConstants.VIRTUAL_KEY_RELEASE: case HapticFeedbackConstants.ENTRY_BUMP: case HapticFeedbackConstants.DRAG_CROSSING: - case HapticFeedbackConstants.GESTURE_END: return VibrationEffect.get(VibrationEffect.EFFECT_TICK, false); case HapticFeedbackConstants.KEYBOARD_TAP: // == KEYBOARD_PRESS case HapticFeedbackConstants.VIRTUAL_KEY: diff --git a/services/core/java/com/android/server/vcn/OWNERS b/services/core/java/com/android/server/vcn/OWNERS index 33b9f0f75f81..2441e772468c 100644 --- a/services/core/java/com/android/server/vcn/OWNERS +++ b/services/core/java/com/android/server/vcn/OWNERS @@ -3,5 +3,5 @@ set noparent benedictwong@google.com ckesting@google.com evitayan@google.com +junyin@google.com nharold@google.com -jchalard@google.com
\ No newline at end of file diff --git a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java index 19fbdbd86099..5565ccb6cf7c 100644 --- a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java +++ b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java @@ -145,7 +145,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { */ public void handleSubscriptionsChanged() { final Map<ParcelUuid, Set<String>> privilegedPackages = new HashMap<>(); - final Map<Integer, ParcelUuid> newSubIdToGroupMap = new HashMap<>(); + final Map<Integer, SubscriptionInfo> newSubIdToInfoMap = new HashMap<>(); final List<SubscriptionInfo> allSubs = mSubscriptionManager.getAllSubscriptionInfoList(); if (allSubs == null) { @@ -160,7 +160,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { } // Build subId -> subGrp cache - newSubIdToGroupMap.put(subInfo.getSubscriptionId(), subInfo.getGroupUuid()); + newSubIdToInfoMap.put(subInfo.getSubscriptionId(), subInfo); // Update subscription groups that are both ready, and active. For a group to be // considered active, both of the following must be true: @@ -186,7 +186,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { } final TelephonySubscriptionSnapshot newSnapshot = - new TelephonySubscriptionSnapshot(newSubIdToGroupMap, privilegedPackages); + new TelephonySubscriptionSnapshot(newSubIdToInfoMap, privilegedPackages); // If snapshot was meaningfully updated, fire the callback if (!newSnapshot.equals(mCurrentSnapshot)) { @@ -245,7 +245,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { /** TelephonySubscriptionSnapshot is a class containing info about active subscriptions */ public static class TelephonySubscriptionSnapshot { - private final Map<Integer, ParcelUuid> mSubIdToGroupMap; + private final Map<Integer, SubscriptionInfo> mSubIdToInfoMap; private final Map<ParcelUuid, Set<String>> mPrivilegedPackages; public static final TelephonySubscriptionSnapshot EMPTY_SNAPSHOT = @@ -253,12 +253,12 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { @VisibleForTesting(visibility = Visibility.PRIVATE) TelephonySubscriptionSnapshot( - @NonNull Map<Integer, ParcelUuid> subIdToGroupMap, + @NonNull Map<Integer, SubscriptionInfo> subIdToInfoMap, @NonNull Map<ParcelUuid, Set<String>> privilegedPackages) { - Objects.requireNonNull(subIdToGroupMap, "subIdToGroupMap was null"); + Objects.requireNonNull(subIdToInfoMap, "subIdToInfoMap was null"); Objects.requireNonNull(privilegedPackages, "privilegedPackages was null"); - mSubIdToGroupMap = Collections.unmodifiableMap(subIdToGroupMap); + mSubIdToInfoMap = Collections.unmodifiableMap(subIdToInfoMap); final Map<ParcelUuid, Set<String>> unmodifiableInnerSets = new ArrayMap<>(); for (Entry<ParcelUuid, Set<String>> entry : privilegedPackages.entrySet()) { @@ -285,7 +285,9 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { /** Returns the Subscription Group for a given subId. */ @Nullable public ParcelUuid getGroupForSubId(int subId) { - return mSubIdToGroupMap.get(subId); + return mSubIdToInfoMap.containsKey(subId) + ? mSubIdToInfoMap.get(subId).getGroupUuid() + : null; } /** @@ -295,8 +297,8 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { public Set<Integer> getAllSubIdsInGroup(ParcelUuid subGrp) { final Set<Integer> subIds = new ArraySet<>(); - for (Entry<Integer, ParcelUuid> entry : mSubIdToGroupMap.entrySet()) { - if (subGrp.equals(entry.getValue())) { + for (Entry<Integer, SubscriptionInfo> entry : mSubIdToInfoMap.entrySet()) { + if (subGrp.equals(entry.getValue().getGroupUuid())) { subIds.add(entry.getKey()); } } @@ -304,9 +306,17 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { return subIds; } + /** Checks if the requested subscription is opportunistic */ + @NonNull + public boolean isOpportunistic(int subId) { + return mSubIdToInfoMap.containsKey(subId) + ? mSubIdToInfoMap.get(subId).isOpportunistic() + : false; + } + @Override public int hashCode() { - return Objects.hash(mSubIdToGroupMap, mPrivilegedPackages); + return Objects.hash(mSubIdToInfoMap, mPrivilegedPackages); } @Override @@ -317,7 +327,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { final TelephonySubscriptionSnapshot other = (TelephonySubscriptionSnapshot) obj; - return mSubIdToGroupMap.equals(other.mSubIdToGroupMap) + return mSubIdToInfoMap.equals(other.mSubIdToInfoMap) && mPrivilegedPackages.equals(other.mPrivilegedPackages); } @@ -326,7 +336,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { pw.println("TelephonySubscriptionSnapshot:"); pw.increaseIndent(); - pw.println("mSubIdToGroupMap: " + mSubIdToGroupMap); + pw.println("mSubIdToInfoMap: " + mSubIdToInfoMap); pw.println("mPrivilegedPackages: " + mPrivilegedPackages); pw.decreaseIndent(); @@ -335,7 +345,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { @Override public String toString() { return "TelephonySubscriptionSnapshot{ " - + "mSubIdToGroupMap=" + mSubIdToGroupMap + + "mSubIdToInfoMap=" + mSubIdToInfoMap + ", mPrivilegedPackages=" + mPrivilegedPackages + " }"; } diff --git a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java index 3bdeec0c1d8e..b05662e1678e 100644 --- a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java +++ b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java @@ -16,6 +16,10 @@ package com.android.server.vcn; +import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; +import static android.net.NetworkCapabilities.TRANSPORT_WIFI; +import static android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener; + import android.annotation.NonNull; import android.annotation.Nullable; import android.net.ConnectivityManager; @@ -25,8 +29,16 @@ import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkRequest; import android.net.TelephonyNetworkSpecifier; +import android.net.vcn.VcnManager; import android.os.Handler; +import android.os.HandlerExecutor; import android.os.ParcelUuid; +import android.os.PersistableBundle; +import android.telephony.CarrierConfigManager; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyCallback; +import android.telephony.TelephonyManager; +import android.util.ArrayMap; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; @@ -35,9 +47,13 @@ import com.android.internal.util.IndentingPrintWriter; import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.TreeSet; /** * Tracks a set of Networks underpinning a VcnGatewayConnection. @@ -51,19 +67,62 @@ import java.util.Set; public class UnderlyingNetworkTracker { @NonNull private static final String TAG = UnderlyingNetworkTracker.class.getSimpleName(); + /** + * Minimum signal strength for a WiFi network to be eligible for switching to + * + * <p>A network that satisfies this is eligible to become the selected underlying network with + * no additional conditions + */ + @VisibleForTesting(visibility = Visibility.PRIVATE) + static final int WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT = -70; + + /** + * Minimum signal strength to continue using a WiFi network + * + * <p>A network that satisfies the conditions may ONLY continue to be used if it is already + * selected as the underlying network. A WiFi network satisfying this condition, but NOT the + * prospective-network RSSI threshold CANNOT be switched to. + */ + @VisibleForTesting(visibility = Visibility.PRIVATE) + static final int WIFI_EXIT_RSSI_THRESHOLD_DEFAULT = -74; + + /** Priority for any cellular network for which the subscription is listed as opportunistic */ + @VisibleForTesting(visibility = Visibility.PRIVATE) + static final int PRIORITY_OPPORTUNISTIC_CELLULAR = 0; + + /** Priority for any WiFi network which is in use, and satisfies the in-use RSSI threshold */ + @VisibleForTesting(visibility = Visibility.PRIVATE) + static final int PRIORITY_WIFI_IN_USE = 1; + + /** Priority for any WiFi network which satisfies the prospective-network RSSI threshold */ + @VisibleForTesting(visibility = Visibility.PRIVATE) + static final int PRIORITY_WIFI_PROSPECTIVE = 2; + + /** Priority for any standard macro cellular network */ + @VisibleForTesting(visibility = Visibility.PRIVATE) + static final int PRIORITY_MACRO_CELLULAR = 3; + + /** Priority for any other networks (including unvalidated, etc) */ + @VisibleForTesting(visibility = Visibility.PRIVATE) + static final int PRIORITY_ANY = Integer.MAX_VALUE; + @NonNull private final VcnContext mVcnContext; @NonNull private final ParcelUuid mSubscriptionGroup; - @NonNull private final Set<Integer> mRequiredUnderlyingNetworkCapabilities; @NonNull private final UnderlyingNetworkTrackerCallback mCb; @NonNull private final Dependencies mDeps; @NonNull private final Handler mHandler; @NonNull private final ConnectivityManager mConnectivityManager; + @NonNull private final TelephonyCallback mActiveDataSubIdListener = + new VcnActiveDataSubscriptionIdListener(); @NonNull private final List<NetworkCallback> mCellBringupCallbacks = new ArrayList<>(); @Nullable private NetworkCallback mWifiBringupCallback; - @Nullable private NetworkCallback mRouteSelectionCallback; + @Nullable private NetworkCallback mWifiEntryRssiThresholdCallback; + @Nullable private NetworkCallback mWifiExitRssiThresholdCallback; + @Nullable private UnderlyingNetworkListener mRouteSelectionCallback; @NonNull private TelephonySubscriptionSnapshot mLastSnapshot; + @Nullable private PersistableBundle mCarrierConfig; private boolean mIsQuitting = false; @Nullable private UnderlyingNetworkRecord mCurrentRecord; @@ -73,13 +132,11 @@ public class UnderlyingNetworkTracker { @NonNull VcnContext vcnContext, @NonNull ParcelUuid subscriptionGroup, @NonNull TelephonySubscriptionSnapshot snapshot, - @NonNull Set<Integer> requiredUnderlyingNetworkCapabilities, @NonNull UnderlyingNetworkTrackerCallback cb) { this( vcnContext, subscriptionGroup, snapshot, - requiredUnderlyingNetworkCapabilities, cb, new Dependencies()); } @@ -88,22 +145,41 @@ public class UnderlyingNetworkTracker { @NonNull VcnContext vcnContext, @NonNull ParcelUuid subscriptionGroup, @NonNull TelephonySubscriptionSnapshot snapshot, - @NonNull Set<Integer> requiredUnderlyingNetworkCapabilities, @NonNull UnderlyingNetworkTrackerCallback cb, @NonNull Dependencies deps) { mVcnContext = Objects.requireNonNull(vcnContext, "Missing vcnContext"); mSubscriptionGroup = Objects.requireNonNull(subscriptionGroup, "Missing subscriptionGroup"); mLastSnapshot = Objects.requireNonNull(snapshot, "Missing snapshot"); - mRequiredUnderlyingNetworkCapabilities = - Objects.requireNonNull( - requiredUnderlyingNetworkCapabilities, - "Missing requiredUnderlyingNetworkCapabilities"); mCb = Objects.requireNonNull(cb, "Missing cb"); mDeps = Objects.requireNonNull(deps, "Missing deps"); mHandler = new Handler(mVcnContext.getLooper()); mConnectivityManager = mVcnContext.getContext().getSystemService(ConnectivityManager.class); + mVcnContext + .getContext() + .getSystemService(TelephonyManager.class) + .registerTelephonyCallback(new HandlerExecutor(mHandler), mActiveDataSubIdListener); + + // TODO: Listen for changes in carrier config that affect this. + for (int subId : mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup)) { + PersistableBundle config = + mVcnContext + .getContext() + .getSystemService(CarrierConfigManager.class) + .getConfigForSubId(subId); + + if (config != null) { + mCarrierConfig = config; + + // Attempt to use (any) non-opportunistic subscription. If this subscription is + // opportunistic, continue and try to find a non-opportunistic subscription, using + // the opportunistic ones as a last resort. + if (!isOpportunistic(mLastSnapshot, Collections.singleton(subId))) { + break; + } + } + } registerOrUpdateNetworkRequests(); } @@ -111,16 +187,30 @@ public class UnderlyingNetworkTracker { private void registerOrUpdateNetworkRequests() { NetworkCallback oldRouteSelectionCallback = mRouteSelectionCallback; NetworkCallback oldWifiCallback = mWifiBringupCallback; + NetworkCallback oldWifiEntryRssiThresholdCallback = mWifiEntryRssiThresholdCallback; + NetworkCallback oldWifiExitRssiThresholdCallback = mWifiExitRssiThresholdCallback; List<NetworkCallback> oldCellCallbacks = new ArrayList<>(mCellBringupCallbacks); mCellBringupCallbacks.clear(); // Register new callbacks. Make-before-break; always register new callbacks before removal // of old callbacks if (!mIsQuitting) { - mRouteSelectionCallback = new RouteSelectionCallback(); - mConnectivityManager.requestBackgroundNetwork( + mRouteSelectionCallback = new UnderlyingNetworkListener(); + mConnectivityManager.registerNetworkCallback( getRouteSelectionRequest(), mRouteSelectionCallback, mHandler); + mWifiEntryRssiThresholdCallback = new NetworkBringupCallback(); + mConnectivityManager.registerNetworkCallback( + getWifiEntryRssiThresholdNetworkRequest(), + mWifiEntryRssiThresholdCallback, + mHandler); + + mWifiExitRssiThresholdCallback = new NetworkBringupCallback(); + mConnectivityManager.registerNetworkCallback( + getWifiExitRssiThresholdNetworkRequest(), + mWifiExitRssiThresholdCallback, + mHandler); + mWifiBringupCallback = new NetworkBringupCallback(); mConnectivityManager.requestBackgroundNetwork( getWifiNetworkRequest(), mWifiBringupCallback, mHandler); @@ -135,6 +225,8 @@ public class UnderlyingNetworkTracker { } else { mRouteSelectionCallback = null; mWifiBringupCallback = null; + mWifiEntryRssiThresholdCallback = null; + mWifiExitRssiThresholdCallback = null; // mCellBringupCallbacks already cleared above. } @@ -145,6 +237,12 @@ public class UnderlyingNetworkTracker { if (oldWifiCallback != null) { mConnectivityManager.unregisterNetworkCallback(oldWifiCallback); } + if (oldWifiEntryRssiThresholdCallback != null) { + mConnectivityManager.unregisterNetworkCallback(oldWifiEntryRssiThresholdCallback); + } + if (oldWifiExitRssiThresholdCallback != null) { + mConnectivityManager.unregisterNetworkCallback(oldWifiExitRssiThresholdCallback); + } for (NetworkCallback cellBringupCallback : oldCellCallbacks) { mConnectivityManager.unregisterNetworkCallback(cellBringupCallback); } @@ -168,6 +266,8 @@ public class UnderlyingNetworkTracker { } return getBaseNetworkRequestBuilder() + .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) + .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED) .setSubscriptionIds(mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup)) .build(); } @@ -189,6 +289,38 @@ public class UnderlyingNetworkTracker { } /** + * Builds the WiFi entry threshold signal strength request + * + * <p>This request ensures that WiFi reports the crossing of the wifi entry RSSI threshold. + * Without this request, WiFi rate-limits, and reports signal strength changes at too slow a + * pace to effectively select a short-lived WiFi offload network. + */ + private NetworkRequest getWifiEntryRssiThresholdNetworkRequest() { + return getBaseNetworkRequestBuilder() + .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) + .setSubscriptionIds(mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup)) + // Ensure wifi updates signal strengths when crossing this threshold. + .setSignalStrength(getWifiEntryRssiThreshold(mCarrierConfig)) + .build(); + } + + /** + * Builds the WiFi exit threshold signal strength request + * + * <p>This request ensures that WiFi reports the crossing of the wifi exit RSSI threshold. + * Without this request, WiFi rate-limits, and reports signal strength changes at too slow a + * pace to effectively select away from a failing WiFi network. + */ + private NetworkRequest getWifiExitRssiThresholdNetworkRequest() { + return getBaseNetworkRequestBuilder() + .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) + .setSubscriptionIds(mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup)) + // Ensure wifi updates signal strengths when crossing this threshold. + .setSignalStrength(getWifiExitRssiThreshold(mCarrierConfig)) + .build(); + } + + /** * Builds a Cellular bringup request for a given subId * * <p>This request is filed in order to ensure that the Telephony stack always has a @@ -233,10 +365,18 @@ public class UnderlyingNetworkTracker { * reevaluate its NetworkBringupCallbacks. This may result in NetworkRequests being registered * or unregistered if the subIds mapped to the this Tracker's SubscriptionGroup change. */ - public void updateSubscriptionSnapshot(@NonNull TelephonySubscriptionSnapshot snapshot) { - Objects.requireNonNull(snapshot, "Missing snapshot"); + public void updateSubscriptionSnapshot(@NonNull TelephonySubscriptionSnapshot newSnapshot) { + Objects.requireNonNull(newSnapshot, "Missing newSnapshot"); + + final TelephonySubscriptionSnapshot oldSnapshot = mLastSnapshot; + mLastSnapshot = newSnapshot; - mLastSnapshot = snapshot; + // Only trigger re-registration if subIds in this group have changed + if (oldSnapshot + .getAllSubIdsInGroup(mSubscriptionGroup) + .equals(newSnapshot.getAllSubIdsInGroup(mSubscriptionGroup))) { + return; + } registerOrUpdateNetworkRequests(); } @@ -247,88 +387,43 @@ public class UnderlyingNetworkTracker { // Will unregister all existing callbacks, but not register new ones due to quitting flag. registerOrUpdateNetworkRequests(); - } - /** Returns whether the currently selected Network matches the given network. */ - private static boolean isSameNetwork( - @Nullable UnderlyingNetworkRecord.Builder recordInProgress, @NonNull Network network) { - return recordInProgress != null && recordInProgress.getNetwork().equals(network); + mVcnContext + .getContext() + .getSystemService(TelephonyManager.class) + .unregisterTelephonyCallback(mActiveDataSubIdListener); } - /** Notify the Callback if a full UnderlyingNetworkRecord exists. */ - private void maybeNotifyCallback() { - // Only forward this update if a complete record has been received - if (!mRecordInProgress.isValid()) { - return; - } + private void reevaluateNetworks() { + TreeSet<UnderlyingNetworkRecord> sorted = + new TreeSet<>( + UnderlyingNetworkRecord.getComparator( + mSubscriptionGroup, mLastSnapshot, mCurrentRecord, mCarrierConfig)); + sorted.addAll(mRouteSelectionCallback.getUnderlyingNetworks()); - // Only forward this update if the updated record differs form the current record - UnderlyingNetworkRecord updatedRecord = mRecordInProgress.build(); - if (!updatedRecord.equals(mCurrentRecord)) { - mCurrentRecord = updatedRecord; - - mCb.onSelectedUnderlyingNetworkChanged(mCurrentRecord); - } - } - - private void handleNetworkAvailable(@NonNull Network network) { - mVcnContext.ensureRunningOnLooperThread(); - - mRecordInProgress = new UnderlyingNetworkRecord.Builder(network); - } - - private void handleNetworkLost(@NonNull Network network) { - mVcnContext.ensureRunningOnLooperThread(); - - if (!isSameNetwork(mRecordInProgress, network)) { - Slog.wtf(TAG, "Non-underlying Network lost"); + UnderlyingNetworkRecord candidate = sorted.isEmpty() ? null : sorted.first(); + if (Objects.equals(mCurrentRecord, candidate)) { return; } - mRecordInProgress = null; - mCurrentRecord = null; - mCb.onSelectedUnderlyingNetworkChanged(null /* underlyingNetworkRecord */); + mCurrentRecord = candidate; + mCb.onSelectedUnderlyingNetworkChanged(mCurrentRecord); } - private void handleCapabilitiesChanged( - @NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) { - mVcnContext.ensureRunningOnLooperThread(); - - if (!isSameNetwork(mRecordInProgress, network)) { - Slog.wtf(TAG, "Invalid update to NetworkCapabilities"); - return; + private static boolean isOpportunistic( + @NonNull TelephonySubscriptionSnapshot snapshot, Set<Integer> subIds) { + if (snapshot == null) { + Slog.wtf(TAG, "Got null snapshot"); + return false; } - mRecordInProgress.setNetworkCapabilities(networkCapabilities); - - maybeNotifyCallback(); - } - - private void handlePropertiesChanged( - @NonNull Network network, @NonNull LinkProperties linkProperties) { - mVcnContext.ensureRunningOnLooperThread(); - - if (!isSameNetwork(mRecordInProgress, network)) { - Slog.wtf(TAG, "Invalid update to LinkProperties"); - return; - } - - mRecordInProgress.setLinkProperties(linkProperties); - - maybeNotifyCallback(); - } - - private void handleNetworkBlocked(@NonNull Network network, boolean isBlocked) { - mVcnContext.ensureRunningOnLooperThread(); - - if (!isSameNetwork(mRecordInProgress, network)) { - Slog.wtf(TAG, "Invalid update to isBlocked"); - return; + for (int subId : subIds) { + if (snapshot.isOpportunistic(subId)) { + return true; + } } - mRecordInProgress.setIsBlocked(isBlocked); - - maybeNotifyCallback(); + return false; } /** @@ -347,36 +442,104 @@ public class UnderlyingNetworkTracker { * truth. */ @VisibleForTesting - class RouteSelectionCallback extends NetworkCallback { + class UnderlyingNetworkListener extends NetworkCallback { + private final Map<Network, UnderlyingNetworkRecord.Builder> + mUnderlyingNetworkRecordBuilders = new ArrayMap<>(); + + private List<UnderlyingNetworkRecord> getUnderlyingNetworks() { + final List<UnderlyingNetworkRecord> records = new ArrayList<>(); + + for (UnderlyingNetworkRecord.Builder builder : + mUnderlyingNetworkRecordBuilders.values()) { + if (builder.isValid()) { + records.add(builder.build()); + } + } + + return records; + } + @Override public void onAvailable(@NonNull Network network) { - handleNetworkAvailable(network); + mUnderlyingNetworkRecordBuilders.put( + network, new UnderlyingNetworkRecord.Builder(network)); } @Override public void onLost(@NonNull Network network) { - handleNetworkLost(network); + mUnderlyingNetworkRecordBuilders.remove(network); + + reevaluateNetworks(); } @Override public void onCapabilitiesChanged( @NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) { - if (networkCapabilities.equals(mRecordInProgress.getNetworkCapabilities())) return; - handleCapabilitiesChanged(network, networkCapabilities); + final UnderlyingNetworkRecord.Builder builder = + mUnderlyingNetworkRecordBuilders.get(network); + if (builder == null) { + Slog.wtf(TAG, "Got capabilities change for unknown key: " + network); + return; + } + + builder.setNetworkCapabilities(networkCapabilities); + if (builder.isValid()) { + reevaluateNetworks(); + } } @Override public void onLinkPropertiesChanged( @NonNull Network network, @NonNull LinkProperties linkProperties) { - handlePropertiesChanged(network, linkProperties); + final UnderlyingNetworkRecord.Builder builder = + mUnderlyingNetworkRecordBuilders.get(network); + if (builder == null) { + Slog.wtf(TAG, "Got link properties change for unknown key: " + network); + return; + } + + builder.setLinkProperties(linkProperties); + if (builder.isValid()) { + reevaluateNetworks(); + } } @Override public void onBlockedStatusChanged(@NonNull Network network, boolean isBlocked) { - handleNetworkBlocked(network, isBlocked); + final UnderlyingNetworkRecord.Builder builder = + mUnderlyingNetworkRecordBuilders.get(network); + if (builder == null) { + Slog.wtf(TAG, "Got blocked status change for unknown key: " + network); + return; + } + + builder.setIsBlocked(isBlocked); + if (builder.isValid()) { + reevaluateNetworks(); + } } } + private static int getWifiEntryRssiThreshold(@Nullable PersistableBundle carrierConfig) { + if (carrierConfig != null) { + return carrierConfig.getInt( + VcnManager.VCN_NETWORK_SELECTION_WIFI_ENTRY_RSSI_THRESHOLD_KEY, + WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT); + } + + return WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT; + } + + private static int getWifiExitRssiThreshold(@Nullable PersistableBundle carrierConfig) { + if (carrierConfig != null) { + return carrierConfig.getInt( + VcnManager.VCN_NETWORK_SELECTION_WIFI_EXIT_RSSI_THRESHOLD_KEY, + WIFI_EXIT_RSSI_THRESHOLD_DEFAULT); + } + + return WIFI_EXIT_RSSI_THRESHOLD_DEFAULT; + } + /** A record of a single underlying network, caching relevant fields. */ public static class UnderlyingNetworkRecord { @NonNull public final Network network; @@ -413,6 +576,89 @@ public class UnderlyingNetworkTracker { return Objects.hash(network, networkCapabilities, linkProperties, isBlocked); } + /** + * Gives networks a priority class, based on the following priorities: + * + * <ol> + * <li>Opportunistic cellular + * <li>Carrier WiFi, signal strength >= WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT + * <li>Carrier WiFi, active network + signal strength >= WIFI_EXIT_RSSI_THRESHOLD_DEFAULT + * <li>Macro cellular + * <li>Any others + * </ol> + */ + private int calculatePriorityClass( + ParcelUuid subscriptionGroup, + TelephonySubscriptionSnapshot snapshot, + UnderlyingNetworkRecord currentlySelected, + PersistableBundle carrierConfig) { + final NetworkCapabilities caps = networkCapabilities; + + // mRouteSelectionNetworkRequest requires a network be both VALIDATED and NOT_SUSPENDED + + if (isBlocked) { + Slog.wtf(TAG, "Network blocked for System Server: " + network); + return PRIORITY_ANY; + } + + if (caps.hasTransport(TRANSPORT_CELLULAR) + && isOpportunistic(snapshot, caps.getSubscriptionIds())) { + // If this carrier is the active data provider, ensure that opportunistic is only + // ever prioritized if it is also the active data subscription. This ensures that + // if an opportunistic subscription is still in the process of being switched to, + // or switched away from, the VCN does not attempt to continue using it against the + // decision made at the telephony layer. Failure to do so may result in the modem + // switching back and forth. + // + // Allow the following two cases: + // 1. Active subId is NOT in the group that this VCN is supporting + // 2. This opportunistic subscription is for the active subId + if (!snapshot.getAllSubIdsInGroup(subscriptionGroup) + .contains(SubscriptionManager.getActiveDataSubscriptionId()) + || caps.getSubscriptionIds() + .contains(SubscriptionManager.getActiveDataSubscriptionId())) { + return PRIORITY_OPPORTUNISTIC_CELLULAR; + } + } + + if (caps.hasTransport(TRANSPORT_WIFI)) { + if (caps.getSignalStrength() >= getWifiExitRssiThreshold(carrierConfig) + && currentlySelected != null + && network.equals(currentlySelected.network)) { + return PRIORITY_WIFI_IN_USE; + } + + if (caps.getSignalStrength() >= getWifiEntryRssiThreshold(carrierConfig)) { + return PRIORITY_WIFI_PROSPECTIVE; + } + } + + // Disallow opportunistic subscriptions from matching PRIORITY_MACRO_CELLULAR, as might + // be the case when Default Data SubId (CBRS) != Active Data SubId (MACRO), as might be + // the case if the Default Data SubId does not support certain services (eg voice + // calling) + if (caps.hasTransport(TRANSPORT_CELLULAR) + && !isOpportunistic(snapshot, caps.getSubscriptionIds())) { + return PRIORITY_MACRO_CELLULAR; + } + + return PRIORITY_ANY; + } + + private static Comparator<UnderlyingNetworkRecord> getComparator( + ParcelUuid subscriptionGroup, + TelephonySubscriptionSnapshot snapshot, + UnderlyingNetworkRecord currentlySelected, + PersistableBundle carrierConfig) { + return (left, right) -> { + return Integer.compare( + left.calculatePriorityClass( + subscriptionGroup, snapshot, currentlySelected, carrierConfig), + right.calculatePriorityClass( + subscriptionGroup, snapshot, currentlySelected, carrierConfig)); + }; + } + /** Dumps the state of this record for logging and debugging purposes. */ public void dump(IndentingPrintWriter pw) { pw.println("UnderlyingNetworkRecord:"); @@ -434,6 +680,8 @@ public class UnderlyingNetworkTracker { boolean mIsBlocked; boolean mWasIsBlockedSet; + @Nullable private UnderlyingNetworkRecord mCached; + private Builder(@NonNull Network network) { mNetwork = network; } @@ -445,6 +693,7 @@ public class UnderlyingNetworkTracker { private void setNetworkCapabilities(@NonNull NetworkCapabilities networkCapabilities) { mNetworkCapabilities = networkCapabilities; + mCached = null; } @Nullable @@ -454,11 +703,13 @@ public class UnderlyingNetworkTracker { private void setLinkProperties(@NonNull LinkProperties linkProperties) { mLinkProperties = linkProperties; + mCached = null; } private void setIsBlocked(boolean isBlocked) { mIsBlocked = isBlocked; mWasIsBlockedSet = true; + mCached = null; } private boolean isValid() { @@ -466,12 +717,30 @@ public class UnderlyingNetworkTracker { } private UnderlyingNetworkRecord build() { - return new UnderlyingNetworkRecord( - mNetwork, mNetworkCapabilities, mLinkProperties, mIsBlocked); + if (!isValid()) { + throw new IllegalArgumentException( + "Called build before UnderlyingNetworkRecord was valid"); + } + + if (mCached == null) { + mCached = + new UnderlyingNetworkRecord( + mNetwork, mNetworkCapabilities, mLinkProperties, mIsBlocked); + } + + return mCached; } } } + private class VcnActiveDataSubscriptionIdListener extends TelephonyCallback + implements ActiveDataSubscriptionIdListener { + @Override + public void onActiveDataSubscriptionIdChanged(int subId) { + reevaluateNetworks(); + } + } + /** Callbacks for being notified of the changes in, or to the selected underlying network. */ public interface UnderlyingNetworkTrackerCallback { /** diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java index 5cecff6f93c1..dff04bfc6d7c 100644 --- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java +++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java @@ -673,7 +673,6 @@ public class VcnGatewayConnection extends StateMachine { mVcnContext, subscriptionGroup, mLastSnapshot, - mConnectionConfig.getAllUnderlyingCapabilities(), mUnderlyingNetworkTrackerCallback); mIpSecManager = mVcnContext.getContext().getSystemService(IpSecManager.class); @@ -2274,13 +2273,11 @@ public class VcnGatewayConnection extends StateMachine { VcnContext vcnContext, ParcelUuid subscriptionGroup, TelephonySubscriptionSnapshot snapshot, - Set<Integer> requiredUnderlyingNetworkCapabilities, UnderlyingNetworkTrackerCallback callback) { return new UnderlyingNetworkTracker( vcnContext, subscriptionGroup, snapshot, - requiredUnderlyingNetworkCapabilities, callback); } diff --git a/services/incremental/OWNERS b/services/incremental/OWNERS index ad5eca7f6daf..7ebb962c8feb 100644 --- a/services/incremental/OWNERS +++ b/services/incremental/OWNERS @@ -5,3 +5,4 @@ alexbuy@google.com schfan@google.com toddke@google.com zyy@google.com +patb@google.com diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java index a02a039c3beb..d041eecab17b 100644 --- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java @@ -159,13 +159,13 @@ import androidx.test.runner.AndroidJUnit4; import com.android.internal.util.test.BroadcastInterceptingContext; import com.android.internal.util.test.BroadcastInterceptingContext.FutureIntent; +import com.android.internal.util.test.FsUtil; import com.android.server.DeviceIdleInternal; import com.android.server.LocalServices; import com.android.server.usage.AppStandbyInternal; import com.google.common.util.concurrent.AbstractFuture; -import libcore.io.IoUtils; import libcore.io.Streams; import org.junit.After; @@ -2347,7 +2347,7 @@ public class NetworkPolicyManagerServiceTest { private void setNetpolicyXml(Context context) throws Exception { mPolicyDir = context.getFilesDir(); if (mPolicyDir.exists()) { - IoUtils.deleteContents(mPolicyDir); + FsUtil.deleteContents(mPolicyDir); } if (!TextUtils.isEmpty(mNetpolicyXml)) { final String assetPath = NETPOLICY_DIR + "/" + mNetpolicyXml; diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java index 579b33e9c283..e332d3ff2b4d 100644 --- a/telecomm/java/android/telecom/PhoneAccount.java +++ b/telecomm/java/android/telecom/PhoneAccount.java @@ -27,6 +27,7 @@ import android.net.Uri; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; +import android.telephony.CarrierConfigManager; import android.telephony.TelephonyManager; import android.text.TextUtils; @@ -283,10 +284,13 @@ public final class PhoneAccount implements Parcelable { * number relies on presence. Should only be set if the {@code PhoneAccount} also has * {@link #CAPABILITY_VIDEO_CALLING}. * <p> - * When set, the {@link ConnectionService} is responsible for toggling the + * Note: As of Android 12, using the * {@link android.provider.ContactsContract.Data#CARRIER_PRESENCE_VT_CAPABLE} bit on the * {@link android.provider.ContactsContract.Data#CARRIER_PRESENCE} column to indicate whether - * a contact's phone number supports video calling. + * a contact's phone number supports video calling has been deprecated and should only be used + * on devices where {@link CarrierConfigManager#KEY_USE_RCS_PRESENCE_BOOL} is set. On newer + * devices, applications must use {@link android.telephony.ims.RcsUceAdapter} instead to + * determine whether or not a contact's phone number supports carrier video calling. * <p> * See {@link #getCapabilities} */ diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index f6ba7becc922..eb423b4a9b53 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -36,6 +36,7 @@ import android.telephony.gba.UaSecurityProtocolIdentifier; import android.telephony.ims.ImsReasonInfo; import android.telephony.ims.ImsRegistrationAttributes; import android.telephony.ims.ImsSsData; +import android.telephony.ims.RcsUceAdapter; import android.telephony.ims.feature.MmTelFeature; import android.telephony.ims.feature.RcsFeature; @@ -4071,6 +4072,9 @@ public class CarrierConfigManager { * If this flag is disabled, the capabilities cache will not be refreshed internally at all * and will only be updated if the cached capabilities are stale when an application * requests them. + * + * @see RcsUceAdapter#isUceSettingEnabled() more information about this feature and how + * it is enabled by the user. */ public static final String KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL = KEY_PREFIX + "rcs_bulk_capability_exchange_bool"; diff --git a/telephony/java/android/telephony/ims/ImsRcsManager.java b/telephony/java/android/telephony/ims/ImsRcsManager.java index 5f4e1e6f3148..81d820731d05 100644 --- a/telephony/java/android/telephony/ims/ImsRcsManager.java +++ b/telephony/java/android/telephony/ims/ImsRcsManager.java @@ -56,7 +56,9 @@ public class ImsRcsManager { /** * Activity Action: Show the opt-in dialog for enabling or disabling RCS contact discovery - * using User Capability Exchange (UCE). + * using User Capability Exchange (UCE), which enables a service that periodically shares the + * phone numbers of all of the contacts in the user's address book with the carrier to refresh + * the RCS capabilities associated with those contacts as the local cache becomes stale. * <p> * An application that depends on RCS contact discovery being enabled must send this intent * using {@link Context#startActivity(Intent)} to ask the user to opt-in for contacts upload for diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java index dd9102699529..7a1c09275a6d 100644 --- a/telephony/java/android/telephony/ims/RcsUceAdapter.java +++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java @@ -28,10 +28,13 @@ import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceSpecificException; +import android.telephony.CarrierConfigManager; +import android.telephony.SubscriptionManager; import android.telephony.TelephonyFrameworkInitializer; import android.telephony.ims.aidl.IImsRcsController; import android.telephony.ims.aidl.IRcsUceControllerCallback; import android.telephony.ims.aidl.IRcsUcePublishStateCallback; +import android.telephony.ims.feature.RcsFeature; import android.util.Log; import java.lang.annotation.Retention; @@ -417,7 +420,7 @@ public class RcsUceAdapter { * <p> * After {@link CapabilitiesCallback#onComplete} or {@link CapabilitiesCallback#onError} has * been called, the reference to this callback will be discarded on the service side. - * @see #requestCapabilities(Executor, List, CapabilitiesCallback) + * @see #requestCapabilities(Collection, Executor, CapabilitiesCallback) * @hide */ @SystemApi @@ -464,10 +467,16 @@ public class RcsUceAdapter { } /** - * Request the User Capability Exchange capabilities for one or more contacts. + * Request the RCS capabilities for one or more contacts using RCS User Capability Exchange. * <p> - * This will return the cached capabilities of the contact and will not perform a capability - * poll on the network unless there are contacts being queried with stale information. + * This API will first check a local cache for the requested numbers and return the cached + * RCS capabilities of each number if the cache exists and is not stale. If the cache for a + * number is stale or there is no cached information about the requested number, the device will + * then perform a query to the carrier's network to request the RCS capabilities of the + * requested numbers. + * <p> + * Depending on the number of requests being sent, this API may throttled internally as the + * operations are queued to be executed by the carrier's network. * <p> * Be sure to check the availability of this feature using * {@link ImsRcsManager#isAvailable(int, int)} and ensuring @@ -552,13 +561,15 @@ public class RcsUceAdapter { } /** - * Ignore the device cache and perform a capability discovery for one contact, also called - * "availability fetch." + * Request the RCS capabilities for a phone number using User Capability Exchange. * <p> - * This will always perform a query to the network as long as requests are over the carrier - * availability fetch throttling threshold. If too many network requests are sent too quickly, - * #ERROR_TOO_MANY_REQUESTS will be returned. - * + * Unlike {@link #requestCapabilities(Collection, Executor, CapabilitiesCallback)}, which caches + * the result received from the network for a certain amount of time and uses that cached result + * for subsequent requests for RCS capabilities of the same phone number, this API will always + * request the RCS capabilities of a contact from the carrier's network. + * <p> + * Depending on the number of requests, this API may throttled internally as the operations are + * queued to be executed by the carrier's network. * <p> * Be sure to check the availability of this feature using * {@link ImsRcsManager#isAvailable(int, int)} and ensuring @@ -680,7 +691,8 @@ public class RcsUceAdapter { * state updates for the subscription specified in {@link ImsManager@getRcsManager(subid)}. * <p> * Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to subscription - * changed events and call {@link #unregisterPublishStateCallback} to clean up. + * changed events and call + * {@link #removeOnPublishStateChangedListener(OnPublishStateChangedListener)} to clean up. * <p> * The registered {@link OnPublishStateChangedListener} will also receive a callback when it is * registered with the current publish state. @@ -770,13 +782,23 @@ public class RcsUceAdapter { } /** - * The user’s setting for whether or not User Capability Exchange (UCE) is enabled for the - * associated subscription. + * The setting for whether or not the user has opted in to the automatic refresh of the RCS + * capabilities associated with the contacts in the user's contact address book. By default, + * this setting is disabled and must be enabled after the user has seen the opt-in dialog shown + * by {@link ImsRcsManager#ACTION_SHOW_CAPABILITY_DISCOVERY_OPT_IN}. + * <p> + * If this feature is enabled, the device will periodically share the phone numbers of all of + * the contacts in the user's address book with the carrier to refresh the RCS capabilities + * cache associated with those contacts as the local cache becomes stale. + * <p> + * This setting will only enable this feature if + * {@link CarrierConfigManager.Ims#KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL} is also enabled. * <p> * Note: This setting does not affect whether or not the device publishes its service * capabilities if the subscription supports presence publication. * - * @return true if the user’s setting for UCE is enabled, false otherwise. + * @return true if the user has opted in for automatic refresh of the RCS capabilities of their + * contacts, false otherwise. * @throws ImsException if the subscription associated with this instance of * {@link RcsUceAdapter} is valid, but the ImsService associated with the subscription is not * available. This can happen if the ImsService has crashed, for example, or if the subscription @@ -802,18 +824,33 @@ public class RcsUceAdapter { } /** - * Change the user’s setting for whether or not UCE is enabled for the associated subscription. + * Change the user’s setting for whether or not the user has opted in to the automatic + * refresh of the RCS capabilities associated with the contacts in the user's contact address + * book. By default, this setting is disabled and must be enabled using this method after the + * user has seen the opt-in dialog shown by + * {@link ImsRcsManager#ACTION_SHOW_CAPABILITY_DISCOVERY_OPT_IN}. + * <p> + * If an application wishes to request that the user enable this feature, they must launch an + * Activity using the Intent {@link ImsRcsManager#ACTION_SHOW_CAPABILITY_DISCOVERY_OPT_IN}, + * which will ask the user if they wish to enable this feature. This setting must only be + * enabled after the user has opted-in to this feature. + * <p> + * This must not affect the + * {@link #requestCapabilities(Collection, Executor, CapabilitiesCallback)} or + * {@link #requestAvailability(Uri, Executor, CapabilitiesCallback)} API, + * as those APIs are still required for per-contact RCS capability queries of phone numbers + * required for operations such as placing a Video Telephony call or starting an RCS chat + * session. * <p> - * If an application Requires UCE, they will launch an Activity using the Intent - * {@link ImsRcsManager#ACTION_SHOW_CAPABILITY_DISCOVERY_OPT_IN}, which will ask the user if - * they wish to enable this feature. This setting should only be enabled after the user has - * opted-in to capability exchange. + * This setting will only enable this feature if + * {@link CarrierConfigManager.Ims#KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL} is also enabled. * <p> * Note: This setting does not affect whether or not the device publishes its service * capabilities if the subscription supports presence publication. * - * @param isEnabled the user's setting for whether or not they wish for User - * Capability Exchange to be enabled. + * @param isEnabled true if the user has opted in for automatic refresh of the RCS capabilities + * of their contacts, or false if they have chosen to opt-out. By default this + * setting is disabled. * @throws ImsException if the subscription associated with this instance of * {@link RcsUceAdapter} is valid, but the ImsService associated with the subscription is not * available. This can happen if the ImsService has crashed, for example, or if the subscription diff --git a/tests/BackgroundDexOptServiceIntegrationTests/OWNERS b/tests/BackgroundDexOptServiceIntegrationTests/OWNERS new file mode 100644 index 000000000000..3414a7469ac2 --- /dev/null +++ b/tests/BackgroundDexOptServiceIntegrationTests/OWNERS @@ -0,0 +1 @@ +include platform/art:/OWNERS diff --git a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java index e05816eb391f..90ddb6ffb34a 100644 --- a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java +++ b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java @@ -20,6 +20,7 @@ import android.app.AlarmManager; import android.content.Context; import android.os.Environment; import android.os.ParcelFileDescriptor; +import android.os.PowerManager; import android.os.SystemProperties; import android.os.storage.StorageManager; import android.util.Log; @@ -201,11 +202,16 @@ public final class BackgroundDexOptServiceIntegrationTests { fillUpStorage((long) (getStorageLowBytes() * LOW_STORAGE_MULTIPLIER)); } - // TODO(aeubanks): figure out how to get scheduled bg-dexopt to run private static void runBackgroundDexOpt() throws IOException { + runBackgroundDexOpt("Success"); + } + + // TODO(aeubanks): figure out how to get scheduled bg-dexopt to run + private static void runBackgroundDexOpt(String expectedStatus) throws IOException { String result = runShellCommand("cmd package bg-dexopt-job " + PACKAGE_NAME); - if (!result.trim().equals("Success")) { - throw new IllegalStateException("Expected command success, received >" + result + "<"); + if (!result.trim().equals(expectedStatus)) { + throw new IllegalStateException("Expected status: " + expectedStatus + + "; Received: " + result.trim()); } } @@ -242,6 +248,16 @@ public final class BackgroundDexOptServiceIntegrationTests { runShellCommand(String.format("cmd package compile -f -m %s %s", filter, pkg)); } + // Override the thermal status of the device + public static void overrideThermalStatus(int status) throws IOException { + runShellCommand("cmd thermalservice override-status " + status); + } + + // Reset the thermal status of the device + public static void resetThermalStatus() throws IOException { + runShellCommand("cmd thermalservice reset"); + } + // Test that background dexopt under normal conditions succeeds. @Test public void testBackgroundDexOpt() throws IOException { @@ -307,4 +323,17 @@ public final class BackgroundDexOptServiceIntegrationTests { } } + // Test that background dexopt job doesn't trigger if the device is under thermal throttling. + @Test + public void testBackgroundDexOptThermalThrottling() throws IOException { + try { + compilePackageWithFilter(PACKAGE_NAME, "verify"); + overrideThermalStatus(PowerManager.THERMAL_STATUS_MODERATE); + // The bgdexopt task should fail when onStartJob is run + runBackgroundDexOpt("Failure"); + Assert.assertEquals("verify", getCompilerFilter(PACKAGE_NAME)); + } finally { + resetThermalStatus(); + } + } } diff --git a/tests/utils/testutils/java/com/android/internal/util/test/FsUtil.java b/tests/utils/testutils/java/com/android/internal/util/test/FsUtil.java new file mode 100644 index 000000000000..e65661298b7c --- /dev/null +++ b/tests/utils/testutils/java/com/android/internal/util/test/FsUtil.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.util.test; + +import java.io.File; + +public class FsUtil { + + /** + * Deletes all files under a given directory. Deliberately ignores errors, on the assumption + * that test cleanup is only supposed to be best-effort. + * + * @param dir directory to clear its contents + */ + public static void deleteContents(File dir) { + File[] files = dir.listFiles(); + if (files != null) { + for (File file : files) { + if (file.isDirectory()) { + deleteContents(file); + } + file.delete(); + } + } + } +} diff --git a/tests/vcn/OWNERS b/tests/vcn/OWNERS index 33b9f0f75f81..2441e772468c 100644 --- a/tests/vcn/OWNERS +++ b/tests/vcn/OWNERS @@ -3,5 +3,5 @@ set noparent benedictwong@google.com ckesting@google.com evitayan@google.com +junyin@google.com nharold@google.com -jchalard@google.com
\ No newline at end of file diff --git a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java index c59dcf879b1c..4ce78aa4d8c1 100644 --- a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java +++ b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java @@ -92,10 +92,6 @@ public class VcnGatewayConnectionConfigTest { builder.addExposedCapability(caps); } - for (int caps : UNDERLYING_CAPS) { - builder.addRequiredUnderlyingCapability(caps); - } - return builder.build(); } @@ -141,9 +137,7 @@ public class VcnGatewayConnectionConfigTest { @Test public void testBuilderRequiresNonEmptyExposedCaps() { try { - newBuilder() - .addRequiredUnderlyingCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - .build(); + newBuilder().build(); fail("Expected exception due to invalid exposed capabilities"); } catch (IllegalArgumentException e) { @@ -187,10 +181,6 @@ public class VcnGatewayConnectionConfigTest { Arrays.sort(exposedCaps); assertArrayEquals(EXPOSED_CAPS, exposedCaps); - int[] underlyingCaps = config.getRequiredUnderlyingCapabilities(); - Arrays.sort(underlyingCaps); - assertArrayEquals(UNDERLYING_CAPS, underlyingCaps); - assertEquals(TUNNEL_CONNECTION_PARAMS, config.getTunnelConnectionParams()); assertArrayEquals(RETRY_INTERVALS_MS, config.getRetryIntervalsMillis()); diff --git a/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java b/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java index 582275d0547d..abae81cf1742 100644 --- a/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java +++ b/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java @@ -16,15 +16,17 @@ package android.net.vcn; -import static android.net.NetworkCapabilities.REDACT_ALL; -import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS; +import static android.net.NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION; +import static android.net.NetworkCapabilities.REDACT_NONE; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNull; +import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; +import android.os.Build; import android.os.Parcel; import org.junit.Test; @@ -39,12 +41,6 @@ public class VcnTransportInfoTest { private static final VcnTransportInfo WIFI_UNDERLYING_INFO = new VcnTransportInfo(WIFI_INFO); @Test - public void testRedactionDefaults() { - assertEquals(REDACT_ALL, CELL_UNDERLYING_INFO.getRedaction()); - assertEquals(REDACT_ALL, WIFI_UNDERLYING_INFO.getRedaction()); - } - - @Test public void testGetWifiInfo() { assertEquals(WIFI_INFO, WIFI_UNDERLYING_INFO.getWifiInfo()); @@ -59,15 +55,19 @@ public class VcnTransportInfoTest { } @Test - public void testMakeCopySetsRedactions() { - assertEquals( - REDACT_FOR_NETWORK_SETTINGS, - ((VcnTransportInfo) CELL_UNDERLYING_INFO.makeCopy(REDACT_FOR_NETWORK_SETTINGS)) - .getRedaction()); + public void testMakeCopyRedactForAccessFineLocation() { assertEquals( - REDACT_FOR_NETWORK_SETTINGS, - ((VcnTransportInfo) WIFI_UNDERLYING_INFO.makeCopy(REDACT_FOR_NETWORK_SETTINGS)) - .getRedaction()); + SUB_ID, + ((VcnTransportInfo) CELL_UNDERLYING_INFO.makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION)) + .getSubId()); + + // TODO: remove the if statement when S pushes to AOSP. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + assertEquals( + WifiConfiguration.INVALID_NETWORK_ID, + ((VcnTransportInfo) WIFI_UNDERLYING_INFO.makeCopy( + REDACT_FOR_ACCESS_FINE_LOCATION)).getWifiInfo().getNetworkId()); + } } @Test @@ -78,35 +78,31 @@ public class VcnTransportInfoTest { } @Test - public void testParcelUnparcel() { - verifyParcelingIsNull(CELL_UNDERLYING_INFO); - verifyParcelingIsNull(WIFI_UNDERLYING_INFO); - } - - private void verifyParcelingIsNull(VcnTransportInfo vcnTransportInfo) { - // Verify redacted by default - Parcel parcel = Parcel.obtain(); - vcnTransportInfo.writeToParcel(parcel, 0 /* flags */); - parcel.setDataPosition(0); + public void testApplicableRedactions() { + assertEquals(REDACT_NONE, CELL_UNDERLYING_INFO.getApplicableRedactions()); - assertNull(VcnTransportInfo.CREATOR.createFromParcel(parcel)); + final long wifiRedactions = WIFI_INFO.getApplicableRedactions(); + assertEquals(wifiRedactions, WIFI_UNDERLYING_INFO.getApplicableRedactions()); } @Test - public void testParcelUnparcelNotRedactedForSysUi() { - verifyParcelingForSysUi(CELL_UNDERLYING_INFO); - verifyParcelingForSysUi(WIFI_UNDERLYING_INFO); + public void testParcelNotRedactedForSysUi() { + VcnTransportInfo cellRedacted = parcelForSysUi(CELL_UNDERLYING_INFO); + assertEquals(SUB_ID, cellRedacted.getSubId()); + VcnTransportInfo wifiRedacted = parcelForSysUi(WIFI_UNDERLYING_INFO); + assertEquals(NETWORK_ID, wifiRedacted.getWifiInfo().getNetworkId()); } - private void verifyParcelingForSysUi(VcnTransportInfo vcnTransportInfo) { + private VcnTransportInfo parcelForSysUi(VcnTransportInfo vcnTransportInfo) { // Allow fully unredacted; SysUI will have all the relevant permissions. - final VcnTransportInfo unRedacted = (VcnTransportInfo) vcnTransportInfo.makeCopy(0); + final VcnTransportInfo unRedacted = (VcnTransportInfo) vcnTransportInfo.makeCopy( + REDACT_NONE); final Parcel parcel = Parcel.obtain(); unRedacted.writeToParcel(parcel, 0 /* flags */); parcel.setDataPosition(0); final VcnTransportInfo unparceled = VcnTransportInfo.CREATOR.createFromParcel(parcel); assertEquals(vcnTransportInfo, unparceled); - assertEquals(REDACT_ALL, unparceled.getRedaction()); + return unparceled; } } diff --git a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java index 528f240b9912..ca7463884d3a 100644 --- a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java +++ b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java @@ -88,13 +88,13 @@ public class TelephonySubscriptionTrackerTest { private static final SubscriptionInfo TEST_SUBINFO_2 = mock(SubscriptionInfo.class); private static final Map<ParcelUuid, Set<String>> TEST_PRIVILEGED_PACKAGES = Collections.singletonMap(TEST_PARCEL_UUID, Collections.singleton(PACKAGE_NAME)); - private static final Map<Integer, ParcelUuid> TEST_SUBID_TO_GROUP_MAP; + private static final Map<Integer, SubscriptionInfo> TEST_SUBID_TO_INFO_MAP; static { - final Map<Integer, ParcelUuid> subIdToGroupMap = new HashMap<>(); - subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_1, TEST_PARCEL_UUID); - subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_2, TEST_PARCEL_UUID); - TEST_SUBID_TO_GROUP_MAP = Collections.unmodifiableMap(subIdToGroupMap); + final Map<Integer, SubscriptionInfo> subIdToGroupMap = new HashMap<>(); + subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_1, TEST_SUBINFO_1); + subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_2, TEST_SUBINFO_2); + TEST_SUBID_TO_INFO_MAP = Collections.unmodifiableMap(subIdToGroupMap); } @NonNull private final Context mContext; @@ -190,13 +190,13 @@ public class TelephonySubscriptionTrackerTest { private TelephonySubscriptionSnapshot buildExpectedSnapshot( Map<ParcelUuid, Set<String>> privilegedPackages) { - return buildExpectedSnapshot(TEST_SUBID_TO_GROUP_MAP, privilegedPackages); + return buildExpectedSnapshot(TEST_SUBID_TO_INFO_MAP, privilegedPackages); } private TelephonySubscriptionSnapshot buildExpectedSnapshot( - Map<Integer, ParcelUuid> subIdToGroupMap, + Map<Integer, SubscriptionInfo> subIdToInfoMap, Map<ParcelUuid, Set<String>> privilegedPackages) { - return new TelephonySubscriptionSnapshot(subIdToGroupMap, privilegedPackages); + return new TelephonySubscriptionSnapshot(subIdToInfoMap, privilegedPackages); } private void verifyNoActiveSubscriptions() { @@ -371,7 +371,7 @@ public class TelephonySubscriptionTrackerTest { @Test public void testTelephonySubscriptionSnapshotGetGroupForSubId() throws Exception { final TelephonySubscriptionSnapshot snapshot = - new TelephonySubscriptionSnapshot(TEST_SUBID_TO_GROUP_MAP, emptyMap()); + new TelephonySubscriptionSnapshot(TEST_SUBID_TO_INFO_MAP, emptyMap()); assertEquals(TEST_PARCEL_UUID, snapshot.getGroupForSubId(TEST_SUBSCRIPTION_ID_1)); assertEquals(TEST_PARCEL_UUID, snapshot.getGroupForSubId(TEST_SUBSCRIPTION_ID_2)); @@ -380,7 +380,7 @@ public class TelephonySubscriptionTrackerTest { @Test public void testTelephonySubscriptionSnapshotGetAllSubIdsInGroup() throws Exception { final TelephonySubscriptionSnapshot snapshot = - new TelephonySubscriptionSnapshot(TEST_SUBID_TO_GROUP_MAP, emptyMap()); + new TelephonySubscriptionSnapshot(TEST_SUBID_TO_INFO_MAP, emptyMap()); assertEquals( new ArraySet<>(Arrays.asList(TEST_SUBSCRIPTION_ID_1, TEST_SUBSCRIPTION_ID_2)), diff --git a/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java b/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java index 0b72cd93e8b0..f91575b670d3 100644 --- a/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java +++ b/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java @@ -42,12 +42,14 @@ import android.net.NetworkRequest; import android.net.TelephonyNetworkSpecifier; import android.os.ParcelUuid; import android.os.test.TestLooper; +import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionInfo; +import android.telephony.TelephonyManager; import android.util.ArraySet; import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; import com.android.server.vcn.UnderlyingNetworkTracker.NetworkBringupCallback; -import com.android.server.vcn.UnderlyingNetworkTracker.RouteSelectionCallback; +import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkListener; import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkRecord; import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkTrackerCallback; @@ -59,7 +61,6 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.Arrays; -import java.util.Collections; import java.util.Set; import java.util.UUID; @@ -98,11 +99,13 @@ public class UnderlyingNetworkTrackerTest { @Mock private Context mContext; @Mock private VcnNetworkProvider mVcnNetworkProvider; @Mock private ConnectivityManager mConnectivityManager; + @Mock private TelephonyManager mTelephonyManager; + @Mock private CarrierConfigManager mCarrierConfigManager; @Mock private TelephonySubscriptionSnapshot mSubscriptionSnapshot; @Mock private UnderlyingNetworkTrackerCallback mNetworkTrackerCb; @Mock private Network mNetwork; - @Captor private ArgumentCaptor<RouteSelectionCallback> mRouteSelectionCallbackCaptor; + @Captor private ArgumentCaptor<UnderlyingNetworkListener> mUnderlyingNetworkListenerCaptor; private TestLooper mTestLooper; private VcnContext mVcnContext; @@ -127,6 +130,13 @@ public class UnderlyingNetworkTrackerTest { mConnectivityManager, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class); + setupSystemService( + mContext, mTelephonyManager, Context.TELEPHONY_SERVICE, TelephonyManager.class); + setupSystemService( + mContext, + mCarrierConfigManager, + Context.CARRIER_CONFIG_SERVICE, + CarrierConfigManager.class); when(mSubscriptionSnapshot.getAllSubIdsInGroup(eq(SUB_GROUP))).thenReturn(INITIAL_SUB_IDS); @@ -135,7 +145,6 @@ public class UnderlyingNetworkTrackerTest { mVcnContext, SUB_GROUP, mSubscriptionSnapshot, - Collections.singleton(NetworkCapabilities.NET_CAPABILITY_INTERNET), mNetworkTrackerCb); } @@ -163,26 +172,25 @@ public class UnderlyingNetworkTrackerTest { @Test public void testNetworkCallbacksRegisteredOnStartupForTestMode() { + final ConnectivityManager cm = mock(ConnectivityManager.class); + setupSystemService(mContext, cm, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class); final VcnContext vcnContext = - spy( - new VcnContext( - mContext, - mTestLooper.getLooper(), - mVcnNetworkProvider, - true /* isInTestMode */)); - - mUnderlyingNetworkTracker = - new UnderlyingNetworkTracker( - vcnContext, - SUB_GROUP, - mSubscriptionSnapshot, - Collections.singleton(NetworkCapabilities.NET_CAPABILITY_INTERNET), - mNetworkTrackerCb); - - verify(mConnectivityManager) - .requestBackgroundNetwork( + new VcnContext( + mContext, + mTestLooper.getLooper(), + mVcnNetworkProvider, + true /* isInTestMode */); + + new UnderlyingNetworkTracker( + vcnContext, + SUB_GROUP, + mSubscriptionSnapshot, + mNetworkTrackerCb); + + verify(cm) + .registerNetworkCallback( eq(getTestNetworkRequest(INITIAL_SUB_IDS)), - any(RouteSelectionCallback.class), + any(UnderlyingNetworkListener.class), any()); } @@ -200,9 +208,19 @@ public class UnderlyingNetworkTrackerTest { } verify(mConnectivityManager) - .requestBackgroundNetwork( + .registerNetworkCallback( eq(getRouteSelectionRequest(expectedSubIds)), - any(RouteSelectionCallback.class), + any(UnderlyingNetworkListener.class), + any()); + verify(mConnectivityManager) + .registerNetworkCallback( + eq(getWifiEntryRssiThresholdRequest(expectedSubIds)), + any(NetworkBringupCallback.class), + any()); + verify(mConnectivityManager) + .registerNetworkCallback( + eq(getWifiExitRssiThresholdRequest(expectedSubIds)), + any(NetworkBringupCallback.class), any()); } @@ -218,9 +236,10 @@ public class UnderlyingNetworkTrackerTest { mUnderlyingNetworkTracker.updateSubscriptionSnapshot(subscriptionUpdate); // verify that initially-filed bringup requests are unregistered (cell + wifi) - verify(mConnectivityManager, times(INITIAL_SUB_IDS.size() + 1)) + verify(mConnectivityManager, times(INITIAL_SUB_IDS.size() + 3)) .unregisterNetworkCallback(any(NetworkBringupCallback.class)); - verify(mConnectivityManager).unregisterNetworkCallback(any(RouteSelectionCallback.class)); + verify(mConnectivityManager) + .unregisterNetworkCallback(any(UnderlyingNetworkListener.class)); verifyNetworkRequestsRegistered(UPDATED_SUB_IDS); } @@ -231,6 +250,24 @@ public class UnderlyingNetworkTrackerTest { .build(); } + private NetworkRequest getWifiEntryRssiThresholdRequest(Set<Integer> netCapsSubIds) { + // TODO (b/187991063): Add tests for carrier-config based thresholds + return getExpectedRequestBase() + .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) + .setSubscriptionIds(netCapsSubIds) + .setSignalStrength(UnderlyingNetworkTracker.WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT) + .build(); + } + + private NetworkRequest getWifiExitRssiThresholdRequest(Set<Integer> netCapsSubIds) { + // TODO (b/187991063): Add tests for carrier-config based thresholds + return getExpectedRequestBase() + .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) + .setSubscriptionIds(netCapsSubIds) + .setSignalStrength(UnderlyingNetworkTracker.WIFI_EXIT_RSSI_THRESHOLD_DEFAULT) + .build(); + } + private NetworkRequest getCellRequestForSubId(int subId) { return getExpectedRequestBase() .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) @@ -239,7 +276,11 @@ public class UnderlyingNetworkTrackerTest { } private NetworkRequest getRouteSelectionRequest(Set<Integer> netCapsSubIds) { - return getExpectedRequestBase().setSubscriptionIds(netCapsSubIds).build(); + return getExpectedRequestBase() + .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) + .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED) + .setSubscriptionIds(netCapsSubIds) + .build(); } private NetworkRequest getTestNetworkRequest(Set<Integer> netCapsSubIds) { @@ -265,11 +306,12 @@ public class UnderlyingNetworkTrackerTest { public void testTeardown() { mUnderlyingNetworkTracker.teardown(); - // Expect 3 NetworkBringupCallbacks to be unregistered: 1 for WiFi and 2 for Cellular (1x - // for each subId) - verify(mConnectivityManager, times(3)) + // Expect 5 NetworkBringupCallbacks to be unregistered: 1 for WiFi, 2 for Cellular (1x for + // each subId), and 1 for each of the Wifi signal strength thresholds + verify(mConnectivityManager, times(5)) .unregisterNetworkCallback(any(NetworkBringupCallback.class)); - verify(mConnectivityManager).unregisterNetworkCallback(any(RouteSelectionCallback.class)); + verify(mConnectivityManager) + .unregisterNetworkCallback(any(UnderlyingNetworkListener.class)); } @Test @@ -302,19 +344,19 @@ public class UnderlyingNetworkTrackerTest { verifyRegistrationOnAvailableAndGetCallback(); } - private RouteSelectionCallback verifyRegistrationOnAvailableAndGetCallback() { + private UnderlyingNetworkListener verifyRegistrationOnAvailableAndGetCallback() { return verifyRegistrationOnAvailableAndGetCallback(INITIAL_NETWORK_CAPABILITIES); } - private RouteSelectionCallback verifyRegistrationOnAvailableAndGetCallback( + private UnderlyingNetworkListener verifyRegistrationOnAvailableAndGetCallback( NetworkCapabilities networkCapabilities) { verify(mConnectivityManager) - .requestBackgroundNetwork( + .registerNetworkCallback( eq(getRouteSelectionRequest(INITIAL_SUB_IDS)), - mRouteSelectionCallbackCaptor.capture(), + mUnderlyingNetworkListenerCaptor.capture(), any()); - RouteSelectionCallback cb = mRouteSelectionCallbackCaptor.getValue(); + UnderlyingNetworkListener cb = mUnderlyingNetworkListenerCaptor.getValue(); cb.onAvailable(mNetwork); cb.onCapabilitiesChanged(mNetwork, networkCapabilities); cb.onLinkPropertiesChanged(mNetwork, INITIAL_LINK_PROPERTIES); @@ -332,7 +374,7 @@ public class UnderlyingNetworkTrackerTest { @Test public void testRecordTrackerCallbackNotifiedForNetworkCapabilitiesChange() { - RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback(); + UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback(); cb.onCapabilitiesChanged(mNetwork, UPDATED_NETWORK_CAPABILITIES); @@ -347,7 +389,7 @@ public class UnderlyingNetworkTrackerTest { @Test public void testRecordTrackerCallbackNotifiedForLinkPropertiesChange() { - RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback(); + UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback(); cb.onLinkPropertiesChanged(mNetwork, UPDATED_LINK_PROPERTIES); @@ -362,7 +404,7 @@ public class UnderlyingNetworkTrackerTest { @Test public void testRecordTrackerCallbackNotifiedForNetworkSuspended() { - RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback(); + UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback(); cb.onCapabilitiesChanged(mNetwork, SUSPENDED_NETWORK_CAPABILITIES); @@ -381,7 +423,7 @@ public class UnderlyingNetworkTrackerTest { @Test public void testRecordTrackerCallbackNotifiedForNetworkResumed() { - RouteSelectionCallback cb = + UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback(SUSPENDED_NETWORK_CAPABILITIES); cb.onCapabilitiesChanged(mNetwork, INITIAL_NETWORK_CAPABILITIES); @@ -401,7 +443,7 @@ public class UnderlyingNetworkTrackerTest { @Test public void testRecordTrackerCallbackNotifiedForBlocked() { - RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback(); + UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback(); cb.onBlockedStatusChanged(mNetwork, true /* isBlocked */); @@ -416,7 +458,7 @@ public class UnderlyingNetworkTrackerTest { @Test public void testRecordTrackerCallbackNotifiedForNetworkLoss() { - RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback(); + UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback(); cb.onLost(mNetwork); @@ -425,7 +467,7 @@ public class UnderlyingNetworkTrackerTest { @Test public void testRecordTrackerCallbackIgnoresDuplicateRecord() { - RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback(); + UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback(); cb.onCapabilitiesChanged(mNetwork, INITIAL_NETWORK_CAPABILITIES); @@ -433,4 +475,6 @@ public class UnderlyingNetworkTrackerTest { // UnderlyingNetworkRecord does not actually change verifyNoMoreInteractions(mNetworkTrackerCb); } + + // TODO (b/187991063): Add tests for network prioritization } diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java index 1ecb4c9ee298..860a919aa9b3 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java @@ -54,6 +54,7 @@ import android.net.vcn.VcnGatewayConnectionConfigTest; import android.os.ParcelUuid; import android.os.PowerManager; import android.os.test.TestLooper; +import android.telephony.SubscriptionInfo; import com.android.internal.util.State; import com.android.internal.util.WakeupMessage; @@ -73,6 +74,12 @@ import java.util.concurrent.TimeUnit; public class VcnGatewayConnectionTestBase { protected static final ParcelUuid TEST_SUB_GRP = new ParcelUuid(UUID.randomUUID()); + protected static final SubscriptionInfo TEST_SUB_INFO = mock(SubscriptionInfo.class); + + static { + doReturn(TEST_SUB_GRP).when(TEST_SUB_INFO).getGroupUuid(); + } + protected static final InetAddress TEST_DNS_ADDR = InetAddresses.parseNumericAddress("2001:DB8:0:1::"); protected static final InetAddress TEST_DNS_ADDR_2 = @@ -116,7 +123,7 @@ public class VcnGatewayConnectionTestBase { protected static final TelephonySubscriptionSnapshot TEST_SUBSCRIPTION_SNAPSHOT = new TelephonySubscriptionSnapshot( - Collections.singletonMap(TEST_SUB_ID, TEST_SUB_GRP), Collections.EMPTY_MAP); + Collections.singletonMap(TEST_SUB_ID, TEST_SUB_INFO), Collections.EMPTY_MAP); @NonNull protected final Context mContext; @NonNull protected final TestLooper mTestLooper; @@ -166,7 +173,7 @@ public class VcnGatewayConnectionTestBase { doReturn(mUnderlyingNetworkTracker) .when(mDeps) - .newUnderlyingNetworkTracker(any(), any(), any(), any(), any()); + .newUnderlyingNetworkTracker(any(), any(), any(), any()); doReturn(mWakeLock) .when(mDeps) .newWakeLock(eq(mContext), eq(PowerManager.PARTIAL_WAKE_LOCK), any()); diff --git a/tools/aapt/pseudolocalize.cpp b/tools/aapt/pseudolocalize.cpp index 5c47e0fa8a16..4e8dcb1bc6ee 100644 --- a/tools/aapt/pseudolocalize.cpp +++ b/tools/aapt/pseudolocalize.cpp @@ -194,7 +194,8 @@ static String16 pseudo_generate_expansion(const unsigned int length) { break; } } - result.remove(length + ext, 0); + // Just keep the first length + ext characters + result = String16(result, length + ext); } return result; } diff --git a/tools/aapt2/OWNERS b/tools/aapt2/OWNERS index f1903a5a54a7..69dfcc98340d 100644 --- a/tools/aapt2/OWNERS +++ b/tools/aapt2/OWNERS @@ -1,3 +1,4 @@ set noparent toddke@google.com -rtmitchell@google.com
\ No newline at end of file +rtmitchell@google.com +patb@google.com
\ No newline at end of file diff --git a/tools/aosp/aosp_sha.sh b/tools/aosp/aosp_sha.sh index f25fcdcb7479..514f17a042bc 100755 --- a/tools/aosp/aosp_sha.sh +++ b/tools/aosp/aosp_sha.sh @@ -5,7 +5,21 @@ if git branch -vv | grep -q -P "^\*[^\[]+\[aosp/"; then # Change appears to be in AOSP exit 0 else - # Change appears to be non-AOSP; search for files + # Change appears to be non-AOSP. + + # If this is a cherry-pick, then allow it. + cherrypick=0 + while read -r line ; do + if [[ $line =~ cherry\ picked\ from ]] ; then + (( cherrypick++ )) + fi + done < <(git show $1) + if (( cherrypick != 0 )); then + # This is a cherry-pick, so allow it. + exit 0 + fi + + # See if any files are affected. count=0 while read -r file ; do if (( count == 0 )); then diff --git a/tools/codegen/src/com/android/codegen/Utils.kt b/tools/codegen/src/com/android/codegen/Utils.kt index c19ae3b0b11f..a117aa09ab62 100644 --- a/tools/codegen/src/com/android/codegen/Utils.kt +++ b/tools/codegen/src/com/android/codegen/Utils.kt @@ -43,8 +43,8 @@ inline infix fun Int.times(action: () -> Unit) { * cccc dd */ fun Iterable<Pair<String, String>>.columnize(separator: String = " | "): String { - val col1w = map { (a, _) -> a.length }.max()!! - val col2w = map { (_, b) -> b.length }.max()!! + val col1w = map { (a, _) -> a.length }.maxOrNull()!! + val col2w = map { (_, b) -> b.length }.maxOrNull()!! return map { it.first.padEnd(col1w) + separator + it.second.padEnd(col2w) }.joinToString("\n") } |