Merge "Fix error formatting issues"
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
index 26010ef6..bdab7d0 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
@@ -545,7 +545,7 @@
out.attribute(null, "net-capabilities", Long.toString(
BitUtils.packBits(network.getCapabilities())));
out.attribute(null, "net-unwanted-capabilities", Long.toString(
- BitUtils.packBits(network.getUnwantedCapabilities())));
+ BitUtils.packBits(network.getForbiddenCapabilities())));
out.attribute(null, "net-transport-types", Long.toString(
BitUtils.packBits(network.getTransportTypes())));
@@ -968,22 +968,22 @@
String val;
final String netCapabilities = parser.getAttributeValue(null, "net-capabilities");
- final String netUnwantedCapabilities = parser.getAttributeValue(
+ final String netforbiddenCapabilities = parser.getAttributeValue(
null, "net-unwanted-capabilities");
final String netTransportTypes = parser.getAttributeValue(null, "net-transport-types");
if (netCapabilities != null && netTransportTypes != null) {
final NetworkRequest.Builder builder = new NetworkRequest.Builder()
.clearCapabilities();
- final long unwantedCapabilities = netUnwantedCapabilities != null
- ? Long.parseLong(netUnwantedCapabilities)
- : BitUtils.packBits(builder.build().getUnwantedCapabilities());
+ final long forbiddenCapabilities = netforbiddenCapabilities != null
+ ? Long.parseLong(netforbiddenCapabilities)
+ : BitUtils.packBits(builder.build().getForbiddenCapabilities());
// We're okay throwing NFE here; caught by caller
for (int capability : BitUtils.unpackBits(Long.parseLong(netCapabilities))) {
builder.addCapability(capability);
}
- for (int unwantedCapability : BitUtils.unpackBits(
- Long.parseLong(netUnwantedCapabilities))) {
- builder.addUnwantedCapability(unwantedCapability);
+ for (int forbiddenCapability : BitUtils.unpackBits(
+ Long.parseLong(netforbiddenCapabilities))) {
+ builder.addForbiddenCapability(forbiddenCapability);
}
for (int transport : BitUtils.unpackBits(Long.parseLong(netTransportTypes))) {
builder.addTransportType(transport);
diff --git a/apex/media/Android.bp b/apex/media/Android.bp
index 308741a..a75f1ae 100644
--- a/apex/media/Android.bp
+++ b/apex/media/Android.bp
@@ -24,3 +24,10 @@
// 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 2df31ec..5b2d97f 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -24,12 +24,17 @@
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 @@
],
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 @@
],
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 @@
],
out: ["removed.txt"],
tools: ["metalava"],
- cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)",
+ cmd: metalava_cmd + "$(in) --api $(out)",
dists: [
{
targets: ["droidcore"],
@@ -157,7 +162,7 @@
],
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 +188,7 @@
],
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) " +
@@ -207,7 +212,7 @@
],
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"],
@@ -239,7 +244,7 @@
],
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 +269,7 @@
],
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
@@ -291,7 +296,7 @@
],
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 +336,7 @@
],
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 +359,7 @@
],
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/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 848f480..5d23eb2 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -89,9 +89,9 @@
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/test-current.txt b/core/api/test-current.txt
index 81b9428..3b759a2 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -537,6 +537,10 @@
field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.ProviderInfoList> CREATOR;
}
+ public final class SharedLibraryInfo implements android.os.Parcelable {
+ method @NonNull public java.util.List<java.lang.String> getAllCodePaths();
+ }
+
public final class ShortcutInfo implements android.os.Parcelable {
method public boolean isVisibleToPublisher();
}
diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java
index 3c20dca..a74c663 100644
--- a/core/java/android/bluetooth/le/ScanFilter.java
+++ b/core/java/android/bluetooth/le/ScanFilter.java
@@ -587,6 +587,10 @@
* @throws IllegalArgumentException If the {@code deviceAddress} is invalid.
*/
public Builder setDeviceAddress(String deviceAddress) {
+ if (deviceAddress == null) {
+ mDeviceAddress = deviceAddress;
+ return this;
+ }
return setDeviceAddress(deviceAddress, BluetoothDevice.ADDRESS_TYPE_PUBLIC);
}
diff --git a/core/java/android/content/pm/SharedLibraryInfo.java b/core/java/android/content/pm/SharedLibraryInfo.java
index da2a3d8..933a0c9 100644
--- a/core/java/android/content/pm/SharedLibraryInfo.java
+++ b/core/java/android/content/pm/SharedLibraryInfo.java
@@ -20,6 +20,7 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -29,6 +30,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
/**
* This class provides information for a shared library. There are
@@ -177,7 +179,8 @@
*
* @hide
*/
- public List<String> getAllCodePaths() {
+ @TestApi
+ public @NonNull List<String> getAllCodePaths() {
if (getPath() != null) {
// Builtin library.
ArrayList<String> list = new ArrayList<>();
@@ -185,7 +188,7 @@
return list;
} else {
// Static or dynamic library.
- return mCodePaths;
+ return Objects.requireNonNull(mCodePaths);
}
}
diff --git a/core/java/android/hardware/hdmi/OWNERS b/core/java/android/hardware/hdmi/OWNERS
index 16c15e3..60d43fd 100644
--- a/core/java/android/hardware/hdmi/OWNERS
+++ b/core/java/android/hardware/hdmi/OWNERS
@@ -4,3 +4,4 @@
marvinramin@google.com
nchalko@google.com
+lcnathalie@google.com
diff --git a/core/java/android/net/UnderlyingNetworkInfo.java b/core/java/android/net/UnderlyingNetworkInfo.java
index 459fdac..33f9375 100644
--- a/core/java/android/net/UnderlyingNetworkInfo.java
+++ b/core/java/android/net/UnderlyingNetworkInfo.java
@@ -71,13 +71,13 @@
/** 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 @@
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/VcnConfig.java b/core/java/android/net/vcn/VcnConfig.java
index d41c0b4..caab152 100644
--- a/core/java/android/net/vcn/VcnConfig.java
+++ b/core/java/android/net/vcn/VcnConfig.java
@@ -52,12 +52,17 @@
private static final String GATEWAY_CONNECTION_CONFIGS_KEY = "mGatewayConnectionConfigs";
@NonNull private final Set<VcnGatewayConnectionConfig> mGatewayConnectionConfigs;
+ private static final String IS_TEST_MODE_PROFILE_KEY = "mIsTestModeProfile";
+ private final boolean mIsTestModeProfile;
+
private VcnConfig(
@NonNull String packageName,
- @NonNull Set<VcnGatewayConnectionConfig> gatewayConnectionConfigs) {
+ @NonNull Set<VcnGatewayConnectionConfig> gatewayConnectionConfigs,
+ boolean isTestModeProfile) {
mPackageName = packageName;
mGatewayConnectionConfigs =
Collections.unmodifiableSet(new ArraySet<>(gatewayConnectionConfigs));
+ mIsTestModeProfile = isTestModeProfile;
validate();
}
@@ -77,6 +82,7 @@
new ArraySet<>(
PersistableBundleUtils.toList(
gatewayConnectionConfigsBundle, VcnGatewayConnectionConfig::new));
+ mIsTestModeProfile = in.getBoolean(IS_TEST_MODE_PROFILE_KEY);
validate();
}
@@ -104,6 +110,15 @@
}
/**
+ * Returns whether or not this VcnConfig is restricted to test networks.
+ *
+ * @hide
+ */
+ public boolean isTestModeProfile() {
+ return mIsTestModeProfile;
+ }
+
+ /**
* Serializes this object to a PersistableBundle.
*
* @hide
@@ -119,13 +134,14 @@
new ArrayList<>(mGatewayConnectionConfigs),
VcnGatewayConnectionConfig::toPersistableBundle);
result.putPersistableBundle(GATEWAY_CONNECTION_CONFIGS_KEY, gatewayConnectionConfigsBundle);
+ result.putBoolean(IS_TEST_MODE_PROFILE_KEY, mIsTestModeProfile);
return result;
}
@Override
public int hashCode() {
- return Objects.hash(mPackageName, mGatewayConnectionConfigs);
+ return Objects.hash(mPackageName, mGatewayConnectionConfigs, mIsTestModeProfile);
}
@Override
@@ -136,7 +152,8 @@
final VcnConfig rhs = (VcnConfig) other;
return mPackageName.equals(rhs.mPackageName)
- && mGatewayConnectionConfigs.equals(rhs.mGatewayConnectionConfigs);
+ && mGatewayConnectionConfigs.equals(rhs.mGatewayConnectionConfigs)
+ && mIsTestModeProfile == rhs.mIsTestModeProfile;
}
// Parcelable methods
@@ -172,6 +189,8 @@
@NonNull
private final Set<VcnGatewayConnectionConfig> mGatewayConnectionConfigs = new ArraySet<>();
+ private boolean mIsTestModeProfile = false;
+
public Builder(@NonNull Context context) {
Objects.requireNonNull(context, "context was null");
@@ -207,13 +226,29 @@
}
/**
+ * Restricts this VcnConfig to matching with test networks (only).
+ *
+ * <p>This method is for testing only, and must not be used by apps. Calling {@link
+ * VcnManager#setVcnConfig(ParcelUuid, VcnConfig)} with a VcnConfig where test-network usage
+ * is enabled will require the MANAGE_TEST_NETWORKS permission.
+ *
+ * @return this {@link Builder} instance, for chaining
+ * @hide
+ */
+ @NonNull
+ public Builder setIsTestModeProfile() {
+ mIsTestModeProfile = true;
+ return this;
+ }
+
+ /**
* Builds and validates the VcnConfig.
*
* @return an immutable VcnConfig instance
*/
@NonNull
public VcnConfig build() {
- return new VcnConfig(mPackageName, mGatewayConnectionConfigs);
+ return new VcnConfig(mPackageName, mGatewayConnectionConfigs, mIsTestModeProfile);
}
}
}
diff --git a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
index be308d01..2df3e6c7 100644
--- a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
+++ b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
@@ -15,6 +15,8 @@
*/
package android.net.vcn;
+import static android.net.ipsec.ike.IkeSessionParams.IKE_OPTION_MOBIKE;
+
import static com.android.internal.annotations.VisibleForTesting.Visibility;
import android.annotation.IntDef;
@@ -433,6 +435,8 @@
* distinguish between VcnGatewayConnectionConfigs configured on a single {@link
* VcnConfig}. This will be used as the identifier in VcnStatusCallback invocations.
* @param tunnelConnectionParams the IKE tunnel connection configuration
+ * @throws IllegalArgumentException if the provided IkeTunnelConnectionParams is not
+ * configured to support MOBIKE
* @see IkeTunnelConnectionParams
* @see VcnManager.VcnStatusCallback#onGatewayConnectionError
*/
@@ -441,6 +445,10 @@
@NonNull IkeTunnelConnectionParams tunnelConnectionParams) {
Objects.requireNonNull(gatewayConnectionName, "gatewayConnectionName was null");
Objects.requireNonNull(tunnelConnectionParams, "tunnelConnectionParams was null");
+ if (!tunnelConnectionParams.getIkeSessionParams().hasIkeOption(IKE_OPTION_MOBIKE)) {
+ throw new IllegalArgumentException(
+ "MOBIKE must be configured for the provided IkeSessionParams");
+ }
mGatewayConnectionName = gatewayConnectionName;
mTunnelConnectionParams = tunnelConnectionParams;
diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java
index 9d1c1ff..390c3b9 100644
--- a/core/java/android/net/vcn/VcnManager.java
+++ b/core/java/android/net/vcn/VcnManager.java
@@ -74,6 +74,36 @@
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 0e9ccf1..1f18184 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 @@
@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 @@
* 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 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 @@
@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 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 d966595..cd02d29 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -63,3 +63,6 @@
# 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/com/android/internal/os/BinderLatencyBuckets.java b/core/java/com/android/internal/os/BinderLatencyBuckets.java
new file mode 100644
index 0000000..bdee4ca
--- /dev/null
+++ b/core/java/com/android/internal/os/BinderLatencyBuckets.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.Collections;
+
+/**
+ * Generates the bucket thresholds (with a custom logarithmic scale) for a histogram to store
+ * latency samples in.
+ */
+public class BinderLatencyBuckets {
+ private static final String TAG = "BinderLatencyBuckets";
+ private ArrayList<Integer> mBuckets;
+
+ /**
+ * @param bucketCount the number of buckets the histogram should have
+ * @param firstBucketSize the size of the first bucket (used to avoid excessive small buckets)
+ * @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);
+
+ // 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.
+ for (int i = 1; i < bucketCount - 1; i++) {
+ // Increase the target bucket limit value by the scale factor.
+ double nextTarget = lastTarget * scaleFactor;
+
+ if (nextTarget > Integer.MAX_VALUE || lastValue == 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");
+ return;
+ }
+
+ if ((int) nextTarget > lastValue) {
+ // Convert the target bucket limit value to an integer.
+ mBuckets.add((int) nextTarget);
+ lastValue = (int) nextTarget;
+ } else {
+ // Avoid creating redundant buckets, so bucket size should be 1 at a minimum.
+ mBuckets.add(lastValue + 1);
+ lastValue = lastValue + 1;
+ }
+ lastTarget = nextTarget;
+ }
+ }
+
+ /** 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();
+ }
+
+ // Binary search returns the element index if it is contained in the list - in this case the
+ // correct bucket is the index after as we use [minValue, maxValue) for bucket boundaries.
+ // 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);
+ return searchResult < 0 ? -(1 + searchResult) : searchResult + 1;
+ }
+
+ @VisibleForTesting
+ public ArrayList<Integer> getBuckets() {
+ return mBuckets;
+ }
+}
diff --git a/core/java/com/android/internal/os/BinderLatencyObserver.java b/core/java/com/android/internal/os/BinderLatencyObserver.java
index 92b4952..59cc66d 100644
--- a/core/java/com/android/internal/os/BinderLatencyObserver.java
+++ b/core/java/com/android/internal/os/BinderLatencyObserver.java
@@ -26,7 +26,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BinderInternal.CallSession;
-import java.util.ArrayList;
import java.util.Random;
/** Collects statistics about Binder call latency per calling API and method. */
@@ -34,18 +33,25 @@
private static final String TAG = "BinderLatencyObserver";
public static final int PERIODIC_SAMPLING_INTERVAL_DEFAULT = 10;
- // This is not the final data structure - we will eventually store latency histograms instead of
- // raw samples as it is much more memory / disk space efficient.
- // TODO(b/179999191): change this to store the histogram.
- // TODO(b/179999191): pre allocate the array size so we would not have to resize this.
+ // Histogram buckets parameters.
+ public static final int BUCKET_COUNT_DEFAULT = 100;
+ public static final int FIRST_BUCKET_SIZE_DEFAULT = 5;
+ public static final float BUCKET_SCALE_FACTOR_DEFAULT = 1.125f;
+
@GuardedBy("mLock")
- private final ArrayMap<LatencyDims, ArrayList<Long>> mLatencySamples = new ArrayMap<>();
+ private final ArrayMap<LatencyDims, int[]> mLatencyHistograms = new ArrayMap<>();
private final Object mLock = new Object();
// Sampling period to control how often to track CPU usage. 1 means all calls, 100 means ~1 out
// of 100 requests.
private int mPeriodicSamplingInterval = PERIODIC_SAMPLING_INTERVAL_DEFAULT;
+
+ private int mBucketCount = BUCKET_COUNT_DEFAULT;
+ private int mFirstBucketSize = FIRST_BUCKET_SIZE_DEFAULT;
+ private float mBucketScaleFactor = BUCKET_SCALE_FACTOR_DEFAULT;
+
private final Random mRandom;
+ private BinderLatencyBuckets mLatencyBuckets;
/** Injector for {@link BinderLatencyObserver}. */
public static class Injector {
@@ -56,6 +62,8 @@
public BinderLatencyObserver(Injector injector) {
mRandom = injector.getRandomGenerator();
+ mLatencyBuckets = new BinderLatencyBuckets(
+ mBucketCount, mFirstBucketSize, mBucketScaleFactor);
}
/** Should be called when a Binder call completes, will store latency data. */
@@ -67,12 +75,21 @@
LatencyDims dims = new LatencyDims(s.binderClass, s.transactionCode);
long callDuration = getElapsedRealtimeMicro() - s.timeStarted;
+ // Find the bucket this sample should go to.
+ int bucketIdx = mLatencyBuckets.sampleToBucket(
+ callDuration > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) callDuration);
+
synchronized (mLock) {
- if (!mLatencySamples.containsKey(dims)) {
- mLatencySamples.put(dims, new ArrayList<Long>());
+ int[] buckets = mLatencyHistograms.get(dims);
+ if (buckets == null) {
+ buckets = new int[mBucketCount];
+ mLatencyHistograms.put(dims, buckets);
}
- mLatencySamples.get(dims).add(callDuration);
+ // Increment the correct bucket.
+ if (buckets[bucketIdx] < Integer.MAX_VALUE) {
+ buckets[bucketIdx] += 1;
+ }
}
}
@@ -100,10 +117,26 @@
}
}
+ /** Updates the histogram buckets parameters. */
+ public void setHistogramBucketsParams(
+ int bucketCount, int firstBucketSize, float bucketScaleFactor) {
+ synchronized (mLock) {
+ if (bucketCount != mBucketCount || firstBucketSize != mFirstBucketSize
+ || bucketScaleFactor != mBucketScaleFactor) {
+ mBucketCount = bucketCount;
+ mFirstBucketSize = firstBucketSize;
+ mBucketScaleFactor = bucketScaleFactor;
+ mLatencyBuckets = new BinderLatencyBuckets(
+ mBucketCount, mFirstBucketSize, mBucketScaleFactor);
+ reset();
+ }
+ }
+ }
+
/** Resets the sample collection. */
public void reset() {
synchronized (mLock) {
- mLatencySamples.clear();
+ mLatencyHistograms.clear();
}
}
@@ -151,7 +184,7 @@
}
@VisibleForTesting
- public ArrayMap<LatencyDims, ArrayList<Long>> getLatencySamples() {
- return mLatencySamples;
+ public ArrayMap<LatencyDims, int[]> getLatencyHistograms() {
+ return mLatencyHistograms;
}
}
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index afd19b6..382acc0 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -149,7 +149,6 @@
"android_os_VintfRuntimeInfo.cpp",
"android_os_incremental_IncrementalManager.cpp",
"android_net_LocalSocketImpl.cpp",
- "android_net_NetworkUtils.cpp",
"android_service_DataLoaderService.cpp",
"android_util_AssetManager.cpp",
"android_util_Binder.cpp",
@@ -216,6 +215,7 @@
static_libs: [
"libasync_safe",
+ "libconnectivityframeworkutils",
"libbinderthreadstateutils",
"libdmabufinfo",
"libgif",
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 357f427..4a57448 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -398,6 +398,8 @@
<protected-broadcast android:name="android.net.wifi.p2p.action.WIFI_P2P_PERSISTENT_GROUPS_CHANGED" />
<protected-broadcast android:name="android.net.conn.TETHER_STATE_CHANGED" />
<protected-broadcast android:name="android.net.conn.INET_CONDITION_ACTION" />
+ <!-- This broadcast is no longer sent in S but it should stay protected to avoid third party
+ apps broadcasting this and confusing old system apps that may not have been updated. -->
<protected-broadcast android:name="android.net.conn.NETWORK_CONDITIONS_MEASURED" />
<protected-broadcast
android:name="android.net.ConnectivityService.action.PKT_CNT_SAMPLE_INTERVAL_ELAPSED" />
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 1156120..cec6216 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
@@ -764,7 +764,7 @@
bcs.elapsedTime += 20;
bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID);
- assertEquals(1, bcs.getLatencyObserver().getLatencySamples().size());
+ assertEquals(1, bcs.getLatencyObserver().getLatencyHistograms().size());
}
@Test
@@ -778,7 +778,7 @@
bcs.elapsedTime += 20;
bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID);
- assertEquals(0, bcs.getLatencyObserver().getLatencySamples().size());
+ assertEquals(0, bcs.getLatencyObserver().getLatencyHistograms().size());
}
class TestBinderCallsStats extends BinderCallsStats {
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderLatencyBucketsTest.java b/core/tests/coretests/src/com/android/internal/os/BinderLatencyBucketsTest.java
new file mode 100644
index 0000000..00443a9
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/BinderLatencyBucketsTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertEquals;
+
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+@Presubmit
+public class BinderLatencyBucketsTest {
+ @Test
+ public void testBucketThresholds() {
+ BinderLatencyBuckets latencyBuckets = new BinderLatencyBuckets(10, 2, 1.45f);
+ assertThat(latencyBuckets.getBuckets())
+ .containsExactly(2, 3, 4, 6, 8, 12, 18, 26, 39)
+ .inOrder();
+ }
+
+ @Test
+ public void testSampleAssignment() {
+ BinderLatencyBuckets latencyBuckets = new BinderLatencyBuckets(10, 2, 1.45f);
+ assertEquals(0, latencyBuckets.sampleToBucket(0));
+ assertEquals(0, latencyBuckets.sampleToBucket(1));
+ assertEquals(1, latencyBuckets.sampleToBucket(2));
+ assertEquals(2, latencyBuckets.sampleToBucket(3));
+ assertEquals(3, latencyBuckets.sampleToBucket(4));
+ assertEquals(5, latencyBuckets.sampleToBucket(9));
+ assertEquals(6, latencyBuckets.sampleToBucket(13));
+ assertEquals(7, latencyBuckets.sampleToBucket(25));
+ assertEquals(9, latencyBuckets.sampleToBucket(100));
+ }
+
+ @Test
+ public void testMaxIntBuckets() {
+ BinderLatencyBuckets latencyBuckets = new BinderLatencyBuckets(5, Integer.MAX_VALUE / 2, 2);
+ assertThat(latencyBuckets.getBuckets())
+ .containsExactly(Integer.MAX_VALUE / 2, Integer.MAX_VALUE - 1)
+ .inOrder();
+
+ assertEquals(0, latencyBuckets.sampleToBucket(0));
+ assertEquals(0, latencyBuckets.sampleToBucket(Integer.MAX_VALUE / 2 - 1));
+ assertEquals(1, latencyBuckets.sampleToBucket(Integer.MAX_VALUE - 2));
+ assertEquals(2, latencyBuckets.sampleToBucket(Integer.MAX_VALUE));
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderLatencyObserverTest.java b/core/tests/coretests/src/com/android/internal/os/BinderLatencyObserverTest.java
index 36915a2..f65fb95 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderLatencyObserverTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderLatencyObserverTest.java
@@ -33,7 +33,6 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
@@ -44,6 +43,7 @@
@Test
public void testLatencyCollectionWithMultipleClasses() {
TestBinderLatencyObserver blo = new TestBinderLatencyObserver();
+ blo.setHistogramBucketsParams(5, 5, 1.125f);
Binder binder = new Binder();
CallSession callSession = new CallSession();
@@ -51,20 +51,24 @@
callSession.transactionCode = 1;
blo.callEnded(callSession);
blo.callEnded(callSession);
+ blo.callEnded(callSession);
callSession.transactionCode = 2;
blo.callEnded(callSession);
+ blo.callEnded(callSession);
- ArrayMap<LatencyDims, ArrayList<Long>> latencySamples = blo.getLatencySamples();
- assertEquals(2, latencySamples.keySet().size());
- assertThat(latencySamples.get(new LatencyDims(binder.getClass(), 1)))
- .containsExactlyElementsIn(Arrays.asList(1L, 2L));
- assertThat(latencySamples.get(new LatencyDims(binder.getClass(), 2))).containsExactly(3L);
+ ArrayMap<LatencyDims, int[]> latencyHistograms = blo.getLatencyHistograms();
+ assertEquals(2, latencyHistograms.keySet().size());
+ assertThat(latencyHistograms.get(new LatencyDims(binder.getClass(), 1)))
+ .asList().containsExactly(2, 0, 1, 0, 0).inOrder();
+ assertThat(latencyHistograms.get(new LatencyDims(binder.getClass(), 2)))
+ .asList().containsExactly(0, 0, 0, 0, 2).inOrder();
}
@Test
public void testSampling() {
TestBinderLatencyObserver blo = new TestBinderLatencyObserver();
blo.setSamplingInterval(2);
+ blo.setHistogramBucketsParams(5, 5, 1.125f);
Binder binder = new Binder();
CallSession callSession = new CallSession();
@@ -74,17 +78,58 @@
callSession.transactionCode = 2;
blo.callEnded(callSession);
- ArrayMap<LatencyDims, ArrayList<Long>> latencySamples = blo.getLatencySamples();
- assertEquals(1, latencySamples.size());
- LatencyDims dims = latencySamples.keySet().iterator().next();
+ ArrayMap<LatencyDims, int[]> latencyHistograms = blo.getLatencyHistograms();
+ assertEquals(1, latencyHistograms.size());
+ LatencyDims dims = latencyHistograms.keySet().iterator().next();
assertEquals(binder.getClass(), dims.getBinderClass());
assertEquals(1, dims.getTransactionCode());
- ArrayList<Long> values = latencySamples.get(dims);
- assertThat(values).containsExactly(1L);
+ assertThat(latencyHistograms.get(dims)).asList().containsExactly(1, 0, 0, 0, 0).inOrder();
+ }
+
+ @Test
+ public void testTooCallLengthOverflow() {
+ TestBinderLatencyObserver blo = new TestBinderLatencyObserver();
+ blo.setElapsedTime(2L + (long) Integer.MAX_VALUE);
+ blo.setHistogramBucketsParams(5, 5, 1.125f);
+
+ Binder binder = new Binder();
+ CallSession callSession = new CallSession();
+ callSession.binderClass = binder.getClass();
+ callSession.transactionCode = 1;
+ blo.callEnded(callSession);
+
+ // The long call should be capped to maxint (to not overflow) and placed in the last bucket.
+ assertThat(blo.getLatencyHistograms()
+ .get(new LatencyDims(binder.getClass(), 1)))
+ .asList().containsExactly(0, 0, 0, 0, 1)
+ .inOrder();
+ }
+
+ @Test
+ public void testHistogramBucketOverflow() {
+ TestBinderLatencyObserver blo = new TestBinderLatencyObserver();
+ blo.setHistogramBucketsParams(3, 5, 1.125f);
+
+ Binder binder = new Binder();
+ CallSession callSession = new CallSession();
+ callSession.binderClass = binder.getClass();
+ callSession.transactionCode = 1;
+ blo.callEnded(callSession);
+
+ LatencyDims dims = new LatencyDims(binder.getClass(), 1);
+ // Fill the buckets with maxint.
+ Arrays.fill(blo.getLatencyHistograms().get(dims), Integer.MAX_VALUE);
+ assertThat(blo.getLatencyHistograms().get(dims))
+ .asList().containsExactly(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
+ // Try to add another sample.
+ blo.callEnded(callSession);
+ // Make sure the buckets don't overflow.
+ assertThat(blo.getLatencyHistograms().get(dims))
+ .asList().containsExactly(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
}
public static class TestBinderLatencyObserver extends BinderLatencyObserver {
- private long mElapsedTimeCallCount = 0;
+ private long mElapsedTime = 0;
TestBinderLatencyObserver() {
// Make random generator not random.
@@ -104,7 +149,12 @@
@Override
protected long getElapsedRealtimeMicro() {
- return ++mElapsedTimeCallCount;
+ mElapsedTime += 2;
+ return mElapsedTime;
+ }
+
+ public void setElapsedTime(long time) {
+ mElapsedTime = time;
}
}
}
diff --git a/keystore/java/android/security/KeyStore2.java b/keystore/java/android/security/KeyStore2.java
index df579bb..1034847 100644
--- a/keystore/java/android/security/KeyStore2.java
+++ b/keystore/java/android/security/KeyStore2.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.compat.annotation.ChangeId;
import android.compat.annotation.Disabled;
+import android.os.Binder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceSpecificException;
@@ -140,6 +141,7 @@
if (mBinder == null || retryLookup) {
mBinder = IKeystoreService.Stub.asInterface(ServiceManager
.getService(KEYSTORE2_SERVICE_NAME));
+ Binder.allowBlocking(mBinder.asBinder());
}
return mBinder;
}
diff --git a/keystore/java/android/security/KeyStoreOperation.java b/keystore/java/android/security/KeyStoreOperation.java
index a6552dd..e6c1ea8 100644
--- a/keystore/java/android/security/KeyStoreOperation.java
+++ b/keystore/java/android/security/KeyStoreOperation.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.hardware.security.keymint.KeyParameter;
+import android.os.Binder;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.security.keymaster.KeymasterDefs;
@@ -39,6 +40,7 @@
Long challenge,
KeyParameter[] parameters
) {
+ Binder.allowBlocking(operation.asBinder());
this.mOperation = operation;
this.mChallenge = challenge;
this.mParameters = parameters;
diff --git a/keystore/java/android/security/KeyStoreSecurityLevel.java b/keystore/java/android/security/KeyStoreSecurityLevel.java
index d188b65..b85dd74 100644
--- a/keystore/java/android/security/KeyStoreSecurityLevel.java
+++ b/keystore/java/android/security/KeyStoreSecurityLevel.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.app.compat.CompatChanges;
import android.hardware.security.keymint.KeyParameter;
+import android.os.Binder;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.security.keystore.BackendBusyException;
@@ -45,6 +46,7 @@
private final IKeystoreSecurityLevel mSecurityLevel;
public KeyStoreSecurityLevel(IKeystoreSecurityLevel securityLevel) {
+ Binder.allowBlocking(securityLevel.asBinder());
this.mSecurityLevel = securityLevel;
}
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java
index fe05989..97592b4 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java
@@ -252,7 +252,9 @@
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 3e2fb94..f3cfcf1 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.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 @@
}
private Set<String> getUniqueAliases() {
-
try {
final KeyDescriptor[] keys = mKeyStore.list(
getTargetDomain(),
@@ -987,7 +988,7 @@
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 @@
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 2315a85..7de4523 100644
--- a/keystore/tests/Android.bp
+++ b/keystore/tests/Android.bp
@@ -28,6 +28,7 @@
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 b7d72fc..2ae61ab 100644
--- a/keystore/tests/src/android/security/ParcelableKeyGenParameterSpecTest.java
+++ b/keystore/tests/src/android/security/ParcelableKeyGenParameterSpecTest.java
@@ -43,7 +43,6 @@
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 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 @@
.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 @@
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 b2edfd0..ddbb1d8 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.assertThat;
import android.security.ParcelableKeyGenParameterSpecTest;
-import android.security.keystore.KeyGenParameterSpec;
-import android.security.keystore.KeyProperties;
import androidx.test.runner.AndroidJUnit4;
@@ -41,7 +39,7 @@
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 0000000..1bd3069
--- /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/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index 139474c..67a040d 100644
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -28,6 +28,7 @@
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.telephony.PhoneNumberUtils;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
@@ -160,7 +161,7 @@
be set to true when the phone is having emergency call, and then will
be set to false by mPhoneStateListener when the emergency call ends.
*/
- mIsInEmergencyCall = mTelephonyManager.isEmergencyNumber(phoneNumber);
+ mIsInEmergencyCall = PhoneNumberUtils.isEmergencyNumber(phoneNumber);
if (DEBUG) Log.v(TAG, "ACTION_NEW_OUTGOING_CALL - " + getInEmergency());
} else if (action.equals(LocationManager.MODE_CHANGED_ACTION)) {
updateLocationMode();
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 2d9bdaf..3131965 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -127,6 +127,9 @@
public static final int SAMPLE_RATE_HZ_MIN = native_getMinSampleRate();
private static native int native_getMinSampleRate();
+ /** @hide */
+ public static final int FCC_24 = 24; // fixed channel count 24; do not change.
+
// Expose only the getter method publicly so we can change it in the future
private static final int NUM_STREAM_TYPES = 12;
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 7c91f52..68ce5e7 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -1712,9 +1712,10 @@
mChannelCount = 0;
break; // channel index configuration only
}
- if (!isMultichannelConfigSupported(channelConfig)) {
- // input channel configuration features unsupported channels
- throw new IllegalArgumentException("Unsupported channel configuration.");
+ if (!isMultichannelConfigSupported(channelConfig, audioFormat)) {
+ throw new IllegalArgumentException(
+ "Unsupported channel mask configuration " + channelConfig
+ + " for encoding " + audioFormat);
}
mChannelMask = channelConfig;
mChannelCount = AudioFormat.channelCountFromOutChannelMask(channelConfig);
@@ -1722,13 +1723,17 @@
// check the channel index configuration (if present)
mChannelIndexMask = channelIndexMask;
if (mChannelIndexMask != 0) {
- // restrictive: indexMask could allow up to AUDIO_CHANNEL_BITS_LOG2
- final int indexMask = (1 << AudioSystem.OUT_CHANNEL_COUNT_MAX) - 1;
- if ((channelIndexMask & ~indexMask) != 0) {
- throw new IllegalArgumentException("Unsupported channel index configuration "
- + channelIndexMask);
+ // As of S, we accept up to 24 channel index mask.
+ final int fullIndexMask = (1 << AudioSystem.FCC_24) - 1;
+ final int channelIndexCount = Integer.bitCount(channelIndexMask);
+ final boolean accepted = (channelIndexMask & ~fullIndexMask) == 0
+ && (!AudioFormat.isEncodingLinearFrames(audioFormat) // compressed OK
+ || channelIndexCount <= AudioSystem.OUT_CHANNEL_COUNT_MAX); // PCM
+ if (!accepted) {
+ throw new IllegalArgumentException(
+ "Unsupported channel index mask configuration " + channelIndexMask
+ + " for encoding " + audioFormat);
}
- int channelIndexCount = Integer.bitCount(channelIndexMask);
if (mChannelCount == 0) {
mChannelCount = channelIndexCount;
} else if (mChannelCount != channelIndexCount) {
@@ -1781,16 +1786,19 @@
* @param channelConfig the mask to validate
* @return false if the AudioTrack can't be used with such a mask
*/
- private static boolean isMultichannelConfigSupported(int channelConfig) {
+ private static boolean isMultichannelConfigSupported(int channelConfig, int encoding) {
// check for unsupported channels
if ((channelConfig & SUPPORTED_OUT_CHANNELS) != channelConfig) {
loge("Channel configuration features unsupported channels");
return false;
}
final int channelCount = AudioFormat.channelCountFromOutChannelMask(channelConfig);
- if (channelCount > AudioSystem.OUT_CHANNEL_COUNT_MAX) {
- loge("Channel configuration contains too many channels " +
- channelCount + ">" + AudioSystem.OUT_CHANNEL_COUNT_MAX);
+ final int channelCountLimit = AudioFormat.isEncodingLinearFrames(encoding)
+ ? AudioSystem.OUT_CHANNEL_COUNT_MAX // PCM limited to OUT_CHANNEL_COUNT_MAX
+ : AudioSystem.FCC_24; // Compressed limited to 24 channels
+ if (channelCount > channelCountLimit) {
+ loge("Channel configuration contains too many channels for encoding "
+ + encoding + "(" + channelCount + " > " + channelCountLimit + ")");
return false;
}
// check for unsupported multichannel combinations:
@@ -2301,7 +2309,7 @@
channelCount = 2;
break;
default:
- if (!isMultichannelConfigSupported(channelConfig)) {
+ if (!isMultichannelConfigSupported(channelConfig, audioFormat)) {
loge("getMinBufferSize(): Invalid channel configuration.");
return ERROR_BAD_VALUE;
} else {
diff --git a/packages/Connectivity/framework/Android.bp b/packages/Connectivity/framework/Android.bp
index 017ff51..657d5a3 100644
--- a/packages/Connectivity/framework/Android.bp
+++ b/packages/Connectivity/framework/Android.bp
@@ -25,6 +25,7 @@
java_library {
name: "framework-connectivity-protos",
+ sdk_version: "module_current",
proto: {
type: "nano",
},
@@ -82,8 +83,7 @@
name: "framework-connectivity",
api_only: true,
defaults: ["framework-module-defaults"],
- // TODO: build against module API
- platform_apis: true,
+ installable: true,
srcs: [
":framework-connectivity-sources",
],
@@ -100,18 +100,56 @@
libs: [
"unsupportedappusage",
],
- permitted_packages: ["android.net", "com.android.connectivity.aidl"],
+ permitted_packages: ["android.net"],
+}
+
+cc_defaults {
+ name: "libframework-connectivity-defaults",
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-parameter",
+ "-Wthread-safety",
+ ],
+ shared_libs: [
+ "libbase",
+ "liblog",
+ "libnativehelper",
+ "libnetd_client",
+ ],
+ header_libs: [
+ "dnsproxyd_protocol_headers",
+ ],
+}
+
+cc_library_static {
+ name: "libconnectivityframeworkutils",
+ defaults: ["libframework-connectivity-defaults"],
+ srcs: [
+ "jni/android_net_NetworkUtils.cpp",
+ ],
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.tethering",
+ ],
+}
+
+cc_library_shared {
+ name: "libframework-connectivity-jni",
+ defaults: ["libframework-connectivity-defaults"],
+ srcs: [
+ "jni/onload.cpp",
+ ],
+ static_libs: ["libconnectivityframeworkutils"],
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.tethering",
+ ],
}
java_library {
name: "framework-connectivity.impl",
- // Instead of building against private API (framework.jar),
- // build against core_platform + framework-minus-apex + module
- // stub libs. This allows framework.jar to depend on this library,
- // so it can be part of the private API until all clients have been migrated.
- // TODO: just build against module_api, and remove this jar from
- // the private API.
- sdk_version: "core_platform",
+ sdk_version: "module_current",
srcs: [
":framework-connectivity-sources",
],
@@ -122,12 +160,11 @@
],
},
libs: [
- "framework-minus-apex",
- // TODO: just framework-tethering, framework-wifi when building against module_api
- "framework-tethering.stubs.module_lib",
- "framework-wifi.stubs.module_lib",
+ // TODO (b/183097033) remove once module_current includes core_current
+ "stable.core.platform.api.stubs",
+ "framework-tethering",
+ "framework-wifi",
"unsupportedappusage",
- "ServiceConnectivityResources",
],
static_libs: [
"framework-connectivity-protos",
@@ -136,5 +173,5 @@
jarjar_rules: "jarjar-rules.txt",
apex_available: ["com.android.tethering"],
installable: true,
- permitted_packages: ["android.net", "com.android.connectivity.aidl"],
+ permitted_packages: ["android.net"],
}
diff --git a/packages/Connectivity/framework/api/module-lib-current.txt b/packages/Connectivity/framework/api/module-lib-current.txt
index a8e2517..6c454bc 100644
--- a/packages/Connectivity/framework/api/module-lib-current.txt
+++ b/packages/Connectivity/framework/api/module-lib-current.txt
@@ -10,7 +10,6 @@
method @NonNull @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public java.util.List<android.net.NetworkStateSnapshot> getAllNetworkStateSnapshots();
method @Nullable public android.net.ProxyInfo getGlobalProxy();
method @NonNull public static android.util.Range<java.lang.Integer> getIpSecNetIdRange();
- method @NonNull public static String getPrivateDnsMode(@NonNull android.content.Context);
method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerDefaultNetworkCallbackForUid(int, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
@@ -20,7 +19,6 @@
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void setAvoidUnvalidated(@NonNull android.net.Network);
method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setGlobalProxy(@Nullable android.net.ProxyInfo);
method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void setLegacyLockdownVpnEnabled(boolean);
- method public static void setPrivateDnsMode(@NonNull android.content.Context, @NonNull String);
method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setProfileNetworkPreference(@NonNull android.os.UserHandle, int, @Nullable java.util.concurrent.Executor, @Nullable Runnable);
method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void setRequireVpnForUids(boolean, @NonNull java.util.Collection<android.util.Range<java.lang.Integer>>);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle);
@@ -40,9 +38,6 @@
field public static final int BLOCKED_REASON_LOCKDOWN_VPN = 16; // 0x10
field public static final int BLOCKED_REASON_NONE = 0; // 0x0
field public static final int BLOCKED_REASON_RESTRICTED_MODE = 8; // 0x8
- field public static final String PRIVATE_DNS_MODE_OFF = "off";
- field public static final String PRIVATE_DNS_MODE_OPPORTUNISTIC = "opportunistic";
- field public static final String PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = "hostname";
field public static final int PROFILE_NETWORK_PREFERENCE_DEFAULT = 0; // 0x0
field public static final int PROFILE_NETWORK_PREFERENCE_ENTERPRISE = 1; // 0x1
}
@@ -53,6 +48,7 @@
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);
@@ -62,15 +58,17 @@
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);
method @NonNull public static java.time.Duration getNetworkSwitchNotificationRateDuration(@NonNull android.content.Context, @NonNull java.time.Duration);
method @NonNull public static String getPrivateDnsDefaultMode(@NonNull android.content.Context);
method @Nullable public static String getPrivateDnsHostname(@NonNull android.content.Context);
+ 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);
@@ -80,13 +78,14 @@
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);
method public static void setNetworkSwitchNotificationRateDuration(@NonNull android.content.Context, @NonNull java.time.Duration);
- method public static void setPrivateDnsDefaultMode(@NonNull android.content.Context, @NonNull String);
+ method public static void setPrivateDnsDefaultMode(@NonNull android.content.Context, @NonNull int);
method public static void setPrivateDnsHostname(@NonNull android.content.Context, @Nullable String);
+ method public static void setPrivateDnsMode(@NonNull android.content.Context, int);
method public static void setWifiAlwaysRequested(@NonNull android.content.Context, boolean);
method public static void setWifiDataActivityTimeout(@NonNull android.content.Context, @NonNull java.time.Duration);
field public static final int CAPTIVE_PORTAL_MODE_AVOID = 2; // 0x2
@@ -95,6 +94,9 @@
field public static final int NETWORK_AVOID_BAD_WIFI_AVOID = 2; // 0x2
field public static final int NETWORK_AVOID_BAD_WIFI_IGNORE = 0; // 0x0
field public static final int NETWORK_AVOID_BAD_WIFI_PROMPT = 1; // 0x1
+ field public static final int PRIVATE_DNS_MODE_OFF = 1; // 0x1
+ field public static final int PRIVATE_DNS_MODE_OPPORTUNISTIC = 2; // 0x2
+ field public static final int PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = 3; // 0x3
}
public final class NetworkAgentConfig implements android.os.Parcelable {
@@ -109,7 +111,7 @@
public final class NetworkCapabilities implements android.os.Parcelable {
method @Nullable public java.util.Set<android.util.Range<java.lang.Integer>> getUids();
- method public boolean hasUnwantedCapability(int);
+ method public boolean hasForbiddenCapability(int);
field public static final long REDACT_ALL = -1L; // 0xffffffffffffffffL
field public static final long REDACT_FOR_ACCESS_FINE_LOCATION = 1L; // 0x1L
field public static final long REDACT_FOR_LOCAL_MAC_ADDRESS = 2L; // 0x2L
@@ -123,13 +125,13 @@
}
public class NetworkRequest implements android.os.Parcelable {
- method @NonNull public int[] getUnwantedCapabilities();
- method public boolean hasUnwantedCapability(int);
+ method @NonNull public int[] getForbiddenCapabilities();
+ method public boolean hasForbiddenCapability(int);
}
public static class NetworkRequest.Builder {
- method @NonNull public android.net.NetworkRequest.Builder addUnwantedCapability(int);
- method @NonNull public android.net.NetworkRequest.Builder removeUnwantedCapability(int);
+ method @NonNull public android.net.NetworkRequest.Builder addForbiddenCapability(int);
+ method @NonNull public android.net.NetworkRequest.Builder removeForbiddenCapability(int);
method @NonNull public android.net.NetworkRequest.Builder setUids(@Nullable java.util.Set<android.util.Range<java.lang.Integer>>);
}
diff --git a/core/jni/android_net_NetworkUtils.cpp b/packages/Connectivity/framework/jni/android_net_NetworkUtils.cpp
similarity index 93%
rename from core/jni/android_net_NetworkUtils.cpp
rename to packages/Connectivity/framework/jni/android_net_NetworkUtils.cpp
index 1cee895..48e262a 100644
--- a/core/jni/android_net_NetworkUtils.cpp
+++ b/packages/Connectivity/framework/jni/android_net_NetworkUtils.cpp
@@ -30,13 +30,13 @@
#include <DnsProxydProtocol.h> // NETID_USE_LOCAL_NAMESERVERS
#include <cutils/properties.h>
+#include <nativehelper/JNIHelp.h>
#include <nativehelper/JNIPlatformHelp.h>
#include <nativehelper/ScopedLocalRef.h>
#include <utils/Log.h>
#include <utils/misc.h>
#include "NetdClient.h"
-#include "core_jni_helpers.h"
#include "jni.h"
extern "C" {
@@ -52,6 +52,19 @@
// FrameworkListener limits the size of commands to 4096 bytes.
constexpr int MAXCMDSIZE = 4096;
+static inline jclass FindClassOrDie(JNIEnv* env, const char* class_name) {
+ jclass clazz = env->FindClass(class_name);
+ LOG_ALWAYS_FATAL_IF(clazz == NULL, "Unable to find class %s", class_name);
+ return clazz;
+}
+
+template <typename T>
+static inline T MakeGlobalRefOrDie(JNIEnv* env, T in) {
+ jobject res = env->NewGlobalRef(in);
+ LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to create global reference.");
+ return static_cast<T>(res);
+}
+
static void android_net_utils_attachDropAllBPFFilter(JNIEnv *env, jobject clazz, jobject javaFd)
{
struct sock_filter filter_code[] = {
@@ -254,8 +267,8 @@
int register_android_net_NetworkUtils(JNIEnv* env)
{
- return RegisterMethodsOrDie(env, NETUTILS_PKG_NAME, gNetworkUtilMethods,
- NELEM(gNetworkUtilMethods));
+ return jniRegisterNativeMethods(env, NETUTILS_PKG_NAME, gNetworkUtilMethods,
+ NELEM(gNetworkUtilMethods));
}
}; // namespace android
diff --git a/packages/Connectivity/framework/jni/onload.cpp b/packages/Connectivity/framework/jni/onload.cpp
new file mode 100644
index 0000000..435f434
--- /dev/null
+++ b/packages/Connectivity/framework/jni/onload.cpp
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#include <nativehelper/JNIHelp.h>
+#include <log/log.h>
+
+namespace android {
+
+int register_android_net_NetworkUtils(JNIEnv* env);
+
+extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
+ JNIEnv *env;
+ if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+ ALOGE("GetEnv failed");
+ return JNI_ERR;
+ }
+
+ if (register_android_net_NetworkUtils(env) < 0) {
+ return JNI_ERR;
+ }
+
+ return JNI_VERSION_1_6;
+}
+
+};
\ No newline at end of file
diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
index 19764dd..1a6b37b 100644
--- a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
+++ b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
@@ -16,8 +16,6 @@
package android.net;
import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
-import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_DEFAULT_MODE;
-import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE;
import static android.net.NetworkRequest.Type.BACKGROUND_REQUEST;
import static android.net.NetworkRequest.Type.LISTEN;
import static android.net.NetworkRequest.Type.LISTEN_FOR_BEST;
@@ -33,7 +31,6 @@
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.StringDef;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
@@ -41,7 +38,6 @@
import android.app.admin.DevicePolicyManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityDiagnosticsManager.DataStallReport.DetectionMethod;
@@ -70,7 +66,6 @@
import android.provider.Settings;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
-import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Range;
@@ -821,38 +816,6 @@
public static final int NETID_UNSET = 0;
/**
- * Private DNS Mode values.
- *
- * The "private_dns_mode" global setting stores a String value which is
- * expected to be one of the following.
- */
-
- /**
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public static final String PRIVATE_DNS_MODE_OFF = "off";
- /**
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public static final String PRIVATE_DNS_MODE_OPPORTUNISTIC = "opportunistic";
- /**
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public static final String PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = "hostname";
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @StringDef(value = {
- PRIVATE_DNS_MODE_OFF,
- PRIVATE_DNS_MODE_OPPORTUNISTIC,
- PRIVATE_DNS_MODE_PROVIDER_HOSTNAME,
- })
- public @interface PrivateDnsMode {}
-
- /**
* Flag to indicate that an app is not subject to any restrictions that could result in its
* network access blocked.
*
@@ -3374,7 +3337,60 @@
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,
@@ -5448,44 +5464,4 @@
public static Range<Integer> getIpSecNetIdRange() {
return new Range(TUN_INTF_NETID_START, TUN_INTF_NETID_START + TUN_INTF_NETID_RANGE - 1);
}
-
- /**
- * Get private DNS mode from settings.
- *
- * @param context The Context to query the private DNS mode from settings.
- * @return A string of private DNS mode as one of the PRIVATE_DNS_MODE_* constants.
- *
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- @NonNull
- @PrivateDnsMode
- public static String getPrivateDnsMode(@NonNull Context context) {
- final ContentResolver cr = context.getContentResolver();
- String mode = Settings.Global.getString(cr, PRIVATE_DNS_MODE);
- if (TextUtils.isEmpty(mode)) mode = Settings.Global.getString(cr, PRIVATE_DNS_DEFAULT_MODE);
- // If both PRIVATE_DNS_MODE and PRIVATE_DNS_DEFAULT_MODE are not set, choose
- // PRIVATE_DNS_MODE_OPPORTUNISTIC as default mode.
- if (TextUtils.isEmpty(mode)) mode = PRIVATE_DNS_MODE_OPPORTUNISTIC;
- return mode;
- }
-
- /**
- * Set private DNS mode to settings.
- *
- * @param context The {@link Context} to set the private DNS mode.
- * @param mode The private dns mode. This should be one of the PRIVATE_DNS_MODE_* constants.
- *
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public static void setPrivateDnsMode(@NonNull Context context,
- @NonNull @PrivateDnsMode String mode) {
- if (!(mode == PRIVATE_DNS_MODE_OFF
- || mode == PRIVATE_DNS_MODE_OPPORTUNISTIC
- || mode == PRIVATE_DNS_MODE_PROVIDER_HOSTNAME)) {
- throw new IllegalArgumentException("Invalid private dns mode");
- }
- Settings.Global.putString(context.getContentResolver(), PRIVATE_DNS_MODE, mode);
- }
}
diff --git a/packages/Connectivity/framework/src/android/net/ConnectivitySettingsManager.java b/packages/Connectivity/framework/src/android/net/ConnectivitySettingsManager.java
index 9a00055..762f24f 100644
--- a/packages/Connectivity/framework/src/android/net/ConnectivitySettingsManager.java
+++ b/packages/Connectivity/framework/src/android/net/ConnectivitySettingsManager.java
@@ -19,20 +19,20 @@
import static android.net.ConnectivityManager.MULTIPATH_PREFERENCE_HANDOVER;
import static android.net.ConnectivityManager.MULTIPATH_PREFERENCE_PERFORMANCE;
import static android.net.ConnectivityManager.MULTIPATH_PREFERENCE_RELIABILITY;
-import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
-import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
-import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.content.ContentResolver;
import android.content.Context;
import android.net.ConnectivityManager.MultipathPreference;
-import android.net.ConnectivityManager.PrivateDnsMode;
+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;
@@ -41,6 +41,8 @@
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.
@@ -333,12 +335,51 @@
"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.
+ */
+ public static final int PRIVATE_DNS_MODE_OFF = 1;
+
+ /**
+ * One of the private DNS modes that indicates the private DNS mode is automatic, which
+ * will try to use the current DNS as private DNS.
+ */
+ public static final int PRIVATE_DNS_MODE_OPPORTUNISTIC = 2;
+
+ /**
+ * One of the private DNS modes that indicates the private DNS mode is strict and the
+ * {@link #PRIVATE_DNS_SPECIFIER} is required, which will try to use the value of
+ * {@link #PRIVATE_DNS_SPECIFIER} as private DNS.
+ */
+ public static final int PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = 3;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ PRIVATE_DNS_MODE_OFF,
+ PRIVATE_DNS_MODE_OPPORTUNISTIC,
+ PRIVATE_DNS_MODE_PROVIDER_HOSTNAME,
+ })
+ public @interface PrivateDnsMode {}
+
+ private static final String PRIVATE_DNS_MODE_OFF_STRING = "off";
+ private static final String PRIVATE_DNS_MODE_OPPORTUNISTIC_STRING = "opportunistic";
+ 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}.
@@ -689,6 +730,65 @@
context.getContentResolver(), GLOBAL_HTTP_PROXY_PAC, "" /* value */);
}
+ private static String getPrivateDnsModeAsString(@PrivateDnsMode int mode) {
+ switch (mode) {
+ case PRIVATE_DNS_MODE_OFF:
+ return PRIVATE_DNS_MODE_OFF_STRING;
+ case PRIVATE_DNS_MODE_OPPORTUNISTIC:
+ return PRIVATE_DNS_MODE_OPPORTUNISTIC_STRING;
+ case PRIVATE_DNS_MODE_PROVIDER_HOSTNAME:
+ return PRIVATE_DNS_MODE_PROVIDER_HOSTNAME_STRING;
+ default:
+ throw new IllegalArgumentException("Invalid private dns mode: " + mode);
+ }
+ }
+
+ private static int getPrivateDnsModeAsInt(String mode) {
+ switch (mode) {
+ case "off":
+ return PRIVATE_DNS_MODE_OFF;
+ case "hostname":
+ return PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
+ case "opportunistic":
+ return PRIVATE_DNS_MODE_OPPORTUNISTIC;
+ default:
+ throw new IllegalArgumentException("Invalid private dns mode: " + mode);
+ }
+ }
+
+ /**
+ * Get private DNS mode from settings.
+ *
+ * @param context The Context to query the private DNS mode from settings.
+ * @return A string of private DNS mode.
+ */
+ @PrivateDnsMode
+ public static int getPrivateDnsMode(@NonNull Context context) {
+ final ContentResolver cr = context.getContentResolver();
+ String mode = Settings.Global.getString(cr, PRIVATE_DNS_MODE);
+ if (TextUtils.isEmpty(mode)) mode = Settings.Global.getString(cr, PRIVATE_DNS_DEFAULT_MODE);
+ // If both PRIVATE_DNS_MODE and PRIVATE_DNS_DEFAULT_MODE are not set, choose
+ // PRIVATE_DNS_MODE_OPPORTUNISTIC as default mode.
+ if (TextUtils.isEmpty(mode)) return PRIVATE_DNS_MODE_OPPORTUNISTIC;
+ return getPrivateDnsModeAsInt(mode);
+ }
+
+ /**
+ * Set private DNS mode to settings.
+ *
+ * @param context The {@link Context} to set the private DNS mode.
+ * @param mode The private dns mode. This should be one of the PRIVATE_DNS_MODE_* constants.
+ */
+ public static void setPrivateDnsMode(@NonNull Context context, @PrivateDnsMode int mode) {
+ if (!(mode == PRIVATE_DNS_MODE_OFF
+ || mode == PRIVATE_DNS_MODE_OPPORTUNISTIC
+ || mode == PRIVATE_DNS_MODE_PROVIDER_HOSTNAME)) {
+ throw new IllegalArgumentException("Invalid private dns mode: " + mode);
+ }
+ Settings.Global.putString(context.getContentResolver(), PRIVATE_DNS_MODE,
+ getPrivateDnsModeAsString(mode));
+ }
+
/**
* Get specific private dns provider name from {@link Settings}.
*
@@ -731,13 +831,14 @@
* constants.
*/
public static void setPrivateDnsDefaultMode(@NonNull Context context,
- @NonNull @PrivateDnsMode String mode) {
+ @NonNull @PrivateDnsMode int mode) {
if (!(mode == PRIVATE_DNS_MODE_OFF
|| mode == PRIVATE_DNS_MODE_OPPORTUNISTIC
|| mode == PRIVATE_DNS_MODE_PROVIDER_HOSTNAME)) {
throw new IllegalArgumentException("Invalid private dns mode");
}
- Settings.Global.putString(context.getContentResolver(), PRIVATE_DNS_DEFAULT_MODE, mode);
+ Settings.Global.putString(context.getContentResolver(), PRIVATE_DNS_DEFAULT_MODE,
+ getPrivateDnsModeAsString(mode));
}
/**
@@ -903,27 +1004,84 @@
}
/**
- * 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 a7cb618f..d937c9cd 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.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 @@
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 0000000..67d2d405
--- /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 950b1c7..c19a906 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java
@@ -139,19 +139,13 @@
*/
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 @@
* @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,15 +171,7 @@
* @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 = mUnwantedNetworkCapabilities = 0;
+ mNetworkCapabilities = mTransportTypes = mForbiddenNetworkCapabilities = 0;
mLinkUpBandwidthKbps = mLinkDownBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED;
mNetworkSpecifier = null;
mTransportInfo = null;
@@ -211,7 +199,7 @@
mLinkDownBandwidthKbps = nc.mLinkDownBandwidthKbps;
mNetworkSpecifier = nc.mNetworkSpecifier;
if (nc.getTransportInfo() != null) {
- setTransportInfo(nc.getTransportInfo().makeCopy(mRedactions));
+ setTransportInfo(nc.getTransportInfo());
} else {
setTransportInfo(null);
}
@@ -219,7 +207,7 @@
mUids = (nc.mUids == null) ? null : new ArraySet<>(nc.mUids);
setAdministratorUids(nc.getAdministratorUids());
mOwnerUid = nc.mOwnerUid;
- mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities;
+ mForbiddenNetworkCapabilities = nc.mForbiddenNetworkCapabilities;
mSSID = nc.mSSID;
mPrivateDnsBroken = nc.mPrivateDnsBroken;
mRequestorUid = nc.mRequestorUid;
@@ -237,7 +225,7 @@
/**
* If any capabilities specified here they must not exist in the matching Network.
*/
- private long mUnwantedNetworkCapabilities;
+ private long mForbiddenNetworkCapabilities;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -586,21 +574,21 @@
* @hide
*/
public @NonNull NetworkCapabilities addCapability(@NetCapability int capability) {
- // If the given capability was previously added to the list of unwanted capabilities
- // then the capability will also be removed from the list of unwanted capabilities.
- // TODO: Consider adding unwanted capabilities to the public API and mention this
+ // If the given capability was previously added to the list of forbidden capabilities
+ // then the capability will also be removed from the list of forbidden capabilities.
+ // TODO: Consider adding forbidden capabilities to the public API and mention this
// in the documentation.
checkValidCapability(capability);
mNetworkCapabilities |= 1L << capability;
- // remove from unwanted capability list
- mUnwantedNetworkCapabilities &= ~(1L << capability);
+ // remove from forbidden capability list
+ mForbiddenNetworkCapabilities &= ~(1L << capability);
return this;
}
/**
- * Adds the given capability to the list of unwanted capabilities of this
+ * Adds the given capability to the list of forbidden capabilities of this
* {@code NetworkCapability} instance. Note that when searching for a network to
- * satisfy a request, the network must not contain any capability from unwanted capability
+ * satisfy a request, the network must not contain any capability from forbidden capability
* list.
* <p>
* If the capability was previously added to the list of required capabilities (for
@@ -610,9 +598,9 @@
* @see #addCapability(int)
* @hide
*/
- public void addUnwantedCapability(@NetCapability int capability) {
+ public void addForbiddenCapability(@NetCapability int capability) {
checkValidCapability(capability);
- mUnwantedNetworkCapabilities |= 1L << capability;
+ mForbiddenNetworkCapabilities |= 1L << capability;
mNetworkCapabilities &= ~(1L << capability); // remove from requested capabilities
}
@@ -632,16 +620,16 @@
}
/**
- * Removes (if found) the given unwanted capability from this {@code NetworkCapability}
- * instance that were added via addUnwantedCapability(int) or setCapabilities(int[], int[]).
+ * Removes (if found) the given forbidden capability from this {@code NetworkCapability}
+ * instance that were added via addForbiddenCapability(int) or setCapabilities(int[], int[]).
*
* @param capability the capability to be removed.
* @return This NetworkCapabilities instance, to facilitate chaining.
* @hide
*/
- public @NonNull NetworkCapabilities removeUnwantedCapability(@NetCapability int capability) {
+ public @NonNull NetworkCapabilities removeForbiddenCapability(@NetCapability int capability) {
checkValidCapability(capability);
- mUnwantedNetworkCapabilities &= ~(1L << capability);
+ mForbiddenNetworkCapabilities &= ~(1L << capability);
return this;
}
@@ -670,13 +658,13 @@
}
/**
- * Gets all the unwanted capabilities set on this {@code NetworkCapability} instance.
+ * Gets all the forbidden capabilities set on this {@code NetworkCapability} instance.
*
- * @return an array of unwanted capability values for this instance.
+ * @return an array of forbidden capability values for this instance.
* @hide
*/
- public @NetCapability int[] getUnwantedCapabilities() {
- return NetworkCapabilitiesUtils.unpackBits(mUnwantedNetworkCapabilities);
+ public @NetCapability int[] getForbiddenCapabilities() {
+ return NetworkCapabilitiesUtils.unpackBits(mForbiddenNetworkCapabilities);
}
@@ -687,9 +675,9 @@
* @hide
*/
public void setCapabilities(@NetCapability int[] capabilities,
- @NetCapability int[] unwantedCapabilities) {
+ @NetCapability int[] forbiddenCapabilities) {
mNetworkCapabilities = NetworkCapabilitiesUtils.packBits(capabilities);
- mUnwantedNetworkCapabilities = NetworkCapabilitiesUtils.packBits(unwantedCapabilities);
+ mForbiddenNetworkCapabilities = NetworkCapabilitiesUtils.packBits(forbiddenCapabilities);
}
/**
@@ -714,9 +702,9 @@
/** @hide */
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
- public boolean hasUnwantedCapability(@NetCapability int capability) {
+ public boolean hasForbiddenCapability(@NetCapability int capability) {
return isValidCapability(capability)
- && ((mUnwantedNetworkCapabilities & (1L << capability)) != 0);
+ && ((mForbiddenNetworkCapabilities & (1L << capability)) != 0);
}
/**
@@ -746,14 +734,14 @@
private void combineNetCapabilities(@NonNull NetworkCapabilities nc) {
final long wantedCaps = this.mNetworkCapabilities | nc.mNetworkCapabilities;
- final long unwantedCaps =
- this.mUnwantedNetworkCapabilities | nc.mUnwantedNetworkCapabilities;
- if ((wantedCaps & unwantedCaps) != 0) {
+ final long forbiddenCaps =
+ this.mForbiddenNetworkCapabilities | nc.mForbiddenNetworkCapabilities;
+ if ((wantedCaps & forbiddenCaps) != 0) {
throw new IllegalArgumentException(
- "Cannot have the same capability in wanted and unwanted lists.");
+ "Cannot have the same capability in wanted and forbidden lists.");
}
this.mNetworkCapabilities = wantedCaps;
- this.mUnwantedNetworkCapabilities = unwantedCaps;
+ this.mForbiddenNetworkCapabilities = forbiddenCaps;
}
/**
@@ -764,7 +752,7 @@
* @hide
*/
public @Nullable String describeFirstNonRequestableCapability() {
- final long nonRequestable = (mNetworkCapabilities | mUnwantedNetworkCapabilities)
+ final long nonRequestable = (mNetworkCapabilities | mForbiddenNetworkCapabilities)
& NON_REQUESTABLE_CAPABILITIES;
if (nonRequestable != 0) {
@@ -781,28 +769,28 @@
private boolean satisfiedByNetCapabilities(@NonNull NetworkCapabilities nc,
boolean onlyImmutable) {
long requestedCapabilities = mNetworkCapabilities;
- long requestedUnwantedCapabilities = mUnwantedNetworkCapabilities;
+ long requestedForbiddenCapabilities = mForbiddenNetworkCapabilities;
long providedCapabilities = nc.mNetworkCapabilities;
if (onlyImmutable) {
requestedCapabilities &= ~MUTABLE_CAPABILITIES;
- requestedUnwantedCapabilities &= ~MUTABLE_CAPABILITIES;
+ requestedForbiddenCapabilities &= ~MUTABLE_CAPABILITIES;
}
return ((providedCapabilities & requestedCapabilities) == requestedCapabilities)
- && ((requestedUnwantedCapabilities & providedCapabilities) == 0);
+ && ((requestedForbiddenCapabilities & providedCapabilities) == 0);
}
/** @hide */
public boolean equalsNetCapabilities(@NonNull NetworkCapabilities nc) {
return (nc.mNetworkCapabilities == this.mNetworkCapabilities)
- && (nc.mUnwantedNetworkCapabilities == this.mUnwantedNetworkCapabilities);
+ && (nc.mForbiddenNetworkCapabilities == this.mForbiddenNetworkCapabilities);
}
private boolean equalsNetCapabilitiesRequestable(@NonNull NetworkCapabilities that) {
- return ((this.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES) ==
- (that.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES))
- && ((this.mUnwantedNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES) ==
- (that.mUnwantedNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES));
+ return ((this.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES)
+ == (that.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES))
+ && ((this.mForbiddenNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES)
+ == (that.mForbiddenNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES));
}
/**
@@ -830,8 +818,17 @@
final int[] originalAdministratorUids = getAdministratorUids();
final TransportInfo originalTransportInfo = getTransportInfo();
clearAll();
- mTransportTypes = (originalTransportTypes & TEST_NETWORKS_ALLOWED_TRANSPORTS)
- | (1 << TRANSPORT_TEST);
+ if (0 != (originalCapabilities & NET_CAPABILITY_NOT_RESTRICTED)) {
+ // If the test network is not restricted, then it is only allowed to declare some
+ // specific transports. This is to minimize impact on running apps in case an app
+ // run from the shell creates a test a network.
+ mTransportTypes =
+ (originalTransportTypes & UNRESTRICTED_TEST_NETWORKS_ALLOWED_TRANSPORTS)
+ | (1 << TRANSPORT_TEST);
+ } else {
+ // If the test transport is restricted, then it may declare any transport.
+ mTransportTypes = (originalTransportTypes | (1 << TRANSPORT_TEST));
+ }
mNetworkCapabilities = originalCapabilities & TEST_NETWORKS_ALLOWED_CAPABILITIES;
mNetworkSpecifier = originalSpecifier;
mSignalStrength = originalSignalStrength;
@@ -935,9 +932,10 @@
};
/**
- * Allowed transports on a test network, in addition to TRANSPORT_TEST.
+ * Allowed transports on an unrestricted test network (in addition to TRANSPORT_TEST).
*/
- private static final int TEST_NETWORKS_ALLOWED_TRANSPORTS = 1 << TRANSPORT_TEST
+ private static final int UNRESTRICTED_TEST_NETWORKS_ALLOWED_TRANSPORTS =
+ 1 << TRANSPORT_TEST
// Test ethernet networks can be created with EthernetManager#setIncludeTestInterfaces
| 1 << TRANSPORT_ETHERNET
// Test VPN networks can be created but their UID ranges must be empty.
@@ -1718,7 +1716,7 @@
* Combine a set of Capabilities to this one. Useful for coming up with the complete set.
* <p>
* Note that this method may break an invariant of having a particular capability in either
- * wanted or unwanted lists but never in both. Requests that have the same capability in
+ * wanted or forbidden lists but never in both. Requests that have the same capability in
* both lists will never be satisfied.
* @hide
*/
@@ -1859,8 +1857,8 @@
public int hashCode() {
return (int) (mNetworkCapabilities & 0xFFFFFFFF)
+ ((int) (mNetworkCapabilities >> 32) * 3)
- + ((int) (mUnwantedNetworkCapabilities & 0xFFFFFFFF) * 5)
- + ((int) (mUnwantedNetworkCapabilities >> 32) * 7)
+ + ((int) (mForbiddenNetworkCapabilities & 0xFFFFFFFF) * 5)
+ + ((int) (mForbiddenNetworkCapabilities >> 32) * 7)
+ ((int) (mTransportTypes & 0xFFFFFFFF) * 11)
+ ((int) (mTransportTypes >> 32) * 13)
+ mLinkUpBandwidthKbps * 17
@@ -1895,7 +1893,7 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(mNetworkCapabilities);
- dest.writeLong(mUnwantedNetworkCapabilities);
+ dest.writeLong(mForbiddenNetworkCapabilities);
dest.writeLong(mTransportTypes);
dest.writeInt(mLinkUpBandwidthKbps);
dest.writeInt(mLinkDownBandwidthKbps);
@@ -1919,7 +1917,7 @@
NetworkCapabilities netCap = new NetworkCapabilities();
netCap.mNetworkCapabilities = in.readLong();
- netCap.mUnwantedNetworkCapabilities = in.readLong();
+ netCap.mForbiddenNetworkCapabilities = in.readLong();
netCap.mTransportTypes = in.readLong();
netCap.mLinkUpBandwidthKbps = in.readInt();
netCap.mLinkDownBandwidthKbps = in.readInt();
@@ -1973,9 +1971,9 @@
appendStringRepresentationOfBitMaskToStringBuilder(sb, mNetworkCapabilities,
NetworkCapabilities::capabilityNameOf, "&");
}
- if (0 != mUnwantedNetworkCapabilities) {
- sb.append(" Unwanted: ");
- appendStringRepresentationOfBitMaskToStringBuilder(sb, mUnwantedNetworkCapabilities,
+ if (0 != mForbiddenNetworkCapabilities) {
+ sb.append(" Forbidden: ");
+ appendStringRepresentationOfBitMaskToStringBuilder(sb, mForbiddenNetworkCapabilities,
NetworkCapabilities::capabilityNameOf, "&");
}
if (mLinkUpBandwidthKbps > 0) {
diff --git a/packages/Connectivity/framework/src/android/net/NetworkProvider.java b/packages/Connectivity/framework/src/android/net/NetworkProvider.java
index 14cb51c..8f93047 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.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 @@
*/
@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 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 8c4f419..dd88c5a 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkRequest.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkRequest.java
@@ -311,7 +311,7 @@
*
* @see #addCapability(int)
*
- * @param capability The capability to add to unwanted capability list.
+ * @param capability The capability to add to forbidden capability list.
* @return The builder to facilitate chaining.
*
* @hide
@@ -319,15 +319,15 @@
@NonNull
@SuppressLint("MissingGetterMatchingBuilder")
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
- public Builder addUnwantedCapability(@NetworkCapabilities.NetCapability int capability) {
- mNetworkCapabilities.addUnwantedCapability(capability);
+ public Builder addForbiddenCapability(@NetworkCapabilities.NetCapability int capability) {
+ mNetworkCapabilities.addForbiddenCapability(capability);
return this;
}
/**
- * Removes (if found) the given unwanted capability from this builder instance.
+ * Removes (if found) the given forbidden capability from this builder instance.
*
- * @param capability The unwanted capability to remove.
+ * @param capability The forbidden capability to remove.
* @return The builder to facilitate chaining.
*
* @hide
@@ -335,8 +335,9 @@
@NonNull
@SuppressLint("BuilderSetStyle")
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
- public Builder removeUnwantedCapability(@NetworkCapabilities.NetCapability int capability) {
- mNetworkCapabilities.removeUnwantedCapability(capability);
+ public Builder removeForbiddenCapability(
+ @NetworkCapabilities.NetCapability int capability) {
+ mNetworkCapabilities.removeForbiddenCapability(capability);
return this;
}
@@ -598,13 +599,13 @@
}
/**
- * @see Builder#addUnwantedCapability(int)
+ * @see Builder#addForbiddenCapability(int)
*
* @hide
*/
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
- public boolean hasUnwantedCapability(@NetCapability int capability) {
- return networkCapabilities.hasUnwantedCapability(capability);
+ public boolean hasForbiddenCapability(@NetCapability int capability) {
+ return networkCapabilities.hasForbiddenCapability(capability);
}
/**
@@ -709,18 +710,18 @@
}
/**
- * Gets all the unwanted capabilities set on this {@code NetworkRequest} instance.
+ * Gets all the forbidden capabilities set on this {@code NetworkRequest} instance.
*
- * @return an array of unwanted capability values for this instance.
+ * @return an array of forbidden capability values for this instance.
*
* @hide
*/
@NonNull
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
- public @NetCapability int[] getUnwantedCapabilities() {
- // No need to make a defensive copy here as NC#getUnwantedCapabilities() already returns
+ public @NetCapability int[] getForbiddenCapabilities() {
+ // No need to make a defensive copy here as NC#getForbiddenCapabilities() already returns
// a new array.
- return networkCapabilities.getUnwantedCapabilities();
+ return networkCapabilities.getForbiddenCapabilities();
}
/**
diff --git a/packages/Connectivity/service/Android.bp b/packages/Connectivity/service/Android.bp
index 1330e71..513de19 100644
--- a/packages/Connectivity/service/Android.bp
+++ b/packages/Connectivity/service/Android.bp
@@ -52,8 +52,8 @@
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/services/core/java/com/android/server/ConnectivityService.java b/packages/Connectivity/service/src/com/android/server/ConnectivityService.java
similarity index 98%
rename from services/core/java/com/android/server/ConnectivityService.java
rename to packages/Connectivity/service/src/com/android/server/ConnectivityService.java
index b31adac..051a00b 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;
@@ -34,7 +33,6 @@
import static android.net.ConnectivityManager.BLOCKED_REASON_LOCKDOWN_VPN;
import static android.net.ConnectivityManager.BLOCKED_REASON_NONE;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
-import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
import static android.net.ConnectivityManager.TYPE_BLUETOOTH;
import static android.net.ConnectivityManager.TYPE_ETHERNET;
import static android.net.ConnectivityManager.TYPE_MOBILE;
@@ -54,6 +52,7 @@
import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
import static android.net.ConnectivityManager.getNetworkTypeName;
import static android.net.ConnectivityManager.isNetworkTypeValid;
+import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
@@ -125,6 +124,7 @@
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;
@@ -133,6 +133,8 @@
import android.net.IpPrefix;
import android.net.LinkProperties;
import android.net.MatchAllNetworkSpecifier;
+import android.net.NativeNetworkConfig;
+import android.net.NativeNetworkType;
import android.net.NattSocketKeepalive;
import android.net.Network;
import android.net.NetworkAgent;
@@ -232,6 +234,7 @@
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;
@@ -239,6 +242,7 @@
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;
@@ -602,6 +606,18 @@
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.
*/
@@ -1378,7 +1394,7 @@
// 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,
@@ -3804,36 +3820,43 @@
nai.onNetworkDestroyed();
}
- private boolean createNativeNetwork(@NonNull NetworkAgentInfo networkAgent) {
+ private boolean createNativeNetwork(@NonNull NetworkAgentInfo nai) {
try {
// This should never fail. Specifying an already in use NetID will cause failure.
- if (networkAgent.isVPN()) {
- mNetd.networkCreateVpn(networkAgent.network.getNetId(),
- (networkAgent.networkAgentConfig == null
- || !networkAgent.networkAgentConfig.allowBypass));
+ final NativeNetworkConfig config;
+ if (nai.isVPN()) {
+ if (getVpnType(nai) == VpnManager.TYPE_VPN_NONE) {
+ Log.wtf(TAG, "Unable to get VPN type from network " + nai.toShortString());
+ return false;
+ }
+ config = new NativeNetworkConfig(nai.network.getNetId(), NativeNetworkType.VIRTUAL,
+ INetd.PERMISSION_NONE,
+ (nai.networkAgentConfig == null || !nai.networkAgentConfig.allowBypass),
+ getVpnType(nai));
} else {
- mNetd.networkCreatePhysical(networkAgent.network.getNetId(),
- getNetworkPermission(networkAgent.networkCapabilities));
+ config = new NativeNetworkConfig(nai.network.getNetId(), NativeNetworkType.PHYSICAL,
+ getNetworkPermission(nai.networkCapabilities), /*secure=*/ false,
+ VpnManager.TYPE_VPN_NONE);
}
- mDnsResolver.createNetworkCache(networkAgent.network.getNetId());
- mDnsManager.updateTransportsForNetwork(networkAgent.network.getNetId(),
- networkAgent.networkCapabilities.getTransportTypes());
+ mNetd.networkCreate(config);
+ mDnsResolver.createNetworkCache(nai.network.getNetId());
+ mDnsManager.updateTransportsForNetwork(nai.network.getNetId(),
+ nai.networkCapabilities.getTransportTypes());
return true;
} catch (RemoteException | ServiceSpecificException e) {
- loge("Error creating network " + networkAgent.network.getNetId() + ": "
- + e.getMessage());
+ loge("Error creating network " + nai.toShortString() + ": " + e.getMessage());
return false;
}
}
- private void destroyNativeNetwork(@NonNull NetworkAgentInfo networkAgent) {
+ private void destroyNativeNetwork(@NonNull NetworkAgentInfo nai) {
try {
- mNetd.networkDestroy(networkAgent.network.getNetId());
+ mNetd.networkDestroy(nai.network.getNetId());
} catch (RemoteException | ServiceSpecificException e) {
loge("Exception destroying network(networkDestroy): " + e);
}
try {
- mDnsResolver.destroyNetworkCache(networkAgent.network.getNetId());
+ mDnsResolver.destroyNetworkCache(nai.network.getNetId());
} catch (RemoteException | ServiceSpecificException e) {
loge("Exception destroying network: " + e);
}
@@ -4675,6 +4698,18 @@
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;
@@ -6205,12 +6240,37 @@
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);
}
@@ -6249,6 +6309,10 @@
// (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<>();
@@ -6424,8 +6488,6 @@
// 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
@@ -6573,6 +6635,65 @@
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
@@ -8572,8 +8693,7 @@
// restore private DNS settings to default mode (opportunistic)
if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_PRIVATE_DNS)) {
- Settings.Global.putString(mContext.getContentResolver(),
- ConnectivitySettingsManager.PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_OPPORTUNISTIC);
+ ConnectivitySettingsManager.setPrivateDnsMode(mContext, PRIVATE_DNS_MODE_OPPORTUNISTIC);
}
Settings.Global.putString(mContext.getContentResolver(),
@@ -9033,7 +9153,8 @@
}
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);
diff --git a/services/core/java/com/android/server/ConnectivityServiceInitializer.java b/packages/Connectivity/service/src/com/android/server/ConnectivityServiceInitializer.java
similarity index 100%
rename from services/core/java/com/android/server/ConnectivityServiceInitializer.java
rename to 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
similarity index 100%
rename from services/core/java/com/android/server/NetIdManager.java
rename to 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
similarity index 100%
rename from services/core/java/com/android/server/TestNetworkService.java
rename to 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
similarity index 100%
rename from services/core/java/com/android/server/connectivity/AutodestructReference.java
rename to 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
similarity index 100%
rename from services/core/java/com/android/server/connectivity/ConnectivityConstants.java
rename to 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
similarity index 97%
rename from services/core/java/com/android/server/connectivity/DnsManager.java
rename to packages/Connectivity/service/src/com/android/server/connectivity/DnsManager.java
index cf4fe1e..05b12ba 100644
--- a/services/core/java/com/android/server/connectivity/DnsManager.java
+++ b/packages/Connectivity/service/src/com/android/server/connectivity/DnsManager.java
@@ -16,14 +16,14 @@
package com.android.server.connectivity;
-import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
-import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
import static android.net.ConnectivitySettingsManager.DNS_RESOLVER_MAX_SAMPLES;
import static android.net.ConnectivitySettingsManager.DNS_RESOLVER_MIN_SAMPLES;
import static android.net.ConnectivitySettingsManager.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS;
import static android.net.ConnectivitySettingsManager.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT;
import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_DEFAULT_MODE;
import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE;
+import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OFF;
+import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_SPECIFIER;
import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_FAILURE;
import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_SUCCESS;
@@ -33,6 +33,7 @@
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
+import android.net.ConnectivitySettingsManager;
import android.net.IDnsResolver;
import android.net.InetAddresses;
import android.net.LinkProperties;
@@ -131,11 +132,11 @@
* Get PrivateDnsConfig.
*/
public static PrivateDnsConfig getPrivateDnsConfig(Context context) {
- final String mode = ConnectivityManager.getPrivateDnsMode(context);
+ final int mode = ConnectivitySettingsManager.getPrivateDnsMode(context);
- final boolean useTls = !TextUtils.isEmpty(mode) && !PRIVATE_DNS_MODE_OFF.equals(mode);
+ final boolean useTls = mode != PRIVATE_DNS_MODE_OFF;
- if (PRIVATE_DNS_MODE_PROVIDER_HOSTNAME.equals(mode)) {
+ if (PRIVATE_DNS_MODE_PROVIDER_HOSTNAME == mode) {
final String specifier = getStringSetting(context.getContentResolver(),
PRIVATE_DNS_SPECIFIER);
return new PrivateDnsConfig(specifier, null);
diff --git a/services/core/java/com/android/server/connectivity/FullScore.java b/packages/Connectivity/service/src/com/android/server/connectivity/FullScore.java
similarity index 83%
rename from services/core/java/com/android/server/connectivity/FullScore.java
rename to packages/Connectivity/service/src/com/android/server/connectivity/FullScore.java
index 028cfee..9326d69 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 @@
}
/**
+ * 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
similarity index 100%
rename from services/core/java/com/android/server/connectivity/KeepaliveTracker.java
rename to 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
similarity index 100%
rename from services/core/java/com/android/server/connectivity/LingerMonitor.java
rename to 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
similarity index 100%
rename from services/core/java/com/android/server/connectivity/MockableSystemProperties.java
rename to 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
similarity index 100%
rename from services/core/java/com/android/server/connectivity/Nat464Xlat.java
rename to 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
similarity index 100%
rename from services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
rename to 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
similarity index 100%
rename from services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
rename to 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
similarity index 100%
rename from services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
rename to 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 0000000..fa2d465
--- /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
similarity index 100%
rename from services/core/java/com/android/server/connectivity/NetworkRanker.java
rename to 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
similarity index 99%
rename from services/core/java/com/android/server/connectivity/PermissionMonitor.java
rename to packages/Connectivity/service/src/com/android/server/connectivity/PermissionMonitor.java
index 7837e6e..506cadb 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/packages/Connectivity/service/src/com/android/server/connectivity/PermissionMonitor.java
@@ -338,7 +338,8 @@
return currentPermission;
}
try {
- final PackageInfo app = mPackageManager.getPackageInfo(name, GET_PERMISSIONS);
+ final PackageInfo app = mPackageManager.getPackageInfo(name,
+ GET_PERMISSIONS | MATCH_ANY_USER);
final boolean isNetwork = hasNetworkPermission(app);
final boolean hasRestrictedPermission = hasRestrictedNetworkPermission(app);
if (isNetwork || hasRestrictedPermission) {
@@ -664,6 +665,7 @@
break;
case INetd.PERMISSION_UNINSTALLED:
uninstalledAppIds.add(netdPermissionsAppIds.keyAt(i));
+ break;
default:
Log.e(TAG, "unknown permission type: " + permissions + "for uid: "
+ netdPermissionsAppIds.keyAt(i));
diff --git a/services/core/java/com/android/server/connectivity/ProfileNetworkPreferences.java b/packages/Connectivity/service/src/com/android/server/connectivity/ProfileNetworkPreferences.java
similarity index 100%
rename from services/core/java/com/android/server/connectivity/ProfileNetworkPreferences.java
rename to 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
similarity index 100%
rename from services/core/java/com/android/server/connectivity/ProxyTracker.java
rename to 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
similarity index 100%
rename from services/core/java/com/android/server/connectivity/QosCallbackAgentConnection.java
rename to 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
similarity index 100%
rename from services/core/java/com/android/server/connectivity/QosCallbackTracker.java
rename to 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
similarity index 100%
rename from services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
rename to packages/Connectivity/service/src/com/android/server/connectivity/TcpKeepaliveController.java
diff --git a/tests/net/OWNERS b/packages/Connectivity/tests/OWNERS
similarity index 100%
rename from tests/net/OWNERS
rename to packages/Connectivity/tests/OWNERS
diff --git a/tests/net/TEST_MAPPING b/packages/Connectivity/tests/TEST_MAPPING
similarity index 100%
rename from tests/net/TEST_MAPPING
rename to packages/Connectivity/tests/TEST_MAPPING
diff --git a/tests/net/common/Android.bp b/packages/Connectivity/tests/common/Android.bp
similarity index 100%
rename from tests/net/common/Android.bp
rename to packages/Connectivity/tests/common/Android.bp
diff --git a/tests/net/common/java/ParseExceptionTest.kt b/packages/Connectivity/tests/common/java/ParseExceptionTest.kt
similarity index 100%
rename from tests/net/common/java/ParseExceptionTest.kt
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/CaptivePortalDataTest.kt
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/CaptivePortalTest.java
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/DependenciesTest.java
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/DhcpInfoTest.java
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/IpPrefixTest.java
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/KeepalivePacketDataTest.kt
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/LinkAddressTest.java
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/LinkPropertiesTest.java
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/MatchAllNetworkSpecifierTest.kt
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/NattKeepalivePacketDataTest.kt
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/NetworkAgentConfigTest.kt
rename to 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
similarity index 92%
rename from tests/net/common/java/android/net/NetworkCapabilitiesTest.java
rename to packages/Connectivity/tests/common/java/android/net/NetworkCapabilitiesTest.java
index 33f2c67..d74b802 100644
--- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
+++ b/packages/Connectivity/tests/common/java/android/net/NetworkCapabilitiesTest.java
@@ -340,7 +340,7 @@
private void testParcelSane(NetworkCapabilities cap) {
if (isAtLeastS()) {
- assertParcelSane(cap, 17);
+ assertParcelSane(cap, 16);
} else if (isAtLeastR()) {
assertParcelSane(cap, 15);
} else {
@@ -390,9 +390,11 @@
@Test
public void testOemPaid() {
NetworkCapabilities nc = new NetworkCapabilities();
- // By default OEM_PAID is neither in the unwanted or required lists and the network is not
+ // By default OEM_PAID is neither in the required or forbidden lists and the network is not
// restricted.
- assertFalse(nc.hasUnwantedCapability(NET_CAPABILITY_OEM_PAID));
+ if (isAtLeastS()) {
+ assertFalse(nc.hasForbiddenCapability(NET_CAPABILITY_OEM_PAID));
+ }
assertFalse(nc.hasCapability(NET_CAPABILITY_OEM_PAID));
nc.maybeMarkCapabilitiesRestricted();
assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
@@ -417,9 +419,9 @@
@Test @IgnoreUpTo(Build.VERSION_CODES.R)
public void testOemPrivate() {
NetworkCapabilities nc = new NetworkCapabilities();
- // By default OEM_PRIVATE is neither in the unwanted or required lists and the network is
+ // By default OEM_PRIVATE is neither in the required or forbidden lists and the network is
// not restricted.
- assertFalse(nc.hasUnwantedCapability(NET_CAPABILITY_OEM_PRIVATE));
+ assertFalse(nc.hasForbiddenCapability(NET_CAPABILITY_OEM_PRIVATE));
assertFalse(nc.hasCapability(NET_CAPABILITY_OEM_PRIVATE));
nc.maybeMarkCapabilitiesRestricted();
assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
@@ -441,8 +443,8 @@
assertFalse(nr.satisfiedByNetworkCapabilities(new NetworkCapabilities()));
}
- @Test
- public void testUnwantedCapabilities() {
+ @Test @IgnoreUpTo(Build.VERSION_CODES.R)
+ public void testForbiddenCapabilities() {
NetworkCapabilities network = new NetworkCapabilities();
NetworkCapabilities request = new NetworkCapabilities();
@@ -450,19 +452,19 @@
request.satisfiedByNetworkCapabilities(network));
// Requesting absence of capabilities that network doesn't have. Request should satisfy.
- request.addUnwantedCapability(NET_CAPABILITY_WIFI_P2P);
- request.addUnwantedCapability(NET_CAPABILITY_NOT_METERED);
+ request.addForbiddenCapability(NET_CAPABILITY_WIFI_P2P);
+ request.addForbiddenCapability(NET_CAPABILITY_NOT_METERED);
assertTrue(request.satisfiedByNetworkCapabilities(network));
- assertArrayEquals(new int[] {NET_CAPABILITY_WIFI_P2P,
+ assertArrayEquals(new int[]{NET_CAPABILITY_WIFI_P2P,
NET_CAPABILITY_NOT_METERED},
- request.getUnwantedCapabilities());
+ request.getForbiddenCapabilities());
// This is a default capability, just want to make sure its there because we use it below.
assertTrue(network.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
- // Verify that adding unwanted capability will effectively remove it from capability list.
- request.addUnwantedCapability(NET_CAPABILITY_NOT_RESTRICTED);
- assertTrue(request.hasUnwantedCapability(NET_CAPABILITY_NOT_RESTRICTED));
+ // Verify that adding forbidden capability will effectively remove it from capability list.
+ request.addForbiddenCapability(NET_CAPABILITY_NOT_RESTRICTED);
+ assertTrue(request.hasForbiddenCapability(NET_CAPABILITY_NOT_RESTRICTED));
assertFalse(request.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
// Now this request won't be satisfied because network contains NOT_RESTRICTED.
@@ -470,10 +472,10 @@
network.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
assertTrue(request.satisfiedByNetworkCapabilities(network));
- // Verify that adding capability will effectively remove it from unwanted list
+ // Verify that adding capability will effectively remove it from forbidden list
request.addCapability(NET_CAPABILITY_NOT_RESTRICTED);
assertTrue(request.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
- assertFalse(request.hasUnwantedCapability(NET_CAPABILITY_NOT_RESTRICTED));
+ assertFalse(request.hasForbiddenCapability(NET_CAPABILITY_NOT_RESTRICTED));
assertFalse(request.satisfiedByNetworkCapabilities(network));
network.addCapability(NET_CAPABILITY_NOT_RESTRICTED);
@@ -512,24 +514,20 @@
assertTrue(nc1.equalsNetCapabilities(nc2));
assertEquals(nc1, nc2);
- nc1.addUnwantedCapability(NET_CAPABILITY_INTERNET);
- assertFalse(nc1.equalsNetCapabilities(nc2));
- nc2.addUnwantedCapability(NET_CAPABILITY_INTERNET);
- assertTrue(nc1.equalsNetCapabilities(nc2));
if (isAtLeastS()) {
- // Remove a required capability doesn't affect unwanted capabilities.
- // This is a behaviour change from S.
+ nc1.addForbiddenCapability(NET_CAPABILITY_INTERNET);
+ assertFalse(nc1.equalsNetCapabilities(nc2));
+ nc2.addForbiddenCapability(NET_CAPABILITY_INTERNET);
+ assertTrue(nc1.equalsNetCapabilities(nc2));
+
+ // Remove a required capability doesn't affect forbidden capabilities.
+ // This is a behaviour change from R to S.
nc1.removeCapability(NET_CAPABILITY_INTERNET);
assertTrue(nc1.equalsNetCapabilities(nc2));
- nc1.removeUnwantedCapability(NET_CAPABILITY_INTERNET);
+ nc1.removeForbiddenCapability(NET_CAPABILITY_INTERNET);
assertFalse(nc1.equalsNetCapabilities(nc2));
- nc2.removeUnwantedCapability(NET_CAPABILITY_INTERNET);
- assertTrue(nc1.equalsNetCapabilities(nc2));
- } else {
- nc1.removeCapability(NET_CAPABILITY_INTERNET);
- assertFalse(nc1.equalsNetCapabilities(nc2));
- nc2.removeCapability(NET_CAPABILITY_INTERNET);
+ nc2.removeForbiddenCapability(NET_CAPABILITY_INTERNET);
assertTrue(nc1.equalsNetCapabilities(nc2));
}
}
@@ -581,31 +579,25 @@
NetworkCapabilities nc1 = new NetworkCapabilities();
NetworkCapabilities nc2 = new NetworkCapabilities();
- nc1.addUnwantedCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
+ if (isAtLeastS()) {
+ nc1.addForbiddenCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
+ }
nc1.addCapability(NET_CAPABILITY_NOT_ROAMING);
assertNotEquals(nc1, nc2);
nc2.combineCapabilities(nc1);
assertEquals(nc1, nc2);
assertTrue(nc2.hasCapability(NET_CAPABILITY_NOT_ROAMING));
- assertTrue(nc2.hasUnwantedCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
-
- // This will effectively move NOT_ROAMING capability from required to unwanted for nc1.
- nc1.addUnwantedCapability(NET_CAPABILITY_NOT_ROAMING);
+ if (isAtLeastS()) {
+ assertTrue(nc2.hasForbiddenCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
+ }
if (isAtLeastS()) {
- // From S, it is not allowed to have the same capability in both wanted and
- // unwanted list.
+ // This will effectively move NOT_ROAMING capability from required to forbidden for nc1.
+ nc1.addForbiddenCapability(NET_CAPABILITY_NOT_ROAMING);
+ // It is not allowed to have the same capability in both wanted and forbidden list.
assertThrows(IllegalArgumentException.class, () -> nc2.combineCapabilities(nc1));
- // Remove unwanted capability to continue other tests.
- nc1.removeUnwantedCapability(NET_CAPABILITY_NOT_ROAMING);
- } else {
- nc2.combineCapabilities(nc1);
- // We will get this capability in both requested and unwanted lists thus this request
- // will never be satisfied.
- assertTrue(nc2.hasCapability(NET_CAPABILITY_NOT_ROAMING));
- assertTrue(nc2.hasUnwantedCapability(NET_CAPABILITY_NOT_ROAMING));
- // For R or below, remove unwanted capability via removeCapability.
- nc1.removeCapability(NET_CAPABILITY_NOT_ROAMING);
+ // Remove forbidden capability to continue other tests.
+ nc1.removeForbiddenCapability(NET_CAPABILITY_NOT_ROAMING);
}
nc1.setSSID(TEST_SSID);
@@ -683,14 +675,11 @@
public void testSetCapabilities() {
final int[] REQUIRED_CAPABILITIES = new int[] {
NET_CAPABILITY_INTERNET, NET_CAPABILITY_NOT_VPN };
- final int[] UNWANTED_CAPABILITIES = new int[] {
- NET_CAPABILITY_NOT_RESTRICTED, NET_CAPABILITY_NOT_METERED
- };
NetworkCapabilities nc1 = new NetworkCapabilities();
NetworkCapabilities nc2 = new NetworkCapabilities();
- nc1.setCapabilities(REQUIRED_CAPABILITIES, UNWANTED_CAPABILITIES);
+ nc1.setCapabilities(REQUIRED_CAPABILITIES);
assertArrayEquals(REQUIRED_CAPABILITIES, nc1.getCapabilities());
// Verify that setting and adding capabilities leads to the same object state.
@@ -698,10 +687,25 @@
for (int cap : REQUIRED_CAPABILITIES) {
nc2.addCapability(cap);
}
- for (int cap : UNWANTED_CAPABILITIES) {
- nc2.addUnwantedCapability(cap);
- }
assertEquals(nc1, nc2);
+
+ if (isAtLeastS()) {
+ final int[] forbiddenCapabilities = new int[]{
+ NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_NOT_RESTRICTED };
+
+ nc1.setCapabilities(REQUIRED_CAPABILITIES, forbiddenCapabilities);
+ assertArrayEquals(REQUIRED_CAPABILITIES, nc1.getCapabilities());
+ assertArrayEquals(forbiddenCapabilities, nc1.getForbiddenCapabilities());
+
+ nc2.clearAll();
+ for (int cap : REQUIRED_CAPABILITIES) {
+ nc2.addCapability(cap);
+ }
+ for (int cap : forbiddenCapabilities) {
+ nc2.addForbiddenCapability(cap);
+ }
+ assertEquals(nc1, nc2);
+ }
}
@Test
@@ -769,23 +773,32 @@
NetworkCapabilities nc1 = new NetworkCapabilities();
NetworkCapabilities nc2 = new NetworkCapabilities();
- nc1.addUnwantedCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
+ if (isAtLeastS()) {
+ nc1.addForbiddenCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
+ }
nc1.addCapability(NET_CAPABILITY_NOT_ROAMING);
assertNotEquals(nc1, nc2);
nc2.set(nc1);
assertEquals(nc1, nc2);
assertTrue(nc2.hasCapability(NET_CAPABILITY_NOT_ROAMING));
- assertTrue(nc2.hasUnwantedCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
+ if (isAtLeastS()) {
+ assertTrue(nc2.hasForbiddenCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
+ }
- // This will effectively move NOT_ROAMING capability from required to unwanted for nc1.
- nc1.addUnwantedCapability(NET_CAPABILITY_NOT_ROAMING);
+ if (isAtLeastS()) {
+ // This will effectively move NOT_ROAMING capability from required to forbidden for nc1.
+ nc1.addForbiddenCapability(NET_CAPABILITY_NOT_ROAMING);
+ }
nc1.setSSID(TEST_SSID);
nc2.set(nc1);
assertEquals(nc1, nc2);
- // Contrary to combineCapabilities, set() will have removed the NOT_ROAMING capability
- // from nc2.
- assertFalse(nc2.hasCapability(NET_CAPABILITY_NOT_ROAMING));
- assertTrue(nc2.hasUnwantedCapability(NET_CAPABILITY_NOT_ROAMING));
+ if (isAtLeastS()) {
+ // Contrary to combineCapabilities, set() will have removed the NOT_ROAMING capability
+ // from nc2.
+ assertFalse(nc2.hasCapability(NET_CAPABILITY_NOT_ROAMING));
+ assertTrue(nc2.hasForbiddenCapability(NET_CAPABILITY_NOT_ROAMING));
+ }
+
if (isAtLeastR()) {
assertTrue(TEST_SSID.equals(nc2.getSsid()));
}
diff --git a/tests/net/common/java/android/net/NetworkProviderTest.kt b/packages/Connectivity/tests/common/java/android/net/NetworkProviderTest.kt
similarity index 100%
rename from tests/net/common/java/android/net/NetworkProviderTest.kt
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/NetworkSpecifierTest.kt
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/NetworkStackTest.java
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/NetworkStateSnapshotTest.kt
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/NetworkTest.java
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/OemNetworkPreferencesTest.java
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/RouteInfoTest.java
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/StaticIpConfigurationTest.java
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/TcpKeepalivePacketDataTest.kt
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/UidRangeTest.java
rename to 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
similarity index 80%
rename from tests/net/common/java/android/net/UnderlyingNetworkInfoTest.kt
rename to packages/Connectivity/tests/common/java/android/net/UnderlyingNetworkInfoTest.kt
index 87cfb34..f23ba26 100644
--- a/tests/net/common/java/android/net/UnderlyingNetworkInfoTest.kt
+++ b/packages/Connectivity/tests/common/java/android/net/UnderlyingNetworkInfoTest.kt
@@ -36,15 +36,15 @@
@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
similarity index 100%
rename from tests/net/common/java/android/net/apf/ApfCapabilitiesTest.java
rename to packages/Connectivity/tests/common/java/android/net/apf/ApfCapabilitiesTest.java
diff --git a/tests/net/common/java/android/net/metrics/ApfProgramEventTest.kt b/packages/Connectivity/tests/common/java/android/net/metrics/ApfProgramEventTest.kt
similarity index 100%
rename from tests/net/common/java/android/net/metrics/ApfProgramEventTest.kt
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/metrics/ApfStatsTest.kt
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/metrics/DhcpClientEventTest.kt
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/metrics/DhcpErrorEventTest.kt
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/metrics/IpConnectivityLogTest.java
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/metrics/IpManagerEventTest.kt
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/metrics/IpReachabilityEventTest.kt
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/metrics/NetworkEventTest.kt
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/metrics/RaEventTest.kt
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/metrics/ValidationProbeEventTest.kt
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/netstats/NetworkStatsApiTest.kt
rename to 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
similarity index 100%
rename from tests/net/common/java/android/net/util/SocketUtilsTest.kt
rename to 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
similarity index 100%
rename from tests/net/deflake/Android.bp
rename to 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
similarity index 100%
rename from tests/net/deflake/src/com/android/server/net/FrameworksNetDeflakeTest.kt
rename to 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
similarity index 100%
rename from tests/net/integration/Android.bp
rename to packages/Connectivity/tests/integration/Android.bp
diff --git a/tests/net/integration/AndroidManifest.xml b/packages/Connectivity/tests/integration/AndroidManifest.xml
similarity index 100%
rename from tests/net/integration/AndroidManifest.xml
rename to 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
similarity index 100%
rename from tests/net/integration/res/values/config.xml
rename to 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
similarity index 100%
rename from tests/net/integration/src/android/net/TestNetworkStackClient.kt
rename to 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
similarity index 100%
rename from tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
rename to 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
similarity index 100%
rename from tests/net/integration/src/com/android/server/net/integrationtests/HttpResponse.aidl
rename to 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
similarity index 100%
rename from tests/net/integration/src/com/android/server/net/integrationtests/HttpResponse.kt
rename to 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
similarity index 100%
rename from tests/net/integration/src/com/android/server/net/integrationtests/INetworkStackInstrumentation.aidl
rename to 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
similarity index 100%
rename from tests/net/integration/src/com/android/server/net/integrationtests/NetworkStackInstrumentationService.kt
rename to 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
similarity index 97%
rename from tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt
rename to packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt
index a44ad1e..eff6658 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
@@ -61,7 +61,6 @@
private class NetworkMonitorDeps(private val privateDnsBypassNetwork: Network) :
NetworkMonitor.Dependencies() {
override fun getPrivateDnsBypassNetwork(network: Network?) = privateDnsBypassNetwork
- override fun sendNetworkConditionsBroadcast(context: Context, broadcast: Intent) = Unit
}
private inner class TestNetworkStackConnector(context: Context) : NetworkStackConnector(
@@ -98,4 +97,4 @@
cb.onNetworkMonitorCreated(NetworkMonitorConnector(nm, TestPermissionChecker()))
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/net/integration/util/com/android/server/ConnectivityServiceTestUtils.kt b/packages/Connectivity/tests/integration/util/com/android/server/ConnectivityServiceTestUtils.kt
similarity index 100%
rename from tests/net/integration/util/com/android/server/ConnectivityServiceTestUtils.kt
rename to 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
similarity index 98%
rename from tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
rename to packages/Connectivity/tests/integration/util/com/android/server/NetworkAgentWrapper.java
index e2d43cb..e809550 100644
--- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
+++ b/packages/Connectivity/tests/integration/util/com/android/server/NetworkAgentWrapper.java
@@ -370,4 +370,8 @@
}
}
}
+
+ public boolean isBypassableVpn() {
+ return mNetworkAgentConfig.isBypassableVpn();
+ }
}
diff --git a/tests/net/integration/util/com/android/server/TestNetIdManager.kt b/packages/Connectivity/tests/integration/util/com/android/server/TestNetIdManager.kt
similarity index 100%
rename from tests/net/integration/util/com/android/server/TestNetIdManager.kt
rename to 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
similarity index 100%
rename from tests/net/smoketest/Android.bp
rename to packages/Connectivity/tests/smoketest/Android.bp
diff --git a/tests/net/smoketest/AndroidManifest.xml b/packages/Connectivity/tests/smoketest/AndroidManifest.xml
similarity index 100%
rename from tests/net/smoketest/AndroidManifest.xml
rename to packages/Connectivity/tests/smoketest/AndroidManifest.xml
diff --git a/tests/net/smoketest/AndroidTest.xml b/packages/Connectivity/tests/smoketest/AndroidTest.xml
similarity index 100%
rename from tests/net/smoketest/AndroidTest.xml
rename to packages/Connectivity/tests/smoketest/AndroidTest.xml
diff --git a/tests/net/smoketest/java/SmokeTest.java b/packages/Connectivity/tests/smoketest/java/SmokeTest.java
similarity index 100%
rename from tests/net/smoketest/java/SmokeTest.java
rename to packages/Connectivity/tests/smoketest/java/SmokeTest.java
diff --git a/tests/net/Android.bp b/packages/Connectivity/tests/unit/Android.bp
similarity index 100%
rename from tests/net/Android.bp
rename to packages/Connectivity/tests/unit/Android.bp
diff --git a/tests/net/AndroidManifest.xml b/packages/Connectivity/tests/unit/AndroidManifest.xml
similarity index 100%
rename from tests/net/AndroidManifest.xml
rename to packages/Connectivity/tests/unit/AndroidManifest.xml
diff --git a/tests/net/AndroidTest.xml b/packages/Connectivity/tests/unit/AndroidTest.xml
similarity index 100%
rename from tests/net/AndroidTest.xml
rename to packages/Connectivity/tests/unit/AndroidTest.xml
diff --git a/tests/net/jarjar-rules.txt b/packages/Connectivity/tests/unit/jarjar-rules.txt
similarity index 100%
rename from tests/net/jarjar-rules.txt
rename to 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
similarity index 100%
rename from tests/net/java/android/app/usage/NetworkStatsManagerTest.java
rename to 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
similarity index 100%
rename from tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java
rename to 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
similarity index 100%
rename from tests/net/java/android/net/ConnectivityManagerTest.java
rename to 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
similarity index 100%
rename from tests/net/java/android/net/Ikev2VpnProfileTest.java
rename to 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
similarity index 100%
rename from tests/net/java/android/net/IpMemoryStoreTest.java
rename to 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
similarity index 100%
rename from tests/net/java/android/net/IpSecAlgorithmTest.java
rename to 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
similarity index 100%
rename from tests/net/java/android/net/IpSecConfigTest.java
rename to 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
similarity index 100%
rename from tests/net/java/android/net/IpSecManagerTest.java
rename to 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
similarity index 100%
rename from tests/net/java/android/net/IpSecTransformTest.java
rename to 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
similarity index 100%
rename from tests/net/java/android/net/KeepalivePacketDataUtilTest.java
rename to 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
similarity index 100%
rename from tests/net/java/android/net/MacAddressTest.java
rename to 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
similarity index 100%
rename from tests/net/java/android/net/NetworkIdentityTest.kt
rename to 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
similarity index 100%
rename from tests/net/java/android/net/NetworkStatsHistoryTest.java
rename to 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
similarity index 100%
rename from tests/net/java/android/net/NetworkStatsTest.java
rename to 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
similarity index 100%
rename from tests/net/java/android/net/NetworkTemplateTest.kt
rename to packages/Connectivity/tests/unit/java/android/net/NetworkTemplateTest.kt
diff --git a/tests/net/java/android/net/NetworkUtilsTest.java b/packages/Connectivity/tests/unit/java/android/net/NetworkUtilsTest.java
similarity index 100%
rename from tests/net/java/android/net/NetworkUtilsTest.java
rename to 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
similarity index 100%
rename from tests/net/java/android/net/QosSocketFilterTest.java
rename to packages/Connectivity/tests/unit/java/android/net/QosSocketFilterTest.java
diff --git a/tests/net/java/android/net/TelephonyNetworkSpecifierTest.java b/packages/Connectivity/tests/unit/java/android/net/TelephonyNetworkSpecifierTest.java
similarity index 100%
rename from tests/net/java/android/net/TelephonyNetworkSpecifierTest.java
rename to 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
similarity index 85%
rename from tests/net/java/android/net/VpnManagerTest.java
rename to packages/Connectivity/tests/unit/java/android/net/VpnManagerTest.java
index c548e30..3135062 100644
--- a/tests/net/java/android/net/VpnManagerTest.java
+++ b/packages/Connectivity/tests/unit/java/android/net/VpnManagerTest.java
@@ -28,11 +28,13 @@
import android.content.ComponentName;
import android.content.Intent;
import android.test.mock.MockContext;
+import android.util.SparseArray;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.net.VpnProfile;
+import com.android.internal.util.MessageUtils;
import org.junit.Before;
import org.junit.Test;
@@ -119,4 +121,18 @@
.setAuthPsk(PSK_BYTES)
.build();
}
+
+ @Test
+ public void testVpnTypesEqual() throws Exception {
+ SparseArray<String> vmVpnTypes = MessageUtils.findMessageNames(
+ new Class[] { VpnManager.class }, new String[]{ "TYPE_VPN_" });
+ SparseArray<String> nativeVpnType = MessageUtils.findMessageNames(
+ new Class[] { NativeVpnType.class }, new String[]{ "" });
+
+ // TYPE_VPN_NONE = -1 is only defined in VpnManager.
+ assertEquals(vmVpnTypes.size() - 1, nativeVpnType.size());
+ for (int i = VpnManager.TYPE_VPN_SERVICE; i < vmVpnTypes.size(); i++) {
+ assertEquals(vmVpnTypes.get(i), "TYPE_VPN_" + nativeVpnType.get(i));
+ }
+ }
}
diff --git a/tests/net/java/android/net/VpnTransportInfoTest.java b/packages/Connectivity/tests/unit/java/android/net/VpnTransportInfoTest.java
similarity index 100%
rename from tests/net/java/android/net/VpnTransportInfoTest.java
rename to 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
similarity index 100%
rename from tests/net/java/android/net/ipmemorystore/ParcelableTests.java
rename to 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
similarity index 100%
rename from tests/net/java/android/net/nsd/NsdManagerTest.java
rename to 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
similarity index 100%
rename from tests/net/java/android/net/nsd/NsdServiceInfoTest.java
rename to 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
similarity index 100%
rename from tests/net/java/android/net/util/DnsUtilsTest.java
rename to 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
similarity index 100%
rename from tests/net/java/android/net/util/KeepaliveUtilsTest.kt
rename to 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
similarity index 100%
rename from tests/net/java/android/net/util/MultinetworkPolicyTrackerTest.kt
rename to 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
similarity index 100%
rename from tests/net/java/com/android/internal/net/NetworkUtilsInternalTest.java
rename to 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
similarity index 100%
rename from tests/net/java/com/android/internal/net/VpnProfileTest.java
rename to 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
similarity index 100%
rename from tests/net/java/com/android/internal/util/BitUtilsTest.java
rename to 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
similarity index 100%
rename from tests/net/java/com/android/internal/util/RingBufferTest.java
rename to 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
similarity index 97%
rename from tests/net/java/com/android/server/ConnectivityServiceTest.java
rename to packages/Connectivity/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index bc06a6e..41458f1 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 @@
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;
@@ -44,9 +45,6 @@
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.EXTRA_NETWORK_INFO;
import static android.net.ConnectivityManager.EXTRA_NETWORK_TYPE;
-import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
-import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
-import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT;
import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE;
import static android.net.ConnectivityManager.TYPE_ETHERNET;
@@ -57,6 +55,9 @@
import static android.net.ConnectivityManager.TYPE_PROXY;
import static android.net.ConnectivityManager.TYPE_VPN;
import static android.net.ConnectivityManager.TYPE_WIFI;
+import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OFF;
+import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
+import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTP;
@@ -126,6 +127,7 @@
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;
@@ -211,6 +213,8 @@
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.MatchAllNetworkSpecifier;
+import android.net.NativeNetworkConfig;
+import android.net.NativeNetworkType;
import android.net.Network;
import android.net.NetworkAgent;
import android.net.NetworkAgentConfig;
@@ -1253,6 +1257,8 @@
verify(mMockNetd, never())
.networkRemoveUidRanges(eq(mMockVpn.getNetwork().getNetId()), any());
mAgentRegistered = true;
+ verify(mMockNetd).networkCreate(nativeNetworkConfigVpn(getNetwork().netId,
+ !mMockNetworkAgent.isBypassableVpn(), mVpnType));
updateState(NetworkInfo.DetailedState.CONNECTED, "registerAgent");
mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
mNetworkAgent = mMockNetworkAgent.getNetworkAgent();
@@ -2809,8 +2815,9 @@
private void grantUsingBackgroundNetworksPermissionForUid(
final int uid, final String packageName) throws Exception {
- when(mPackageManager.getPackageInfo(eq(packageName), eq(GET_PERMISSIONS)))
- .thenReturn(buildPackageInfo(true, uid));
+ when(mPackageManager.getPackageInfo(
+ eq(packageName), eq(GET_PERMISSIONS | MATCH_ANY_USER)))
+ .thenReturn(buildPackageInfo(true /* hasSystemPermission */, uid));
mService.mPermissionMonitor.onPackageAdded(packageName, uid);
}
@@ -2860,6 +2867,16 @@
mCm.unregisterNetworkCallback(callback);
}
+ private NativeNetworkConfig nativeNetworkConfigPhysical(int netId, int permission) {
+ return new NativeNetworkConfig(netId, NativeNetworkType.PHYSICAL, permission,
+ /*secure=*/ false, VpnManager.TYPE_VPN_NONE);
+ }
+
+ private NativeNetworkConfig nativeNetworkConfigVpn(int netId, boolean secure, int vpnType) {
+ return new NativeNetworkConfig(netId, NativeNetworkType.VIRTUAL, INetd.PERMISSION_NONE,
+ secure, vpnType);
+ }
+
@Test
public void testNetworkAgentCallbacks() throws Exception {
// Keeps track of the order of events that happen in this test.
@@ -2881,8 +2898,8 @@
wifiNetwork.set(mWiFiNetworkAgent.getNetwork());
assertNotNull(wifiNetwork.get());
try {
- verify(mMockNetd).networkCreatePhysical(wifiNetwork.get().getNetId(),
- INetd.PERMISSION_NONE);
+ verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
+ wifiNetwork.get().getNetId(), INetd.PERMISSION_NONE));
} catch (RemoteException impossible) {
fail();
}
@@ -4242,10 +4259,9 @@
waitForIdle();
}
- private void setPrivateDnsSettings(String mode, String specifier) {
- final ContentResolver cr = mServiceContext.getContentResolver();
- Settings.Global.putString(cr, ConnectivitySettingsManager.PRIVATE_DNS_MODE, mode);
- Settings.Global.putString(cr, ConnectivitySettingsManager.PRIVATE_DNS_SPECIFIER, specifier);
+ private void setPrivateDnsSettings(int mode, String specifier) {
+ ConnectivitySettingsManager.setPrivateDnsMode(mServiceContext, mode);
+ ConnectivitySettingsManager.setPrivateDnsHostname(mServiceContext, specifier);
mService.updatePrivateDnsSettings();
waitForIdle();
}
@@ -5791,20 +5807,8 @@
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);
@@ -5812,26 +5816,24 @@
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
@@ -5839,8 +5841,8 @@
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);
@@ -5851,7 +5853,7 @@
mCellNetworkAgent.connect(false);
mCellNetworkAgent.sendLinkProperties(cellLp);
waitForIdle();
- expectNetworkStatus(onlyCell, MOBILE_IFNAME);
+ expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME);
reset(mStatsManager);
// Default network switch should update ifaces.
@@ -5859,37 +5861,37 @@
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.
@@ -5899,29 +5901,29 @@
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
@@ -5930,23 +5932,23 @@
// 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.
@@ -5959,15 +5961,15 @@
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);
@@ -5980,8 +5982,8 @@
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);
@@ -5994,26 +5996,26 @@
// 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);
}
@@ -8327,7 +8329,8 @@
final int cellNetId = mCellNetworkAgent.getNetwork().netId;
waitForIdle();
- verify(mMockNetd, times(1)).networkCreatePhysical(eq(cellNetId), anyInt());
+ verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(cellNetId,
+ INetd.PERMISSION_NONE));
assertRoutesAdded(cellNetId, ipv6Subnet, defaultRoute);
verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId));
verify(mMockNetd, times(1)).networkAddInterface(cellNetId, MOBILE_IFNAME);
@@ -9392,9 +9395,9 @@
@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
);
}
@@ -9417,8 +9420,26 @@
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,
@@ -9447,7 +9468,6 @@
wifiNetworkCallback.expectCapabilitiesThat(mWiFiNetworkAgent,
nc -> Objects.equals(expectedOwnerUid, nc.getOwnerUid())
&& Objects.equals(expectedTransportInfo, nc.getTransportInfo()));
-
}
@Test
@@ -9468,6 +9488,40 @@
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);
@@ -9825,12 +9879,27 @@
// 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 {
@@ -9841,12 +9910,7 @@
// 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
@@ -9862,12 +9926,7 @@
// 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
@@ -11982,8 +12041,9 @@
mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
- inOrder.verify(mMockNetd).networkCreatePhysical(mCellNetworkAgent.getNetwork().netId,
- INetd.PERMISSION_NONE);
+ inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
+ mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE));
+
final TestOnCompleteListener listener = new TestOnCompleteListener();
mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
@@ -12010,8 +12070,8 @@
mProfileDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(workAgent);
mSystemDefaultNetworkCallback.assertNoCallback();
mDefaultNetworkCallback.assertNoCallback();
- inOrder.verify(mMockNetd).networkCreatePhysical(workAgent.getNetwork().netId,
- INetd.PERMISSION_SYSTEM);
+ inOrder.verify(mMockNetd).networkCreate(
+ nativeNetworkConfigPhysical(workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM));
inOrder.verify(mMockNetd).networkAddUidRanges(workAgent.getNetwork().netId,
uidRangeFor(testHandle));
inOrder.verify(mMockNetd).networkRemoveUidRanges(mCellNetworkAgent.getNetwork().netId,
@@ -12054,8 +12114,8 @@
mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
mProfileDefaultNetworkCallback.assertNoCallback();
- inOrder.verify(mMockNetd).networkCreatePhysical(mCellNetworkAgent.getNetwork().netId,
- INetd.PERMISSION_NONE);
+ inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
+ mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE));
// When the agent disconnects, test that the app on the work profile falls back to the
// default network.
@@ -12085,8 +12145,8 @@
mProfileDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(workAgent2);
assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
- inOrder.verify(mMockNetd).networkCreatePhysical(workAgent2.getNetwork().netId,
- INetd.PERMISSION_SYSTEM);
+ inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
+ workAgent2.getNetwork().netId, INetd.PERMISSION_SYSTEM));
inOrder.verify(mMockNetd).networkAddUidRanges(workAgent2.getNetwork().netId,
uidRangeFor(testHandle));
@@ -12131,8 +12191,8 @@
mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
r -> r.run(), listener);
listener.expectOnComplete();
- inOrder.verify(mMockNetd).networkCreatePhysical(mCellNetworkAgent.getNetwork().netId,
- INetd.PERMISSION_NONE);
+ inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
+ mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE));
inOrder.verify(mMockNetd).networkAddUidRanges(workAgent.getNetwork().netId,
uidRangeFor(testHandle));
@@ -12184,10 +12244,10 @@
mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
app4Cb.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
- inOrder.verify(mMockNetd).networkCreatePhysical(mCellNetworkAgent.getNetwork().netId,
- INetd.PERMISSION_NONE);
- inOrder.verify(mMockNetd).networkCreatePhysical(workAgent.getNetwork().netId,
- INetd.PERMISSION_SYSTEM);
+ inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
+ mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE));
+ inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
+ workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM));
final TestOnCompleteListener listener = new TestOnCompleteListener();
mCm.setProfileNetworkPreference(testHandle2, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
@@ -12239,8 +12299,8 @@
mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
r -> r.run(), listener);
listener.expectOnComplete();
- inOrder.verify(mMockNetd).networkCreatePhysical(mCellNetworkAgent.getNetwork().netId,
- INetd.PERMISSION_NONE);
+ inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
+ mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE));
inOrder.verify(mMockNetd).networkAddUidRanges(mCellNetworkAgent.getNetwork().netId,
uidRangeFor(testHandle));
diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/packages/Connectivity/tests/unit/java/com/android/server/IpSecServiceParameterizedTest.java
similarity index 100%
rename from tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
rename to 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
similarity index 100%
rename from tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java
rename to 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
similarity index 100%
rename from tests/net/java/com/android/server/IpSecServiceTest.java
rename to 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
similarity index 100%
rename from tests/net/java/com/android/server/LegacyTypeTrackerTest.kt
rename to 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
similarity index 100%
rename from tests/net/java/com/android/server/NetIdManagerTest.kt
rename to 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
similarity index 100%
rename from tests/net/java/com/android/server/NetworkManagementServiceTest.java
rename to 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
similarity index 100%
rename from tests/net/java/com/android/server/NsdServiceTest.java
rename to 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
similarity index 96%
rename from tests/net/java/com/android/server/connectivity/DnsManagerTest.java
rename to packages/Connectivity/tests/unit/java/com/android/server/connectivity/DnsManagerTest.java
index 692c50f..0ffeec9 100644
--- a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java
+++ b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/DnsManagerTest.java
@@ -16,10 +16,10 @@
package com.android.server.connectivity;
-import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
-import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_DEFAULT_MODE;
import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE;
+import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OFF;
+import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_SPECIFIER;
import static android.net.NetworkCapabilities.MAX_TRANSPORT;
import static android.net.NetworkCapabilities.MIN_TRANSPORT;
@@ -44,6 +44,7 @@
import android.annotation.NonNull;
import android.content.Context;
+import android.net.ConnectivitySettingsManager;
import android.net.IDnsResolver;
import android.net.IpPrefix;
import android.net.LinkAddress;
@@ -187,9 +188,8 @@
lp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
TEST_IFACENAME));
- Settings.Global.putString(mContentResolver,
- PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
- Settings.Global.putString(mContentResolver, PRIVATE_DNS_SPECIFIER, "strictmode.com");
+ ConnectivitySettingsManager.setPrivateDnsMode(mCtx, PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
+ ConnectivitySettingsManager.setPrivateDnsHostname(mCtx, "strictmode.com");
mDnsManager.updatePrivateDns(new Network(TEST_NETID),
new PrivateDnsConfig("strictmode.com", new InetAddress[] {
InetAddress.parseNumericAddress("6.6.6.6"),
@@ -294,7 +294,7 @@
assertNull(lp.getPrivateDnsServerName());
// Turn private DNS mode off
- Settings.Global.putString(mContentResolver, PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_OFF);
+ ConnectivitySettingsManager.setPrivateDnsMode(mCtx, PRIVATE_DNS_MODE_OFF);
mDnsManager.updatePrivateDns(new Network(TEST_NETID),
mDnsManager.getPrivateDnsConfig());
mDnsManager.updateTransportsForNetwork(TEST_NETID, TEST_TRANSPORT_TYPES);
@@ -318,16 +318,15 @@
assertEquals(new InetAddress[0], cfgAuto.ips);
// Pretend a gservices push sets the default to "off".
- Settings.Global.putString(mContentResolver, PRIVATE_DNS_DEFAULT_MODE, "off");
+ ConnectivitySettingsManager.setPrivateDnsDefaultMode(mCtx, PRIVATE_DNS_MODE_OFF);
final PrivateDnsConfig cfgOff = DnsManager.getPrivateDnsConfig(mCtx);
assertFalse(cfgOff.useTls);
assertEquals("", cfgOff.hostname);
assertEquals(new InetAddress[0], cfgOff.ips);
// Strict mode still works.
- Settings.Global.putString(
- mContentResolver, PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
- Settings.Global.putString(mContentResolver, PRIVATE_DNS_SPECIFIER, "strictmode.com");
+ ConnectivitySettingsManager.setPrivateDnsMode(mCtx, PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
+ ConnectivitySettingsManager.setPrivateDnsHostname(mCtx, "strictmode.com");
final PrivateDnsConfig cfgStrict = DnsManager.getPrivateDnsConfig(mCtx);
assertTrue(cfgStrict.useTls);
assertEquals("strictmode.com", cfgStrict.hostname);
diff --git a/tests/net/java/com/android/server/connectivity/FullScoreTest.kt b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/FullScoreTest.kt
similarity index 100%
rename from tests/net/java/com/android/server/connectivity/FullScoreTest.kt
rename to 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
similarity index 100%
rename from tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
rename to 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
similarity index 100%
rename from tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
rename to 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
similarity index 100%
rename from tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
rename to 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
similarity index 100%
rename from tests/net/java/com/android/server/connectivity/MetricsTestUtil.java
rename to 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
similarity index 100%
rename from tests/net/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java
rename to 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
similarity index 100%
rename from tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
rename to 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
similarity index 100%
rename from tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
rename to 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
similarity index 100%
rename from tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
rename to 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
similarity index 100%
rename from tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt
rename to 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
similarity index 97%
rename from tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
rename to packages/Connectivity/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
index d7535a9..02a5808 100644
--- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -479,13 +479,14 @@
public void testUidFilteringDuringVpnConnectDisconnectAndUidUpdates() throws Exception {
when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
Arrays.asList(new PackageInfo[] {
- buildPackageInfo(/* SYSTEM */ true, SYSTEM_UID1, MOCK_USER1),
- buildPackageInfo(/* SYSTEM */ false, MOCK_UID1, MOCK_USER1),
- buildPackageInfo(/* SYSTEM */ false, MOCK_UID2, MOCK_USER1),
- buildPackageInfo(/* SYSTEM */ false, VPN_UID, MOCK_USER1)
+ buildPackageInfo(true /* hasSystemPermission */, SYSTEM_UID1, MOCK_USER1),
+ buildPackageInfo(false /* hasSystemPermission */, MOCK_UID1, MOCK_USER1),
+ buildPackageInfo(false /* hasSystemPermission */, MOCK_UID2, MOCK_USER1),
+ buildPackageInfo(false /* hasSystemPermission */, VPN_UID, MOCK_USER1)
}));
- when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE1), eq(GET_PERMISSIONS))).thenReturn(
- buildPackageInfo(false, MOCK_UID1, MOCK_USER1));
+ when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE1),
+ eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
+ buildPackageInfo(false /* hasSystemPermission */, MOCK_UID1, MOCK_USER1));
mPermissionMonitor.startMonitoring();
// Every app on user 0 except MOCK_UID2 are under VPN.
final Set<UidRange> vpnRange1 = new HashSet<>(Arrays.asList(new UidRange[] {
@@ -530,11 +531,12 @@
public void testUidFilteringDuringPackageInstallAndUninstall() throws Exception {
when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
Arrays.asList(new PackageInfo[] {
- buildPackageInfo(true, SYSTEM_UID1, MOCK_USER1),
- buildPackageInfo(false, VPN_UID, MOCK_USER1)
+ buildPackageInfo(true /* hasSystemPermission */, SYSTEM_UID1, MOCK_USER1),
+ buildPackageInfo(false /* hasSystemPermission */, VPN_UID, MOCK_USER1)
}));
- when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE1), eq(GET_PERMISSIONS))).thenReturn(
- buildPackageInfo(false, MOCK_UID1, MOCK_USER1));
+ when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE1),
+ eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
+ buildPackageInfo(false /* hasSystemPermission */, MOCK_UID1, MOCK_USER1));
mPermissionMonitor.startMonitoring();
final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(MOCK_USER1));
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/VpnTest.java
similarity index 100%
rename from tests/net/java/com/android/server/connectivity/VpnTest.java
rename to 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
similarity index 100%
rename from tests/net/java/com/android/server/net/NetworkStatsAccessTest.java
rename to 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
similarity index 100%
rename from tests/net/java/com/android/server/net/NetworkStatsBaseTest.java
rename to 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
similarity index 100%
rename from tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
rename to 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
similarity index 100%
rename from tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java
rename to packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java
diff --git a/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java
similarity index 100%
rename from tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
rename to 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
similarity index 100%
rename from tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
rename to packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
diff --git a/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java
similarity index 100%
rename from tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java
rename to 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
similarity index 100%
rename from tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java
rename to 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
similarity index 100%
rename from tests/net/jni/Android.bp
rename to 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
similarity index 100%
rename from tests/net/jni/test_onload.cpp
rename to 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
similarity index 100%
rename from tests/net/res/raw/history_v1
rename to packages/Connectivity/tests/unit/res/raw/history_v1
Binary files differ
diff --git a/tests/net/res/raw/net_dev_typical b/packages/Connectivity/tests/unit/res/raw/net_dev_typical
similarity index 100%
rename from tests/net/res/raw/net_dev_typical
rename to 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
similarity index 100%
rename from tests/net/res/raw/netstats_uid_v4
rename to packages/Connectivity/tests/unit/res/raw/netstats_uid_v4
Binary files differ
diff --git a/tests/net/res/raw/netstats_v1 b/packages/Connectivity/tests/unit/res/raw/netstats_v1
similarity index 100%
rename from tests/net/res/raw/netstats_v1
rename to packages/Connectivity/tests/unit/res/raw/netstats_v1
Binary files differ
diff --git a/tests/net/res/raw/xt_qtaguid_iface_fmt_typical b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_iface_fmt_typical
similarity index 100%
rename from tests/net/res/raw/xt_qtaguid_iface_fmt_typical
rename to 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
similarity index 100%
rename from tests/net/res/raw/xt_qtaguid_iface_typical
rename to 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
similarity index 100%
rename from tests/net/res/raw/xt_qtaguid_typical
rename to 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
similarity index 100%
rename from tests/net/res/raw/xt_qtaguid_vpn_incorrect_iface
rename to 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
similarity index 100%
rename from tests/net/res/raw/xt_qtaguid_vpn_one_underlying
rename to 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
similarity index 100%
rename from tests/net/res/raw/xt_qtaguid_vpn_one_underlying_compression
rename to 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
similarity index 100%
rename from tests/net/res/raw/xt_qtaguid_vpn_one_underlying_own_traffic
rename to 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
similarity index 100%
rename from tests/net/res/raw/xt_qtaguid_vpn_one_underlying_two_vpn
rename to 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
similarity index 100%
rename from tests/net/res/raw/xt_qtaguid_vpn_rewrite_through_self
rename to 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
similarity index 100%
rename from tests/net/res/raw/xt_qtaguid_vpn_two_underlying_duplication
rename to 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
similarity index 100%
rename from tests/net/res/raw/xt_qtaguid_vpn_two_underlying_split
rename to 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
similarity index 100%
rename from tests/net/res/raw/xt_qtaguid_vpn_two_underlying_split_compression
rename to 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
similarity index 100%
rename from tests/net/res/raw/xt_qtaguid_vpn_with_clat
rename to 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
similarity index 100%
rename from tests/net/res/raw/xt_qtaguid_with_clat
rename to 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
similarity index 100%
rename from tests/net/res/raw/xt_qtaguid_with_clat_100mb_download_after
rename to 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
similarity index 100%
rename from tests/net/res/raw/xt_qtaguid_with_clat_100mb_download_before
rename to 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
similarity index 100%
rename from tests/net/res/raw/xt_qtaguid_with_clat_simple
rename to packages/Connectivity/tests/unit/res/raw/xt_qtaguid_with_clat_simple
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
index 16a946d..f8cb5d3 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
@@ -561,7 +561,20 @@
break;
}
- Log.d(TAG, "status=" + statusString + ", cause=" + causeString + ", detail=" + detail);
+ StringBuilder msg = new StringBuilder();
+ msg.append("status: " + statusString + ", cause: " + causeString);
+ if (status == STATUS_IN_PROGRESS) {
+ msg.append(
+ String.format(
+ ", partition name: %s, progress: %d/%d",
+ mCurrentPartitionName,
+ mCurrentPartitionInstalledSize,
+ mCurrentPartitionSize));
+ }
+ if (detail != null) {
+ msg.append(", detail: " + detail);
+ }
+ Log.d(TAG, msg.toString());
if (notifyOnNotificationBar) {
mNM.notify(NOTIFICATION_ID, buildNotification(status, cause, detail));
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
index 59ea9f0..f18d426 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
@@ -320,20 +320,21 @@
}
}
- private void installScratch() throws IOException {
- final long scratchSize = mDynSystem.suggestScratchSize();
+ private void installWritablePartition(final String partitionName, final long partitionSize)
+ throws IOException {
+ Log.d(TAG, "Creating writable partition: " + partitionName + ", size: " + partitionSize);
+
Thread thread = new Thread() {
@Override
public void run() {
mInstallationSession =
- mDynSystem.createPartition("scratch", scratchSize, /* readOnly= */ false);
+ mDynSystem.createPartition(
+ partitionName, partitionSize, /* readOnly= */ false);
}
};
- Log.d(TAG, "Creating partition: scratch, size = " + scratchSize);
thread.start();
-
- Progress progress = new Progress("scratch", scratchSize, mNumInstalledPartitions++);
+ Progress progress = new Progress(partitionName, partitionSize, mNumInstalledPartitions++);
while (thread.isAlive()) {
if (isCancelled()) {
@@ -356,53 +357,22 @@
if (mInstallationSession == null) {
throw new IOException(
- "Failed to start installation with requested size: " + scratchSize);
+ "Failed to start installation with requested size: " + partitionSize);
}
+
// Reset installation session and verify that installation completes successfully.
mInstallationSession = null;
if (!mDynSystem.closePartition()) {
- throw new IOException("Failed to complete partition installation: scratch");
+ throw new IOException("Failed to complete partition installation: " + partitionName);
}
}
+ private void installScratch() throws IOException {
+ installWritablePartition("scratch", mDynSystem.suggestScratchSize());
+ }
+
private void installUserdata() throws IOException {
- Thread thread = new Thread(() -> {
- mInstallationSession = mDynSystem.createPartition("userdata", mUserdataSize, false);
- });
-
- Log.d(TAG, "Creating partition: userdata, size = " + mUserdataSize);
- thread.start();
-
- Progress progress = new Progress("userdata", mUserdataSize, mNumInstalledPartitions++);
-
- while (thread.isAlive()) {
- if (isCancelled()) {
- return;
- }
-
- final long installedSize = mDynSystem.getInstallationProgress().bytes_processed;
-
- if (installedSize > progress.installedSize + MIN_PROGRESS_TO_PUBLISH) {
- progress.installedSize = installedSize;
- publishProgress(progress);
- }
-
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- // Ignore the error.
- }
- }
-
- if (mInstallationSession == null) {
- throw new IOException(
- "Failed to start installation with requested size: " + mUserdataSize);
- }
- // Reset installation session and verify that installation completes successfully.
- mInstallationSession = null;
- if (!mDynSystem.closePartition()) {
- throw new IOException("Failed to complete partition installation: userdata");
- }
+ installWritablePartition("userdata", mUserdataSize);
}
private void installImages() throws IOException, ImageValidationException {
diff --git a/packages/InputDevices/res/raw/keyboard_layout_arabic.kcm b/packages/InputDevices/res/raw/keyboard_layout_arabic.kcm
index 44d5a0c..1614188 100644
--- a/packages/InputDevices/res/raw/keyboard_layout_arabic.kcm
+++ b/packages/InputDevices/res/raw/keyboard_layout_arabic.kcm
@@ -171,15 +171,15 @@
}
key LEFT_BRACKET {
- label: '['
+ label: ']'
base, capslock: '\u062c'
- shift: '<'
+ shift: '>'
}
key RIGHT_BRACKET {
- label: ']'
+ label: '['
base, capslock: '\u062f'
- shift: '>'
+ shift: '<'
}
key BACKSLASH {
diff --git a/packages/InputDevices/res/raw/keyboard_layout_hebrew.kcm b/packages/InputDevices/res/raw/keyboard_layout_hebrew.kcm
index cd3a4b9..283cb4e 100644
--- a/packages/InputDevices/res/raw/keyboard_layout_hebrew.kcm
+++ b/packages/InputDevices/res/raw/keyboard_layout_hebrew.kcm
@@ -89,14 +89,14 @@
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 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 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 e7dd6c6..bfe7821 100644
--- a/packages/InputDevices/res/raw/keyboard_layout_persian.kcm
+++ b/packages/InputDevices/res/raw/keyboard_layout_persian.kcm
@@ -292,14 +292,14 @@
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_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/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 27df92f..2a12ce2 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -467,6 +467,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/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
index 583953c..5043724 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
@@ -80,6 +80,7 @@
private int mImeHeight;
private boolean mIsShelfShowing;
private int mShelfHeight;
+ private boolean mDefaultLandscape;
private final DisplayController.OnDisplaysChangedListener mDisplaysChangedListener =
new DisplayController.OnDisplaysChangedListener() {
@@ -87,6 +88,7 @@
public void onDisplayAdded(int displayId) {
if (displayId == mContext.getDisplayId()) {
mDisplayLayout.set(mDisplayController.getDisplayLayout(displayId));
+ mDefaultLandscape = (mDisplayInfo.logicalWidth > mDisplayInfo.logicalHeight);
}
}
};
@@ -362,9 +364,17 @@
private void updateDisplayInfoIfNeeded() {
final boolean updateNeeded;
if ((mDisplayInfo.rotation == ROTATION_0) || (mDisplayInfo.rotation == ROTATION_180)) {
- updateNeeded = (mDisplayInfo.logicalWidth > mDisplayInfo.logicalHeight);
+ if (!mDefaultLandscape) {
+ updateNeeded = (mDisplayInfo.logicalWidth > mDisplayInfo.logicalHeight);
+ } else {
+ updateNeeded = (mDisplayInfo.logicalWidth < mDisplayInfo.logicalHeight);
+ }
} else {
- updateNeeded = (mDisplayInfo.logicalWidth < mDisplayInfo.logicalHeight);
+ if (!mDefaultLandscape) {
+ updateNeeded = (mDisplayInfo.logicalWidth < mDisplayInfo.logicalHeight);
+ } else {
+ updateNeeded = (mDisplayInfo.logicalWidth > mDisplayInfo.logicalHeight);
+ }
}
if (updateNeeded) {
final int newLogicalHeight = mDisplayInfo.logicalWidth;
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 0ac8f74..706f738 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -10,7 +10,6 @@
filegroup {
name: "services.core-sources",
srcs: ["java/**/*.java"],
- exclude_srcs: [":connectivity-service-srcs"],
path: "java",
visibility: ["//frameworks/base/services"],
}
@@ -200,29 +199,3 @@
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/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java
index 9c8582f7..f4a8f37 100644
--- a/services/core/java/com/android/server/BinderCallsStatsService.java
+++ b/services/core/java/com/android/server/BinderCallsStatsService.java
@@ -133,6 +133,12 @@
private static final String SETTINGS_COLLECT_LATENCY_DATA_KEY = "collect_Latency_data";
private static final String SETTINGS_LATENCY_OBSERVER_SAMPLING_INTERVAL_KEY =
"latency_observer_sampling_interval";
+ private static final String SETTINGS_LATENCY_HISTOGRAM_BUCKET_COUNT_KEY =
+ "latency_histogram_bucket_count";
+ private static final String SETTINGS_LATENCY_HISTOGRAM_FIRST_BUCKET_SIZE_KEY =
+ "latency_histogram_first_bucket_size";
+ private static final String SETTINGS_LATENCY_HISTOGRAM_BUCKET_SCALE_FACTOR_KEY =
+ "latency_histogram_bucket_scale_factor";
private boolean mEnabled;
private final Uri mUri = Settings.Global.getUriFor(Settings.Global.BINDER_CALLS_STATS);
@@ -190,9 +196,20 @@
mParser.getBoolean(SETTINGS_COLLECT_LATENCY_DATA_KEY,
BinderCallsStats.DEFAULT_COLLECT_LATENCY_DATA));
// Binder latency observer settings.
- mBinderCallsStats.getLatencyObserver().setSamplingInterval(mParser.getInt(
+ BinderLatencyObserver binderLatencyObserver = mBinderCallsStats.getLatencyObserver();
+ binderLatencyObserver.setSamplingInterval(mParser.getInt(
SETTINGS_LATENCY_OBSERVER_SAMPLING_INTERVAL_KEY,
BinderLatencyObserver.PERIODIC_SAMPLING_INTERVAL_DEFAULT));
+ binderLatencyObserver.setHistogramBucketsParams(
+ mParser.getInt(
+ SETTINGS_LATENCY_HISTOGRAM_BUCKET_COUNT_KEY,
+ BinderLatencyObserver.BUCKET_COUNT_DEFAULT),
+ mParser.getInt(
+ SETTINGS_LATENCY_HISTOGRAM_FIRST_BUCKET_SIZE_KEY,
+ BinderLatencyObserver.FIRST_BUCKET_SIZE_DEFAULT),
+ mParser.getFloat(
+ SETTINGS_LATENCY_HISTOGRAM_BUCKET_SCALE_FACTOR_KEY,
+ BinderLatencyObserver.BUCKET_SCALE_FACTOR_DEFAULT));
final boolean enabled =
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index d574e74..d6ee951 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -1112,7 +1112,7 @@
case IpSecManager.DIRECTION_IN:
return;
case IpSecManager.DIRECTION_FWD:
- // Only NETWORK_STACK or PERMISSION_NETWORK_STACK allowed to use forward policies
+ // Only NETWORK_STACK or MAINLINE_NETWORK_STACK allowed to use forward policies
PermissionUtils.enforceNetworkStackPermission(mContext);
return;
}
@@ -1358,6 +1358,16 @@
ikey,
0xffffffff,
resourceId);
+
+ // Add a forwarding policy on the tunnel interface. In order to support forwarding
+ // the IpSecTunnelInterface must have a forwarding policy matching the incoming SA.
+ //
+ // Unless a IpSecTransform is also applied against this interface in DIRECTION_FWD,
+ // forwarding will be blocked by default (as would be the case if this policy was
+ // absent).
+ //
+ // This is necessary only on the tunnel interface, and not any the interface to
+ // which traffic will be forwarded to.
netd.ipSecAddSecurityPolicy(
callerUid,
selAddrFamily,
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index 1fd637a..bcbd692 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -167,7 +167,6 @@
@NonNull private final VcnNetworkProvider mNetworkProvider;
@NonNull private final TelephonySubscriptionTrackerCallback mTelephonySubscriptionTrackerCb;
@NonNull private final TelephonySubscriptionTracker mTelephonySubscriptionTracker;
- @NonNull private final VcnContext mVcnContext;
@NonNull private final BroadcastReceiver mPkgChangeReceiver;
@NonNull
@@ -212,7 +211,6 @@
mContext, mLooper, mTelephonySubscriptionTrackerCb);
mConfigDiskRwHelper = mDeps.newPersistableBundleLockingReadWriteHelper(VCN_CONFIG_FILE);
- mVcnContext = mDeps.newVcnContext(mContext, mLooper, mNetworkProvider);
mPkgChangeReceiver = new BroadcastReceiver() {
@Override
@@ -336,8 +334,9 @@
public VcnContext newVcnContext(
@NonNull Context context,
@NonNull Looper looper,
- @NonNull VcnNetworkProvider vcnNetworkProvider) {
- return new VcnContext(context, looper, vcnNetworkProvider);
+ @NonNull VcnNetworkProvider vcnNetworkProvider,
+ boolean isInTestMode) {
+ return new VcnContext(context, looper, vcnNetworkProvider, isInTestMode);
}
/** Creates a new Vcn instance using the provided configuration */
@@ -421,6 +420,14 @@
"Carrier privilege required for subscription group to set VCN Config");
}
+ private void enforceManageTestNetworksForTestMode(@NonNull VcnConfig vcnConfig) {
+ if (vcnConfig.isTestModeProfile()) {
+ mContext.enforceCallingPermission(
+ android.Manifest.permission.MANAGE_TEST_NETWORKS,
+ "Test-mode require the MANAGE_TEST_NETWORKS permission");
+ }
+ }
+
private class VcnSubscriptionTrackerCallback implements TelephonySubscriptionTrackerCallback {
/**
* Handles subscription group changes, as notified by {@link TelephonySubscriptionTracker}
@@ -544,8 +551,11 @@
final VcnCallbackImpl vcnCallback = new VcnCallbackImpl(subscriptionGroup);
+ final VcnContext vcnContext =
+ mDeps.newVcnContext(
+ mContext, mLooper, mNetworkProvider, config.isTestModeProfile());
final Vcn newInstance =
- mDeps.newVcn(mVcnContext, subscriptionGroup, config, mLastSnapshot, vcnCallback);
+ mDeps.newVcn(vcnContext, subscriptionGroup, config, mLastSnapshot, vcnCallback);
mVcns.put(subscriptionGroup, newInstance);
// Now that a new VCN has started, notify all registered listeners to refresh their
@@ -589,6 +599,7 @@
mContext.getSystemService(AppOpsManager.class)
.checkPackage(mDeps.getBinderCallingUid(), config.getProvisioningPackageName());
+ enforceManageTestNetworksForTestMode(config);
enforceCallingUserAndCarrierPrivilege(subscriptionGroup, opPkgName);
Binder.withCleanCallingIdentity(() -> {
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index a37115d..2e38278 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -96,6 +96,7 @@
"/system/bin/audioserver",
"/system/bin/cameraserver",
"/system/bin/drmserver",
+ "/system/bin/keystore2",
"/system/bin/mediadrmserver",
"/system/bin/mediaserver",
"/system/bin/netd",
diff --git a/services/core/java/com/android/server/am/LmkdConnection.java b/services/core/java/com/android/server/am/LmkdConnection.java
index f41c364..1ecb9eb 100644
--- a/services/core/java/com/android/server/am/LmkdConnection.java
+++ b/services/core/java/com/android/server/am/LmkdConnection.java
@@ -31,6 +31,8 @@
import libcore.io.IoUtils;
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
@@ -43,8 +45,12 @@
public class LmkdConnection {
private static final String TAG = TAG_WITH_CLASS_NAME ? "LmkdConnection" : TAG_AM;
- // lmkd reply max size in bytes
- private static final int LMKD_REPLY_MAX_SIZE = 12;
+ /**
+ * Max LMKD reply packet length in bytes
+ * Used to hold the data for the statsd atoms logging
+ * Must be in sync with statslog.h
+ */
+ private static final int LMKD_REPLY_MAX_SIZE = 214;
// connection listener interface
interface LmkdConnectionListener {
@@ -70,7 +76,7 @@
* @param receivedLen Size of the data received
* @return True if the message has been handled correctly, false otherwise.
*/
- boolean handleUnsolicitedMessage(ByteBuffer dataReceived, int receivedLen);
+ boolean handleUnsolicitedMessage(DataInputStream inputData, int receivedLen);
}
private final MessageQueue mMsgQueue;
@@ -95,6 +101,10 @@
private final ByteBuffer mInputBuf =
ByteBuffer.allocate(LMKD_REPLY_MAX_SIZE);
+ // Input stream to parse the incoming data
+ private final DataInputStream mInputData = new DataInputStream(
+ new ByteArrayInputStream(mInputBuf.array()));
+
// object to protect mReplyBuf and to wait/notify when reply is received
private final Object mReplyBufLock = new Object();
@@ -186,26 +196,32 @@
private void processIncomingData() {
int len = read(mInputBuf);
if (len > 0) {
- synchronized (mReplyBufLock) {
- if (mReplyBuf != null) {
- if (mListener.isReplyExpected(mReplyBuf, mInputBuf, len)) {
- // copy into reply buffer
- mReplyBuf.put(mInputBuf.array(), 0, len);
- mReplyBuf.rewind();
- // wakeup the waiting thread
- mReplyBufLock.notifyAll();
- } else if (!mListener.handleUnsolicitedMessage(mInputBuf, len)) {
- // received unexpected packet
- // treat this as an error
- mReplyBuf = null;
- mReplyBufLock.notifyAll();
- Slog.e(TAG, "Received an unexpected packet from lmkd");
+ try {
+ // reset InputStream to point into mInputBuf.array() begin
+ mInputData.reset();
+ synchronized (mReplyBufLock) {
+ if (mReplyBuf != null) {
+ if (mListener.isReplyExpected(mReplyBuf, mInputBuf, len)) {
+ // copy into reply buffer
+ mReplyBuf.put(mInputBuf.array(), 0, len);
+ mReplyBuf.rewind();
+ // wakeup the waiting thread
+ mReplyBufLock.notifyAll();
+ } else if (!mListener.handleUnsolicitedMessage(mInputData, len)) {
+ // received unexpected packet
+ // treat this as an error
+ mReplyBuf = null;
+ mReplyBufLock.notifyAll();
+ Slog.e(TAG, "Received an unexpected packet from lmkd");
+ }
+ } else if (!mListener.handleUnsolicitedMessage(mInputData, len)) {
+ // received asynchronous communication from lmkd
+ // but we don't recognize it.
+ Slog.w(TAG, "Received an unexpected packet from lmkd");
}
- } else if (!mListener.handleUnsolicitedMessage(mInputBuf, len)) {
- // received asynchronous communication from lmkd
- // but we don't recognize it.
- Slog.w(TAG, "Received an unexpected packet from lmkd");
}
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to parse lmkd data buffer. Size = " + len);
}
}
}
diff --git a/services/core/java/com/android/server/am/LmkdStatsReporter.java b/services/core/java/com/android/server/am/LmkdStatsReporter.java
new file mode 100644
index 0000000..c702d78
--- /dev/null
+++ b/services/core/java/com/android/server/am/LmkdStatsReporter.java
@@ -0,0 +1,107 @@
+/*
+ * 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.am;
+
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+
+import android.util.Slog;
+
+import com.android.internal.util.FrameworkStatsLog;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+
+/**
+ * Activity manager communication with lmkd data handling and statsd atom logging
+ */
+public final class LmkdStatsReporter {
+
+ static final String TAG = TAG_WITH_CLASS_NAME ? "LmkdStatsReporter" : TAG_AM;
+
+ public static final int KILL_OCCURRED_MSG_SIZE = 80;
+ public static final int STATE_CHANGED_MSG_SIZE = 8;
+
+ private static final int PRESSURE_AFTER_KILL = 0;
+ private static final int NOT_RESPONDING = 1;
+ private static final int LOW_SWAP_AND_THRASHING = 2;
+ private static final int LOW_MEM_AND_SWAP = 3;
+ private static final int LOW_MEM_AND_THRASHING = 4;
+ private static final int DIRECT_RECL_AND_THRASHING = 5;
+ private static final int LOW_MEM_AND_SWAP_UTIL = 6;
+
+ /**
+ * Processes the LMK_KILL_OCCURRED packet data
+ * Logs the event when LMKD kills a process to reduce memory pressure.
+ * Code: LMK_KILL_OCCURRED = 51
+ */
+ public static void logKillOccurred(DataInputStream inputData) {
+ try {
+ final long pgFault = inputData.readLong();
+ final long pgMajFault = inputData.readLong();
+ final long rssInBytes = inputData.readLong();
+ final long cacheInBytes = inputData.readLong();
+ final long swapInBytes = inputData.readLong();
+ final long processStartTimeNS = inputData.readLong();
+ final int uid = inputData.readInt();
+ final int oomScore = inputData.readInt();
+ final int minOomScore = inputData.readInt();
+ final int freeMemKb = inputData.readInt();
+ final int freeSwapKb = inputData.readInt();
+ final int killReason = inputData.readInt();
+ final String procName = inputData.readUTF();
+
+ FrameworkStatsLog.write(FrameworkStatsLog.LMK_KILL_OCCURRED, uid, procName, oomScore,
+ pgFault, pgMajFault, rssInBytes, cacheInBytes, swapInBytes, processStartTimeNS,
+ minOomScore, freeMemKb, freeSwapKb, mapKillReason(killReason));
+ } catch (IOException e) {
+ Slog.e(TAG, "Invalid buffer data. Failed to log LMK_KILL_OCCURRED");
+ return;
+ }
+ }
+
+ /**
+ * Processes the LMK_STATE_CHANGED packet
+ * Logs the change in LMKD state which is used as start/stop boundaries for logging
+ * LMK_KILL_OCCURRED event.
+ * Code: LMK_STATE_CHANGED = 54
+ */
+ public static void logStateChanged(int state) {
+ FrameworkStatsLog.write(FrameworkStatsLog.LMK_STATE_CHANGED, state);
+ }
+
+ private static int mapKillReason(int reason) {
+ switch (reason) {
+ case PRESSURE_AFTER_KILL:
+ return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__PRESSURE_AFTER_KILL;
+ case NOT_RESPONDING:
+ return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__NOT_RESPONDING;
+ case LOW_SWAP_AND_THRASHING:
+ return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__LOW_SWAP_AND_THRASHING;
+ case LOW_MEM_AND_SWAP:
+ return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__LOW_MEM_AND_SWAP;
+ case LOW_MEM_AND_THRASHING:
+ return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__LOW_MEM_AND_THRASHING;
+ case DIRECT_RECL_AND_THRASHING:
+ return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__DIRECT_RECL_AND_THRASHING;
+ case LOW_MEM_AND_SWAP_UTIL:
+ return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__LOW_MEM_AND_SWAP_UTIL;
+ default:
+ return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__UNKNOWN;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 444418c..e9b0146 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -125,6 +125,7 @@
import dalvik.system.VMRuntime;
+import java.io.DataInputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -316,18 +317,25 @@
// LMK_GETKILLCNT
// LMK_SUBSCRIBE
// LMK_PROCKILL
+ // LMK_UPDATE_PROPS
+ // LMK_KILL_OCCURRED
+ // LMK_STATE_CHANGED
static final byte LMK_TARGET = 0;
static final byte LMK_PROCPRIO = 1;
static final byte LMK_PROCREMOVE = 2;
static final byte LMK_PROCPURGE = 3;
static final byte LMK_GETKILLCNT = 4;
static final byte LMK_SUBSCRIBE = 5;
- static final byte LMK_PROCKILL = 6; // Note: this is an unsolicated command
+ static final byte LMK_PROCKILL = 6; // Note: this is an unsolicited command
+ static final byte LMK_UPDATE_PROPS = 7;
+ static final byte LMK_KILL_OCCURRED = 8; // Msg to subscribed clients on kill occurred event
+ static final byte LMK_STATE_CHANGED = 9; // Msg to subscribed clients on state changed
// Low Memory Killer Daemon command codes.
// These must be kept in sync with async_event_type definitions in lmkd.h
//
static final int LMK_ASYNC_EVENT_KILL = 0;
+ static final int LMK_ASYNC_EVENT_STAT = 1;
// lmkd reconnect delay in msecs
private static final long LMKD_RECONNECT_DELAY_MS = 1000;
@@ -776,22 +784,44 @@
}
@Override
- public boolean handleUnsolicitedMessage(ByteBuffer dataReceived,
+ public boolean handleUnsolicitedMessage(DataInputStream inputData,
int receivedLen) {
if (receivedLen < 4) {
return false;
}
- switch (dataReceived.getInt(0)) {
- case LMK_PROCKILL:
- if (receivedLen != 12) {
+
+ try {
+ switch (inputData.readInt()) {
+ case LMK_PROCKILL:
+ if (receivedLen != 12) {
+ return false;
+ }
+ final int pid = inputData.readInt();
+ final int uid = inputData.readInt();
+ mAppExitInfoTracker.scheduleNoteLmkdProcKilled(pid, uid);
+ return true;
+ case LMK_KILL_OCCURRED:
+ if (receivedLen
+ < LmkdStatsReporter.KILL_OCCURRED_MSG_SIZE) {
+ return false;
+ }
+ LmkdStatsReporter.logKillOccurred(inputData);
+ return true;
+ case LMK_STATE_CHANGED:
+ if (receivedLen
+ != LmkdStatsReporter.STATE_CHANGED_MSG_SIZE) {
+ return false;
+ }
+ final int state = inputData.readInt();
+ LmkdStatsReporter.logStateChanged(state);
+ return true;
+ default:
return false;
- }
- mAppExitInfoTracker.scheduleNoteLmkdProcKilled(
- dataReceived.getInt(4), dataReceived.getInt(8));
- return true;
- default:
- return false;
+ }
+ } catch (IOException e) {
+ Slog.e(TAG, "Invalid buffer data. Failed to log LMK_KILL_OCCURRED");
}
+ return false;
}
}
);
@@ -1433,6 +1463,12 @@
buf.putInt(LMK_SUBSCRIBE);
buf.putInt(LMK_ASYNC_EVENT_KILL);
ostream.write(buf.array(), 0, buf.position());
+
+ // Subscribe for stats event notifications
+ buf = ByteBuffer.allocate(4 * 2);
+ buf.putInt(LMK_SUBSCRIBE);
+ buf.putInt(LMK_ASYNC_EVENT_STAT);
+ ostream.write(buf.array(), 0, buf.position());
} catch (IOException ex) {
return false;
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 22a6044..d0a3079 100755
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -5860,6 +5860,10 @@
if (index == -1) {
continue;
}
+ if (mPublicStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED
+ && mCameraSoundForced) {
+ index = mIndexMax;
+ }
if (DEBUG_VOL) {
Log.v(TAG, "readSettings: found stored index " + getValidIndex(index)
+ " for group " + mAudioVolumeGroup.name() + ", device: " + name);
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java b/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java
index 740407c..e233084 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java
@@ -86,6 +86,8 @@
pw.println(" Send a Vendor Command to the given target device");
pw.println(" setsystemaudiomode, setsam [on|off]");
pw.println(" Sets the System Audio Mode feature on or off on TV devices");
+ pw.println(" setarc [on|off]");
+ pw.println(" Sets the ARC feature on or off on TV devices");
}
private int handleShellCommand(String cmd) throws RemoteException {
@@ -100,6 +102,8 @@
case "setsystemaudiomode":
case "setsam":
return setSystemAudioMode(pw);
+ case "setarc":
+ return setArcMode(pw);
}
getErrPrintWriter().println("Unhandled command: " + cmd);
@@ -188,6 +192,27 @@
return mCecResult.get() == HdmiControlManager.RESULT_SUCCESS ? 0 : 1;
}
+ private int setArcMode(PrintWriter pw) throws RemoteException {
+ if (1 > getRemainingArgsCount()) {
+ throw new IllegalArgumentException(
+ "Please indicate if ARC mode should be turned \"on\" or \"off\".");
+ }
+
+ String arg = getNextArg();
+ if (arg.equals("on")) {
+ pw.println("Setting ARC mode on");
+ mBinderService.setArcMode(true);
+ } else if (arg.equals("off")) {
+ pw.println("Setting ARC mode off");
+ mBinderService.setArcMode(false);
+ } else {
+ throw new IllegalArgumentException(
+ "Please indicate if ARC mode should be turned \"on\" or \"off\".");
+ }
+
+ return 0;
+ }
+
private boolean receiveCallback(String command) {
try {
if (!mLatch.await(HdmiConfig.TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java
index e7c0a50..431b009 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 @@
// 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/os/OWNERS b/services/core/java/com/android/server/os/OWNERS
new file mode 100644
index 0000000..1957332
--- /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/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index fa64df5..836e615 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 @@
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 @@
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/TelephonySubscriptionTracker.java b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
index 19fbdbd..5565ccb 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 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 @@
}
// 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 @@
}
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 @@
/** 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 @@
@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 @@
/** 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 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 @@
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 @@
final TelephonySubscriptionSnapshot other = (TelephonySubscriptionSnapshot) obj;
- return mSubIdToGroupMap.equals(other.mSubIdToGroupMap)
+ return mSubIdToInfoMap.equals(other.mSubIdToInfoMap)
&& mPrivilegedPackages.equals(other.mPrivilegedPackages);
}
@@ -326,7 +336,7 @@
pw.println("TelephonySubscriptionSnapshot:");
pw.increaseIndent();
- pw.println("mSubIdToGroupMap: " + mSubIdToGroupMap);
+ pw.println("mSubIdToInfoMap: " + mSubIdToInfoMap);
pw.println("mPrivilegedPackages: " + mPrivilegedPackages);
pw.decreaseIndent();
@@ -335,7 +345,7 @@
@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 8818023..fb4c623 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.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.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,6 +67,45 @@
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;
@@ -58,12 +113,17 @@
@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;
@@ -104,6 +164,30 @@
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 +195,30 @@
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 +233,8 @@
} else {
mRouteSelectionCallback = null;
mWifiBringupCallback = null;
+ mWifiEntryRssiThresholdCallback = null;
+ mWifiExitRssiThresholdCallback = null;
// mCellBringupCallbacks already cleared above.
}
@@ -145,6 +245,12 @@
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);
}
@@ -158,9 +264,18 @@
* carrier owned networks may be selected, as the request specifies only subIds in the VCN's
* subscription group, while the VCN networks are excluded by virtue of not having subIds set on
* the VCN-exposed networks.
+ *
+ * <p>If the VCN that this UnderlyingNetworkTracker belongs to is in test-mode, this will return
+ * a NetworkRequest that only matches Test Networks.
*/
private NetworkRequest getRouteSelectionRequest() {
+ if (mVcnContext.isInTestMode()) {
+ return getTestNetworkRequest(mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup));
+ }
+
return getBaseNetworkRequestBuilder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)
.setSubscriptionIds(mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup))
.build();
}
@@ -182,6 +297,38 @@
}
/**
+ * 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
@@ -210,6 +357,15 @@
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED);
}
+ /** Builds and returns a NetworkRequest for the given subIds to match Test Networks. */
+ private NetworkRequest getTestNetworkRequest(@NonNull Set<Integer> subIds) {
+ return new NetworkRequest.Builder()
+ .clearCapabilities()
+ .addTransportType(NetworkCapabilities.TRANSPORT_TEST)
+ .setSubscriptionIds(subIds)
+ .build();
+ }
+
/**
* Update this UnderlyingNetworkTracker's TelephonySubscriptionSnapshot.
*
@@ -217,10 +373,18 @@
* 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");
- mLastSnapshot = snapshot;
+ final TelephonySubscriptionSnapshot oldSnapshot = mLastSnapshot;
+ mLastSnapshot = newSnapshot;
+
+ // Only trigger re-registration if subIds in this group have changed
+ if (oldSnapshot
+ .getAllSubIdsInGroup(mSubscriptionGroup)
+ .equals(newSnapshot.getAllSubIdsInGroup(mSubscriptionGroup))) {
+ return;
+ }
registerOrUpdateNetworkRequests();
}
@@ -231,88 +395,43 @@
// Will unregister all existing callbacks, but not register new ones due to quitting flag.
registerOrUpdateNetworkRequests();
+
+ mVcnContext
+ .getContext()
+ .getSystemService(TelephonyManager.class)
+ .unregisterTelephonyCallback(mActiveDataSubIdListener);
}
- /** 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);
- }
+ private void reevaluateNetworks() {
+ TreeSet<UnderlyingNetworkRecord> sorted =
+ new TreeSet<>(
+ UnderlyingNetworkRecord.getComparator(
+ mSubscriptionGroup, mLastSnapshot, mCurrentRecord, mCarrierConfig));
+ sorted.addAll(mRouteSelectionCallback.getUnderlyingNetworks());
- /** 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()) {
+ UnderlyingNetworkRecord candidate = sorted.isEmpty() ? null : sorted.first();
+ if (Objects.equals(mCurrentRecord, candidate)) {
return;
}
- // 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);
- }
+ mCurrentRecord = candidate;
+ 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");
- return;
+ private static boolean isOpportunistic(
+ @NonNull TelephonySubscriptionSnapshot snapshot, Set<Integer> subIds) {
+ if (snapshot == null) {
+ Slog.wtf(TAG, "Got null snapshot");
+ return false;
}
- mRecordInProgress = null;
- mCurrentRecord = null;
- mCb.onSelectedUnderlyingNetworkChanged(null /* underlyingNetworkRecord */);
- }
-
- private void handleCapabilitiesChanged(
- @NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) {
- mVcnContext.ensureRunningOnLooperThread();
-
- if (!isSameNetwork(mRecordInProgress, network)) {
- Slog.wtf(TAG, "Invalid update to NetworkCapabilities");
- return;
+ for (int subId : subIds) {
+ if (snapshot.isOpportunistic(subId)) {
+ return true;
+ }
}
- 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;
- }
-
- mRecordInProgress.setIsBlocked(isBlocked);
-
- maybeNotifyCallback();
+ return false;
}
/**
@@ -331,36 +450,104 @@
* 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;
@@ -397,6 +584,89 @@
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:");
@@ -418,6 +688,8 @@
boolean mIsBlocked;
boolean mWasIsBlockedSet;
+ @Nullable private UnderlyingNetworkRecord mCached;
+
private Builder(@NonNull Network network) {
mNetwork = network;
}
@@ -429,6 +701,7 @@
private void setNetworkCapabilities(@NonNull NetworkCapabilities networkCapabilities) {
mNetworkCapabilities = networkCapabilities;
+ mCached = null;
}
@Nullable
@@ -438,11 +711,13 @@
private void setLinkProperties(@NonNull LinkProperties linkProperties) {
mLinkProperties = linkProperties;
+ mCached = null;
}
private void setIsBlocked(boolean isBlocked) {
mIsBlocked = isBlocked;
mWasIsBlockedSet = true;
+ mCached = null;
}
private boolean isValid() {
@@ -450,12 +725,30 @@
}
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/VcnContext.java b/services/core/java/com/android/server/vcn/VcnContext.java
index 7399e56..d958222 100644
--- a/services/core/java/com/android/server/vcn/VcnContext.java
+++ b/services/core/java/com/android/server/vcn/VcnContext.java
@@ -31,14 +31,17 @@
@NonNull private final Context mContext;
@NonNull private final Looper mLooper;
@NonNull private final VcnNetworkProvider mVcnNetworkProvider;
+ private final boolean mIsInTestMode;
public VcnContext(
@NonNull Context context,
@NonNull Looper looper,
- @NonNull VcnNetworkProvider vcnNetworkProvider) {
+ @NonNull VcnNetworkProvider vcnNetworkProvider,
+ boolean isInTestMode) {
mContext = Objects.requireNonNull(context, "Missing context");
mLooper = Objects.requireNonNull(looper, "Missing looper");
mVcnNetworkProvider = Objects.requireNonNull(vcnNetworkProvider, "Missing networkProvider");
+ mIsInTestMode = isInTestMode;
}
@NonNull
@@ -56,6 +59,10 @@
return mVcnNetworkProvider;
}
+ public boolean isInTestMode() {
+ return mIsInTestMode;
+ }
+
/**
* Verifies that the caller is running on the VcnContext Thread.
*
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 736a6f6..8e3cb25 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -91,7 +91,6 @@
import static android.os.UserManagerInternal.OWNER_TYPE_DEVICE_OWNER;
import static android.os.UserManagerInternal.OWNER_TYPE_PROFILE_OWNER;
import static android.os.UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE;
-import static android.provider.Settings.Global.PRIVATE_DNS_MODE;
import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER;
import static android.provider.Telephony.Carriers.DPC_URI;
import static android.provider.Telephony.Carriers.ENFORCE_KEY;
@@ -195,6 +194,7 @@
import android.media.AudioManager;
import android.media.IAudioService;
import android.net.ConnectivityManager;
+import android.net.ConnectivitySettingsManager;
import android.net.IIpConnectivityMetrics;
import android.net.ProxyInfo;
import android.net.Uri;
@@ -15566,12 +15566,12 @@
return context.getResources().getString(R.string.config_managed_provisioning_package);
}
- private void putPrivateDnsSettings(@Nullable String mode, @Nullable String host) {
+ private void putPrivateDnsSettings(int mode, @Nullable String host) {
// Set Private DNS settings using system permissions, as apps cannot write
// to global settings.
mInjector.binderWithCleanCallingIdentity(() -> {
- mInjector.settingsGlobalPutString(PRIVATE_DNS_MODE, mode);
- mInjector.settingsGlobalPutString(PRIVATE_DNS_SPECIFIER, host);
+ ConnectivitySettingsManager.setPrivateDnsMode(mContext, mode);
+ ConnectivitySettingsManager.setPrivateDnsHostname(mContext, host);
});
}
@@ -15592,7 +15592,8 @@
throw new IllegalArgumentException(
"Host provided for opportunistic mode, but is not needed.");
}
- putPrivateDnsSettings(ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC, null);
+ putPrivateDnsSettings(ConnectivitySettingsManager.PRIVATE_DNS_MODE_OPPORTUNISTIC,
+ null);
return PRIVATE_DNS_SET_NO_ERROR;
case PRIVATE_DNS_MODE_PROVIDER_HOSTNAME:
if (TextUtils.isEmpty(privateDnsHost)
@@ -15604,7 +15605,7 @@
// Connectivity check will have been performed in the DevicePolicyManager before
// the call here.
putPrivateDnsSettings(
- ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME,
+ ConnectivitySettingsManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME,
privateDnsHost);
return PRIVATE_DNS_SET_NO_ERROR;
default:
@@ -15621,13 +15622,13 @@
Objects.requireNonNull(who, "ComponentName is null");
enforceDeviceOwner(who);
- final String currentMode = ConnectivityManager.getPrivateDnsMode(mContext);
+ final int currentMode = ConnectivitySettingsManager.getPrivateDnsMode(mContext);
switch (currentMode) {
- case ConnectivityManager.PRIVATE_DNS_MODE_OFF:
+ case ConnectivitySettingsManager.PRIVATE_DNS_MODE_OFF:
return PRIVATE_DNS_MODE_OFF;
- case ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC:
+ case ConnectivitySettingsManager.PRIVATE_DNS_MODE_OPPORTUNISTIC:
return PRIVATE_DNS_MODE_OPPORTUNISTIC;
- case ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME:
+ case ConnectivitySettingsManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME:
return PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
}
diff --git a/services/net/TEST_MAPPING b/services/net/TEST_MAPPING
index 7025dd1..7eca1f9 100644
--- a/services/net/TEST_MAPPING
+++ b/services/net/TEST_MAPPING
@@ -2,6 +2,9 @@
"imports": [
{
"path": "frameworks/base/core/java/android/net"
+ },
+ {
+ "path": "packages/modules/Wifi/framework"
}
]
-}
\ No newline at end of file
+}
diff --git a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
index deaeb46..a1bce52 100644
--- a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
@@ -374,7 +374,7 @@
.setPersisted(true)
.setRequiredNetwork(new NetworkRequest.Builder()
.addCapability(NET_CAPABILITY_IMS)
- .addUnwantedCapability(NET_CAPABILITY_OEM_PAID)
+ .addForbiddenCapability(NET_CAPABILITY_OEM_PAID)
.build())
.build());
}
diff --git a/telecomm/java/android/telecom/CallerInfo.java b/telecomm/java/android/telecom/CallerInfo.java
index 2983e63..a63ee46 100644
--- a/telecomm/java/android/telecom/CallerInfo.java
+++ b/telecomm/java/android/telecom/CallerInfo.java
@@ -406,8 +406,7 @@
// Change the callerInfo number ONLY if it is an emergency number
// or if it is the voicemail number. If it is either, take a
// shortcut and skip the query.
- TelephonyManager tm = context.getSystemService(TelephonyManager.class);
- if (tm.isEmergencyNumber(number)) {
+ if (PhoneNumberUtils.isLocalEmergencyNumber(context, number)) {
return new CallerInfo().markAsEmergency(context);
} else if (PhoneNumberUtils.isVoiceMailNumber(null, subId, number)) {
return new CallerInfo().markAsVoiceMail(context, subId);
diff --git a/telecomm/java/android/telecom/CallerInfoAsyncQuery.java b/telecomm/java/android/telecom/CallerInfoAsyncQuery.java
index a9e1a8f..bf49f3c 100644
--- a/telecomm/java/android/telecom/CallerInfoAsyncQuery.java
+++ b/telecomm/java/android/telecom/CallerInfoAsyncQuery.java
@@ -483,7 +483,16 @@
// check to see if these are recognized numbers, and use shortcuts if we can.
TelephonyManager tm = context.getSystemService(TelephonyManager.class);
- if (tm.isEmergencyNumber(number)) {
+ boolean isEmergencyNumber = false;
+ try {
+ isEmergencyNumber = tm.isEmergencyNumber(number);
+ } catch (IllegalStateException ise) {
+ // Ignore the exception that Telephony is not up. Use PhoneNumberUtils API now.
+ // Ideally the PhoneNumberUtils API needs to be removed once the
+ // telphony service not up issue can be fixed (b/187412989)
+ isEmergencyNumber = PhoneNumberUtils.isLocalEmergencyNumber(context, number);
+ }
+ if (isEmergencyNumber) {
cw.event = EVENT_EMERGENCY_NUMBER;
} else if (PhoneNumberUtils.isVoiceMailNumber(context, subId, number)) {
cw.event = EVENT_VOICEMAIL_NUMBER;
diff --git a/telephony/java/android/telephony/ims/RcsConfig.java b/telephony/java/android/telephony/ims/RcsConfig.java
index 8a31211..6867c86 100644
--- a/telephony/java/android/telephony/ims/RcsConfig.java
+++ b/telephony/java/android/telephony/ims/RcsConfig.java
@@ -22,10 +22,10 @@
import android.content.Context;
import android.database.Cursor;
import android.os.Build;
-import android.os.Parcel;
-import android.os.Parcelable;
import android.provider.Telephony.SimInfo;
import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.ArraySet;
import com.android.telephony.Rlog;
@@ -36,7 +36,9 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
@@ -44,23 +46,138 @@
* RCS config data and methods to process the config
* @hide
*/
-public final class RcsConfig implements Parcelable {
+public final class RcsConfig {
private static final String LOG_TAG = "RcsConfig";
private static final boolean DBG = Build.IS_ENG;
- // Tag for Rcs Volte single registration defined in RCC.07 A.1.6.2
- private static final String TAG_SINGLE_REGISTRATION = "rcsVolteSingleRegistration";
+ // Tag and attribute defined in RCC.07 A.2
+ private static final String TAG_CHARACTERISTIC = "characteristic";
+ private static final String TAG_PARM = "parm";
+ private static final String ATTRIBUTE_TYPE = "type";
+ private static final String ATTRIBUTE_NAME = "name";
+ private static final String ATTRIBUTE_VALUE = "value";
+ // Keyword for Rcs Volte single registration defined in RCC.07 A.1.6.2
+ private static final String PARM_SINGLE_REGISTRATION = "rcsVolteSingleRegistration";
- private final HashMap<String, String> mValues = new HashMap<>();
+ /**
+ * Characteristic of the RCS provisioning config
+ */
+ public static class Characteristic {
+ private String mType;
+ private final Map<String, String> mParms = new ArrayMap<>();
+ private final Set<Characteristic> mSubs = new ArraySet<>();
+ private final Characteristic mParent;
- private RcsConfig(HashMap<String, String> values) {
- mValues.putAll(values);
+ private Characteristic(String type, Characteristic parent) {
+ mType = type;
+ mParent = parent;
+ }
+
+ private String getType() {
+ return mType;
+ }
+
+ private Map<String, String> getParms() {
+ return mParms;
+ }
+
+ private Set<Characteristic> getSubs() {
+ return mSubs;
+ }
+
+ private Characteristic getParent() {
+ return mParent;
+ }
+
+ private Characteristic getSubByType(String type) {
+ if (TextUtils.equals(mType, type)) {
+ return this;
+ }
+ Characteristic result = null;
+ for (Characteristic sub : mSubs) {
+ result = sub.getSubByType(type);
+ if (result != null) {
+ break;
+ }
+ }
+ return result;
+ }
+
+ private boolean hasSubByType(String type) {
+ return getSubByType(type) != null;
+ }
+
+ private String getParmValue(String name) {
+ String value = mParms.get(name);
+ if (value == null) {
+ for (Characteristic sub : mSubs) {
+ value = sub.getParmValue(name);
+ if (value != null) {
+ break;
+ }
+ }
+ }
+ return value;
+ }
+
+ boolean hasParm(String name) {
+ if (mParms.containsKey(name)) {
+ return true;
+ }
+
+ for (Characteristic sub : mSubs) {
+ if (sub.hasParm(name)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("[" + mType + "]: ");
+ if (DBG) {
+ sb.append(mParms);
+ }
+ for (Characteristic sub : mSubs) {
+ sb.append("\n");
+ sb.append(sub.toString().replace("\n", "\n\t"));
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof Characteristic)) {
+ return false;
+ }
+
+ Characteristic o = (Characteristic) obj;
+
+ return TextUtils.equals(mType, o.mType) && mParms.equals(o.mParms)
+ && mSubs.equals(o.mSubs);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mType, mParms, mSubs);
+ }
}
+ private final Characteristic mRoot;
+ private Characteristic mCurrent;
+ private final byte[] mData;
+
public RcsConfig(byte[] data) throws IllegalArgumentException {
if (data == null || data.length == 0) {
throw new IllegalArgumentException("Empty data");
}
+ mRoot = new Characteristic(null, null);
+ mCurrent = mRoot;
+ mData = data;
+ Characteristic current = mRoot;
ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
@@ -69,16 +186,51 @@
xpp.setInput(inputStream, null);
int eventType = xpp.getEventType();
String tag = null;
- while (eventType != XmlPullParser.END_DOCUMENT) {
+ while (eventType != XmlPullParser.END_DOCUMENT && current != null) {
if (eventType == XmlPullParser.START_TAG) {
- tag = xpp.getName().trim();
- } else if (eventType == XmlPullParser.END_TAG) {
- tag = null;
- } else if (eventType == XmlPullParser.TEXT) {
- String value = xpp.getText().trim();
- if (!TextUtils.isEmpty(tag) && !TextUtils.isEmpty(value)) {
- mValues.put(tag, value);
+ tag = xpp.getName().trim().toLowerCase();
+ if (TAG_CHARACTERISTIC.equals(tag)) {
+ int count = xpp.getAttributeCount();
+ String type = null;
+ if (count > 0) {
+ for (int i = 0; i < count; i++) {
+ String name = xpp.getAttributeName(i).trim().toLowerCase();
+ if (ATTRIBUTE_TYPE.equals(name)) {
+ type = xpp.getAttributeValue(xpp.getAttributeNamespace(i),
+ name).trim().toLowerCase();
+ break;
+ }
+ }
+ }
+ Characteristic next = new Characteristic(type, current);
+ current.getSubs().add(next);
+ current = next;
+ } else if (TAG_PARM.equals(tag)) {
+ int count = xpp.getAttributeCount();
+ String key = null;
+ String value = null;
+ if (count > 1) {
+ for (int i = 0; i < count; i++) {
+ String name = xpp.getAttributeName(i).trim().toLowerCase();
+ if (ATTRIBUTE_NAME.equals(name)) {
+ key = xpp.getAttributeValue(xpp.getAttributeNamespace(i),
+ name).trim().toLowerCase();
+ } else if (ATTRIBUTE_VALUE.equals(name)) {
+ value = xpp.getAttributeValue(xpp.getAttributeNamespace(i),
+ name).trim();
+ }
+ }
+ }
+ if (key != null && value != null) {
+ current.getParms().put(key, value);
+ }
}
+ } else if (eventType == XmlPullParser.END_TAG) {
+ tag = xpp.getName().trim().toLowerCase();
+ if (TAG_CHARACTERISTIC.equals(tag)) {
+ current = current.getParent();
+ }
+ tag = null;
}
eventType = xpp.next();
}
@@ -102,7 +254,8 @@
* @return Returns the config value if it exists, or defaultVal.
*/
public @Nullable String getString(@NonNull String tag, @Nullable String defaultVal) {
- return mValues.containsKey(tag) ? mValues.get(tag) : defaultVal;
+ String value = mCurrent.getParmValue(tag.trim().toLowerCase());
+ return value != null ? value : defaultVal;
}
/**
@@ -115,7 +268,7 @@
*/
public int getInteger(@NonNull String tag, int defaultVal) {
try {
- return Integer.parseInt(mValues.get(tag));
+ return Integer.parseInt(getString(tag, null));
} catch (NumberFormatException e) {
logd("error to getInteger for " + tag + " due to " + e);
}
@@ -131,10 +284,8 @@
* @return Returns the config value if it exists, or defaultVal.
*/
public boolean getBoolean(@NonNull String tag, boolean defaultVal) {
- if (!mValues.containsKey(tag)) {
- return defaultVal;
- }
- return Boolean.parseBoolean(mValues.get(tag));
+ String value = getString(tag, null);
+ return value != null ? Boolean.parseBoolean(value) : defaultVal;
}
/**
@@ -145,15 +296,70 @@
* @return Returns true if it exists, or false.
*/
public boolean hasConfig(@NonNull String tag) {
- return mValues.containsKey(tag);
+ return mCurrent.hasParm(tag.trim().toLowerCase());
+ }
+
+ /**
+ * Return the Characteristic with the given type
+ */
+ public @Nullable Characteristic getCharacteristic(@NonNull String type) {
+ return mCurrent.getSubByType(type.trim().toLowerCase());
+ }
+
+ /**
+ * Check whether the Characteristic with the given type exists
+ */
+ public boolean hasCharacteristic(@NonNull String type) {
+ return mCurrent.getSubByType(type.trim().toLowerCase()) != null;
+ }
+
+ /**
+ * Set current Characteristic to given Characteristic
+ */
+ public void setCurrentCharacteristic(@NonNull Characteristic current) {
+ if (current != null) {
+ mCurrent = current;
+ }
+ }
+
+ /**
+ * Move current Characteristic to parent layer
+ */
+ public boolean moveToParent() {
+ if (mCurrent.getParent() == null) {
+ return false;
+ }
+ mCurrent = mCurrent.getParent();
+ return true;
+ }
+
+ /**
+ * Move current Characteristic to the root
+ */
+ public void moveToRoot() {
+ mCurrent = mRoot;
+ }
+
+ /**
+ * Return root Characteristic
+ */
+ public @NonNull Characteristic getRoot() {
+ return mRoot;
+ }
+
+ /**
+ * Return current Characteristic
+ */
+ public @NonNull Characteristic getCurrentCharacteristic() {
+ return mCurrent;
}
/**
* Check whether Rcs Volte single registration is supported by the config.
*/
public boolean isRcsVolteSingleRegistrationSupported() {
- return getBoolean(TAG_SINGLE_REGISTRATION, false)
- || getInteger(TAG_SINGLE_REGISTRATION, 0) != 0;
+ return getBoolean(PARM_SINGLE_REGISTRATION, false)
+ || getInteger(PARM_SINGLE_REGISTRATION, 0) != 0;
}
@Override
@@ -161,12 +367,10 @@
final StringBuilder sb = new StringBuilder();
sb.append("[RCS Config]");
if (DBG) {
- mValues.forEach((t, v) -> {
- sb.append("\n");
- sb.append(t);
- sb.append(" : ");
- sb.append(v);
- });
+ sb.append("=== Root ===\n");
+ sb.append(mRoot);
+ sb.append("=== Current ===\n");
+ sb.append(mCurrent);
}
return sb.toString();
}
@@ -179,12 +383,12 @@
RcsConfig other = (RcsConfig) obj;
- return mValues.equals(other.mValues);
+ return mRoot.equals(other.mRoot) && mCurrent.equals(other.mCurrent);
}
@Override
public int hashCode() {
- return mValues.hashCode();
+ return Objects.hash(mRoot, mCurrent);
}
/**
@@ -275,38 +479,6 @@
return isCompressed ? data : decompressGzip(data);
}
- /**
- * {@link Parcelable#writeToParcel}
- */
- public void writeToParcel(@NonNull Parcel out, int flags) {
- out.writeMap(mValues);
- }
-
- /**
- * {@link Parcelable.Creator}
- *
- */
- public static final @NonNull Parcelable.Creator<RcsConfig>
- CREATOR = new Creator<RcsConfig>() {
- @Override
- public RcsConfig createFromParcel(Parcel in) {
- HashMap<String, String> values = in.readHashMap(null);
- return values == null ? null : new RcsConfig(values);
- }
-
- @Override
- public RcsConfig[] newArray(int size) {
- return new RcsConfig[size];
- }
- };
-
- /**
- * {@link Parcelable#describeContents}
- */
- public int describeContents() {
- return 0;
- }
-
private static void logd(String msg) {
Rlog.d(LOG_TAG, msg);
}
diff --git a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
index 9410886..c59dcf8 100644
--- a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
@@ -16,13 +16,17 @@
package android.net.vcn;
+import static android.net.ipsec.ike.IkeSessionParams.IKE_OPTION_MOBIKE;
+
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import android.net.NetworkCapabilities;
+import android.net.ipsec.ike.IkeSessionParams;
import android.net.ipsec.ike.IkeTunnelConnectionParams;
+import android.net.vcn.persistablebundleutils.IkeSessionParamsUtilsTest;
import android.net.vcn.persistablebundleutils.TunnelConnectionParamsUtilsTest;
import androidx.test.filters.SmallTest;
@@ -120,6 +124,21 @@
}
@Test
+ public void testBuilderRequiresMobikeEnabled() {
+ try {
+ final IkeSessionParams ikeParams =
+ IkeSessionParamsUtilsTest.createBuilderMinimum()
+ .removeIkeOption(IKE_OPTION_MOBIKE)
+ .build();
+ final IkeTunnelConnectionParams tunnelParams =
+ TunnelConnectionParamsUtilsTest.buildTestParams(ikeParams);
+ new VcnGatewayConnectionConfig.Builder(GATEWAY_CONNECTION_NAME_PREFIX, tunnelParams);
+ fail("Expected exception due to MOBIKE not enabled");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ @Test
public void testBuilderRequiresNonEmptyExposedCaps() {
try {
newBuilder()
diff --git a/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java b/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java
index 582275d..abae81c 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 @@
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 @@
}
@Test
- public void testMakeCopySetsRedactions() {
+ public void testMakeCopyRedactForAccessFineLocation() {
assertEquals(
- REDACT_FOR_NETWORK_SETTINGS,
- ((VcnTransportInfo) CELL_UNDERLYING_INFO.makeCopy(REDACT_FOR_NETWORK_SETTINGS))
- .getRedaction());
- 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 @@
}
@Test
- public void testParcelUnparcel() {
- verifyParcelingIsNull(CELL_UNDERLYING_INFO);
- verifyParcelingIsNull(WIFI_UNDERLYING_INFO);
- }
+ public void testApplicableRedactions() {
+ assertEquals(REDACT_NONE, CELL_UNDERLYING_INFO.getApplicableRedactions());
- private void verifyParcelingIsNull(VcnTransportInfo vcnTransportInfo) {
- // Verify redacted by default
- Parcel parcel = Parcel.obtain();
- vcnTransportInfo.writeToParcel(parcel, 0 /* flags */);
- parcel.setDataPosition(0);
-
- 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/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java b/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java
index 393787f..f385113 100644
--- a/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java
+++ b/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java
@@ -52,8 +52,8 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
public class IkeSessionParamsUtilsTest {
- // Package private for use in EncryptedTunnelParamsUtilsTest
- static IkeSessionParams.Builder createBuilderMinimum() {
+ // Public for use in VcnGatewayConnectionConfigTest, EncryptedTunnelParamsUtilsTest
+ public static IkeSessionParams.Builder createBuilderMinimum() {
final InetAddress serverAddress = InetAddresses.parseNumericAddress("192.0.2.100");
// TODO: b/185941731 Make sure all valid IKE_OPTIONS are added and validated.
@@ -63,6 +63,7 @@
.setLocalIdentification(new IkeFqdnIdentification("client.test.android.net"))
.setRemoteIdentification(new IkeFqdnIdentification("server.test.android.net"))
.addIkeOption(IkeSessionParams.IKE_OPTION_FORCE_PORT_4500)
+ .addIkeOption(IkeSessionParams.IKE_OPTION_MOBIKE)
.setAuthPsk("psk".getBytes());
}
diff --git a/tests/vcn/java/android/net/vcn/persistablebundleutils/TunnelConnectionParamsUtilsTest.java b/tests/vcn/java/android/net/vcn/persistablebundleutils/TunnelConnectionParamsUtilsTest.java
index 0c8ad32..f9dc9eb 100644
--- a/tests/vcn/java/android/net/vcn/persistablebundleutils/TunnelConnectionParamsUtilsTest.java
+++ b/tests/vcn/java/android/net/vcn/persistablebundleutils/TunnelConnectionParamsUtilsTest.java
@@ -18,6 +18,7 @@
import static org.junit.Assert.assertEquals;
+import android.net.ipsec.ike.IkeSessionParams;
import android.net.ipsec.ike.IkeTunnelConnectionParams;
import androidx.test.filters.SmallTest;
@@ -31,9 +32,13 @@
public class TunnelConnectionParamsUtilsTest {
// Public for use in VcnGatewayConnectionConfigTest
public static IkeTunnelConnectionParams buildTestParams() {
+ return buildTestParams(IkeSessionParamsUtilsTest.createBuilderMinimum().build());
+ }
+
+ // Public for use in VcnGatewayConnectionConfigTest
+ public static IkeTunnelConnectionParams buildTestParams(IkeSessionParams params) {
return new IkeTunnelConnectionParams(
- IkeSessionParamsUtilsTest.createBuilderMinimum().build(),
- TunnelModeChildSessionParamsUtilsTest.createBuilderMinimum().build());
+ params, TunnelModeChildSessionParamsUtilsTest.createBuilderMinimum().build());
}
@Test
diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
index 9ecd82f..3360d40 100644
--- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
+++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
@@ -37,6 +37,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.CALLS_REAL_METHODS;
@@ -66,6 +67,7 @@
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
import android.net.vcn.VcnConfig;
import android.net.vcn.VcnConfigTest;
+import android.net.vcn.VcnGatewayConnectionConfigTest;
import android.net.vcn.VcnManager;
import android.net.vcn.VcnUnderlyingNetworkPolicy;
import android.os.IBinder;
@@ -197,7 +199,8 @@
.newVcnContext(
eq(mMockContext),
eq(mTestLooper.getLooper()),
- any(VcnNetworkProvider.class));
+ any(VcnNetworkProvider.class),
+ anyBoolean());
doReturn(mSubscriptionTracker)
.when(mMockDeps)
.newTelephonySubscriptionTracker(
@@ -371,6 +374,12 @@
TelephonySubscriptionSnapshot snapshot =
triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_1));
verify(mMockDeps)
+ .newVcnContext(
+ eq(mMockContext),
+ eq(mTestLooper.getLooper()),
+ any(VcnNetworkProvider.class),
+ anyBoolean());
+ verify(mMockDeps)
.newVcn(eq(mVcnContext), eq(TEST_UUID_1), eq(TEST_VCN_CONFIG), eq(snapshot), any());
}
@@ -528,6 +537,28 @@
}
@Test
+ public void testSetVcnConfigTestModeRequiresPermission() throws Exception {
+ doThrow(new SecurityException("Requires MANAGE_TEST_NETWORKS"))
+ .when(mMockContext)
+ .enforceCallingPermission(
+ eq(android.Manifest.permission.MANAGE_TEST_NETWORKS), any());
+
+ final VcnConfig vcnConfig =
+ new VcnConfig.Builder(mMockContext)
+ .addGatewayConnectionConfig(
+ VcnGatewayConnectionConfigTest.buildTestConfig())
+ .setIsTestModeProfile()
+ .build();
+
+ try {
+ mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, vcnConfig, TEST_PACKAGE_NAME);
+ fail("Expected exception due to using test-mode without permission");
+ } catch (SecurityException e) {
+ verify(mMockPolicyListener, never()).onPolicyChanged();
+ }
+ }
+
+ @Test
public void testSetVcnConfigNotifiesStatusCallback() throws Exception {
triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_2));
diff --git a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
index 528f240..ca74638 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 @@
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 @@
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 @@
@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 @@
@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 8289e85..a36fd79 100644
--- a/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java
+++ b/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java
@@ -26,6 +26,7 @@
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -41,12 +42,14 @@
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;
@@ -97,11 +100,13 @@
@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;
@@ -112,14 +117,27 @@
MockitoAnnotations.initMocks(this);
mTestLooper = new TestLooper();
- mVcnContext = spy(new VcnContext(mContext, mTestLooper.getLooper(), mVcnNetworkProvider));
- doNothing().when(mVcnContext).ensureRunningOnLooperThread();
+ mVcnContext =
+ spy(
+ new VcnContext(
+ mContext,
+ mTestLooper.getLooper(),
+ mVcnNetworkProvider,
+ false /* isInTestMode */));
+ resetVcnContext();
setupSystemService(
mContext,
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);
@@ -132,6 +150,11 @@
mNetworkTrackerCb);
}
+ private void resetVcnContext() {
+ reset(mVcnContext);
+ doNothing().when(mVcnContext).ensureRunningOnLooperThread();
+ }
+
private static LinkProperties getLinkPropertiesWithName(String iface) {
LinkProperties linkProperties = new LinkProperties();
linkProperties.setInterfaceName(iface);
@@ -149,6 +172,31 @@
verifyNetworkRequestsRegistered(INITIAL_SUB_IDS);
}
+ @Test
+ public void testNetworkCallbacksRegisteredOnStartupForTestMode() {
+ final ConnectivityManager cm = mock(ConnectivityManager.class);
+ setupSystemService(mContext, cm, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class);
+ final VcnContext vcnContext =
+ new VcnContext(
+ mContext,
+ mTestLooper.getLooper(),
+ mVcnNetworkProvider,
+ true /* isInTestMode */);
+
+ new UnderlyingNetworkTracker(
+ vcnContext,
+ SUB_GROUP,
+ mSubscriptionSnapshot,
+ Collections.singleton(NetworkCapabilities.NET_CAPABILITY_INTERNET),
+ mNetworkTrackerCb);
+
+ verify(cm)
+ .registerNetworkCallback(
+ eq(getTestNetworkRequest(INITIAL_SUB_IDS)),
+ any(UnderlyingNetworkListener.class),
+ any());
+ }
+
private void verifyNetworkRequestsRegistered(Set<Integer> expectedSubIds) {
verify(mConnectivityManager)
.requestBackgroundNetwork(
@@ -163,9 +211,20 @@
}
verify(mConnectivityManager)
- .requestBackgroundNetwork(
+ .registerNetworkCallback(
eq(getRouteSelectionRequest(expectedSubIds)),
- any(RouteSelectionCallback.class), any());
+ any(UnderlyingNetworkListener.class),
+ any());
+ verify(mConnectivityManager)
+ .registerNetworkCallback(
+ eq(getWifiEntryRssiThresholdRequest(expectedSubIds)),
+ any(NetworkBringupCallback.class),
+ any());
+ verify(mConnectivityManager)
+ .registerNetworkCallback(
+ eq(getWifiExitRssiThresholdRequest(expectedSubIds)),
+ any(NetworkBringupCallback.class),
+ any());
}
@Test
@@ -180,9 +239,10 @@
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);
}
@@ -193,6 +253,24 @@
.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)
@@ -201,7 +279,19 @@
}
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) {
+ return new NetworkRequest.Builder()
+ .clearCapabilities()
+ .addTransportType(NetworkCapabilities.TRANSPORT_TEST)
+ .setSubscriptionIds(netCapsSubIds)
+ .build();
}
private NetworkRequest.Builder getExpectedRequestBase() {
@@ -219,11 +309,12 @@
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
@@ -256,19 +347,19 @@
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);
@@ -286,7 +377,7 @@
@Test
public void testRecordTrackerCallbackNotifiedForNetworkCapabilitiesChange() {
- RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback();
+ UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
cb.onCapabilitiesChanged(mNetwork, UPDATED_NETWORK_CAPABILITIES);
@@ -301,7 +392,7 @@
@Test
public void testRecordTrackerCallbackNotifiedForLinkPropertiesChange() {
- RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback();
+ UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
cb.onLinkPropertiesChanged(mNetwork, UPDATED_LINK_PROPERTIES);
@@ -316,7 +407,7 @@
@Test
public void testRecordTrackerCallbackNotifiedForNetworkSuspended() {
- RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback();
+ UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
cb.onCapabilitiesChanged(mNetwork, SUSPENDED_NETWORK_CAPABILITIES);
@@ -335,7 +426,7 @@
@Test
public void testRecordTrackerCallbackNotifiedForNetworkResumed() {
- RouteSelectionCallback cb =
+ UnderlyingNetworkListener cb =
verifyRegistrationOnAvailableAndGetCallback(SUSPENDED_NETWORK_CAPABILITIES);
cb.onCapabilitiesChanged(mNetwork, INITIAL_NETWORK_CAPABILITIES);
@@ -355,7 +446,7 @@
@Test
public void testRecordTrackerCallbackNotifiedForBlocked() {
- RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback();
+ UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
cb.onBlockedStatusChanged(mNetwork, true /* isBlocked */);
@@ -370,7 +461,7 @@
@Test
public void testRecordTrackerCallbackNotifiedForNetworkLoss() {
- RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback();
+ UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
cb.onLost(mNetwork);
@@ -379,7 +470,7 @@
@Test
public void testRecordTrackerCallbackIgnoresDuplicateRecord() {
- RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback();
+ UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
cb.onCapabilitiesChanged(mNetwork, INITIAL_NETWORK_CAPABILITIES);
@@ -387,4 +478,6 @@
// 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 1ecb4c9..c747bc0 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.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 @@
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 @@
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;
diff --git a/tools/aapt/pseudolocalize.cpp b/tools/aapt/pseudolocalize.cpp
index 5c47e0f..4e8dcb1 100644
--- a/tools/aapt/pseudolocalize.cpp
+++ b/tools/aapt/pseudolocalize.cpp
@@ -194,7 +194,8 @@
break;
}
}
- result.remove(length + ext, 0);
+ // Just keep the first length + ext characters
+ result = String16(result, length + ext);
}
return result;
}