summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmds/idmap2/OWNERS3
-rw-r--r--core/api/module-lib-current.txt4
-rw-r--r--core/java/android/app/RESOURCES_OWNERS1
-rw-r--r--core/java/android/app/usage/NetworkStatsManager.java20
-rw-r--r--core/java/android/content/pm/parsing/result/ParseTypeImpl.java1
-rw-r--r--core/java/android/net/INetworkStatsService.aidl4
-rw-r--r--core/java/android/net/NetworkIdentity.java32
-rw-r--r--core/java/android/net/NetworkTemplate.java24
-rw-r--r--core/java/android/net/UnderlyingNetworkInfo.java8
-rw-r--r--core/java/android/net/vcn/OWNERS2
-rw-r--r--core/java/android/net/vcn/VcnGatewayConnectionConfig.java93
-rw-r--r--core/java/android/net/vcn/VcnManager.java30
-rw-r--r--core/java/android/net/vcn/VcnTransportInfo.java76
-rw-r--r--core/java/android/os/OWNERS3
-rw-r--r--core/java/android/os/incremental/OWNERS1
-rw-r--r--core/java/com/android/internal/app/procstats/OWNERS1
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java22
-rw-r--r--core/java/com/android/internal/os/BinderCallsStats.java96
-rw-r--r--core/java/com/android/internal/os/BinderInternal.java11
-rw-r--r--core/java/com/android/internal/os/BinderLatencyBuckets.java30
-rw-r--r--core/java/com/android/internal/os/WrapperInit.java12
-rw-r--r--core/java/com/android/internal/os/ZygoteInit.java8
-rw-r--r--core/java/com/android/server/OWNERS2
-rw-r--r--core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp4
-rw-r--r--core/proto/OWNERS5
-rw-r--r--core/res/OWNERS4
-rw-r--r--core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java72
-rw-r--r--core/tests/coretests/src/com/android/internal/os/BinderLatencyBucketsTest.java2
-rw-r--r--core/tests/utiltests/src/com/android/internal/util/FileRotatorTest.java9
-rw-r--r--data/etc/OWNERS1
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java4
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java16
-rw-r--r--keystore/tests/Android.bp1
-rw-r--r--keystore/tests/src/android/security/ParcelableKeyGenParameterSpecTest.java10
-rw-r--r--keystore/tests/src/android/security/keystore/KeyGenParameterSpecTest.java4
-rw-r--r--keystore/tests/src/android/security/keystore2/AndroidKeyStoreSpiTest.java55
-rw-r--r--libs/androidfw/OWNERS1
-rw-r--r--packages/Connectivity/framework/api/module-lib-current.txt4
-rw-r--r--packages/Connectivity/framework/api/system-current.txt4
-rw-r--r--packages/Connectivity/framework/src/android/net/ConnectivityManager.java53
-rw-r--r--packages/Connectivity/framework/src/android/net/ConnectivitySettingsManager.java32
-rw-r--r--packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl5
-rw-r--r--packages/Connectivity/framework/src/android/net/INetworkOfferCallback.aidl62
-rw-r--r--packages/Connectivity/framework/src/android/net/NetworkCapabilities.java48
-rw-r--r--packages/Connectivity/framework/src/android/net/NetworkProvider.java153
-rw-r--r--packages/Connectivity/framework/src/android/net/NetworkRequest.java19
-rw-r--r--packages/Connectivity/framework/src/android/net/QosFilter.java11
-rw-r--r--packages/Connectivity/framework/src/android/net/QosSocketFilter.java19
-rw-r--r--packages/Connectivity/framework/src/android/net/QosSocketInfo.java50
-rw-r--r--packages/Connectivity/service/Android.bp2
-rw-r--r--packages/Connectivity/service/src/com/android/server/ConnectivityService.java (renamed from services/core/java/com/android/server/ConnectivityService.java)137
-rw-r--r--packages/Connectivity/service/src/com/android/server/ConnectivityServiceInitializer.java (renamed from services/core/java/com/android/server/ConnectivityServiceInitializer.java)0
-rw-r--r--packages/Connectivity/service/src/com/android/server/NetIdManager.java (renamed from services/core/java/com/android/server/NetIdManager.java)0
-rw-r--r--packages/Connectivity/service/src/com/android/server/TestNetworkService.java (renamed from services/core/java/com/android/server/TestNetworkService.java)0
-rw-r--r--packages/Connectivity/service/src/com/android/server/connectivity/AutodestructReference.java (renamed from services/core/java/com/android/server/connectivity/AutodestructReference.java)0
-rw-r--r--packages/Connectivity/service/src/com/android/server/connectivity/ConnectivityConstants.java (renamed from services/core/java/com/android/server/connectivity/ConnectivityConstants.java)0
-rw-r--r--packages/Connectivity/service/src/com/android/server/connectivity/DnsManager.java (renamed from services/core/java/com/android/server/connectivity/DnsManager.java)0
-rw-r--r--packages/Connectivity/service/src/com/android/server/connectivity/FullScore.java (renamed from services/core/java/com/android/server/connectivity/FullScore.java)28
-rw-r--r--packages/Connectivity/service/src/com/android/server/connectivity/KeepaliveTracker.java (renamed from services/core/java/com/android/server/connectivity/KeepaliveTracker.java)0
-rw-r--r--packages/Connectivity/service/src/com/android/server/connectivity/LingerMonitor.java (renamed from services/core/java/com/android/server/connectivity/LingerMonitor.java)0
-rw-r--r--packages/Connectivity/service/src/com/android/server/connectivity/MockableSystemProperties.java (renamed from services/core/java/com/android/server/connectivity/MockableSystemProperties.java)0
-rw-r--r--packages/Connectivity/service/src/com/android/server/connectivity/Nat464Xlat.java (renamed from services/core/java/com/android/server/connectivity/Nat464Xlat.java)0
-rw-r--r--packages/Connectivity/service/src/com/android/server/connectivity/NetworkAgentInfo.java (renamed from services/core/java/com/android/server/connectivity/NetworkAgentInfo.java)0
-rw-r--r--packages/Connectivity/service/src/com/android/server/connectivity/NetworkDiagnostics.java (renamed from services/core/java/com/android/server/connectivity/NetworkDiagnostics.java)0
-rw-r--r--packages/Connectivity/service/src/com/android/server/connectivity/NetworkNotificationManager.java (renamed from services/core/java/com/android/server/connectivity/NetworkNotificationManager.java)0
-rw-r--r--packages/Connectivity/service/src/com/android/server/connectivity/NetworkOffer.java94
-rw-r--r--packages/Connectivity/service/src/com/android/server/connectivity/NetworkRanker.java (renamed from services/core/java/com/android/server/connectivity/NetworkRanker.java)0
-rw-r--r--packages/Connectivity/service/src/com/android/server/connectivity/PermissionMonitor.java (renamed from services/core/java/com/android/server/connectivity/PermissionMonitor.java)156
-rw-r--r--packages/Connectivity/service/src/com/android/server/connectivity/ProfileNetworkPreferences.java (renamed from services/core/java/com/android/server/connectivity/ProfileNetworkPreferences.java)0
-rw-r--r--packages/Connectivity/service/src/com/android/server/connectivity/ProxyTracker.java (renamed from services/core/java/com/android/server/connectivity/ProxyTracker.java)0
-rw-r--r--packages/Connectivity/service/src/com/android/server/connectivity/QosCallbackAgentConnection.java (renamed from services/core/java/com/android/server/connectivity/QosCallbackAgentConnection.java)0
-rw-r--r--packages/Connectivity/service/src/com/android/server/connectivity/QosCallbackTracker.java (renamed from services/core/java/com/android/server/connectivity/QosCallbackTracker.java)0
-rw-r--r--packages/Connectivity/service/src/com/android/server/connectivity/TcpKeepaliveController.java (renamed from services/core/java/com/android/server/connectivity/TcpKeepaliveController.java)0
-rw-r--r--packages/Connectivity/tests/common/java/android/net/NetworkCapabilitiesTest.java2
-rw-r--r--packages/Connectivity/tests/common/java/android/net/UnderlyingNetworkInfoTest.kt12
-rw-r--r--packages/Connectivity/tests/unit/java/android/net/NetworkTemplateTest.kt58
-rw-r--r--packages/Connectivity/tests/unit/java/android/net/QosSocketFilterTest.java10
-rw-r--r--packages/Connectivity/tests/unit/java/com/android/server/ConnectivityServiceTest.java212
-rw-r--r--packages/Connectivity/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java200
-rw-r--r--packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java5
-rw-r--r--packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java140
-rw-r--r--packages/CtsShim/OWNERS3
-rw-r--r--packages/PackageInstaller/OWNERS1
-rw-r--r--packages/SettingsProvider/OWNERS1
-rw-r--r--packages/Shell/AndroidManifest.xml3
-rw-r--r--packages/Shell/OWNERS1
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipBuilder.kt2
-rw-r--r--services/OWNERS2
-rw-r--r--services/core/Android.bp27
-rw-r--r--services/core/java/android/os/BatteryStatsInternal.java10
-rw-r--r--services/core/java/com/android/server/BinderCallsStatsService.java12
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java6
-rw-r--r--services/core/java/com/android/server/am/BatteryStatsService.java9
-rw-r--r--services/core/java/com/android/server/am/OWNERS1
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsFactory.java4
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsService.java36
-rw-r--r--services/core/java/com/android/server/os/OWNERS2
-rw-r--r--services/core/java/com/android/server/pm/BackgroundDexOptService.java45
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java2
-rw-r--r--services/core/java/com/android/server/vcn/OWNERS2
-rw-r--r--services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java38
-rw-r--r--services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java453
-rw-r--r--services/core/java/com/android/server/vcn/VcnGatewayConnection.java3
-rw-r--r--services/incremental/OWNERS1
-rw-r--r--services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java4
-rw-r--r--tests/BackgroundDexOptServiceIntegrationTests/OWNERS1
-rw-r--r--tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java35
-rw-r--r--tests/utils/testutils/java/com/android/internal/util/test/FsUtil.java40
-rw-r--r--tests/vcn/OWNERS2
-rw-r--r--tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java12
-rw-r--r--tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java62
-rw-r--r--tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java20
-rw-r--r--tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java130
-rw-r--r--tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java11
-rw-r--r--tools/aapt/pseudolocalize.cpp3
-rw-r--r--tools/aapt2/OWNERS3
-rwxr-xr-xtools/aosp/aosp_sha.sh16
-rw-r--r--tools/codegen/src/com/android/codegen/Utils.kt4
119 files changed, 2389 insertions, 808 deletions
diff --git a/cmds/idmap2/OWNERS b/cmds/idmap2/OWNERS
index f1903a5a54a7..69dfcc98340d 100644
--- a/cmds/idmap2/OWNERS
+++ b/cmds/idmap2/OWNERS
@@ -1,3 +1,4 @@
set noparent
toddke@google.com
-rtmitchell@google.com \ No newline at end of file
+rtmitchell@google.com
+patb@google.com \ No newline at end of file
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 848f480c79a1..5d23eb20a81a 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -89,9 +89,9 @@ package android.net {
public final class UnderlyingNetworkInfo implements android.os.Parcelable {
ctor public UnderlyingNetworkInfo(int, @NonNull String, @NonNull java.util.List<java.lang.String>);
method public int describeContents();
- method @NonNull public String getIface();
+ method @NonNull public String getInterface();
method public int getOwnerUid();
- method @NonNull public java.util.List<java.lang.String> getUnderlyingIfaces();
+ method @NonNull public java.util.List<java.lang.String> getUnderlyingInterfaces();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.UnderlyingNetworkInfo> CREATOR;
}
diff --git a/core/java/android/app/RESOURCES_OWNERS b/core/java/android/app/RESOURCES_OWNERS
index 21c39a8828ad..558280396348 100644
--- a/core/java/android/app/RESOURCES_OWNERS
+++ b/core/java/android/app/RESOURCES_OWNERS
@@ -1,2 +1,3 @@
rtmitchell@google.com
toddke@google.com
+patb@google.com
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 9f1132b605ef..fe99f8532aaa 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -644,7 +644,10 @@ public class NetworkStatsManager {
: NetworkTemplate.buildTemplateMobileAll(subscriberId);
break;
case ConnectivityManager.TYPE_WIFI:
- template = NetworkTemplate.buildTemplateWifiWildcard();
+ template = subscriberId == null
+ ? NetworkTemplate.buildTemplateWifiWildcard()
+ : NetworkTemplate.buildTemplateWifi(NetworkTemplate.WIFI_NETWORKID_ALL,
+ subscriberId);
break;
default:
throw new IllegalArgumentException("Cannot create template for network type "
@@ -655,14 +658,14 @@ public class NetworkStatsManager {
}
/**
- * Notify {@code NetworkStatsService} about network status changed.
+ * Notify {@code NetworkStatsService} about network status changed.
*
- * Notifies NetworkStatsService of network state changes for data usage accounting purposes.
+ * Notifies NetworkStatsService of network state changes for data usage accounting purposes.
*
- * To avoid races that attribute data usage to wrong network, such as new network with
- * the same interface after SIM hot-swap, this function will not return until
- * {@code NetworkStatsService} finishes its work of retrieving traffic statistics from
- * all data sources.
+ * To avoid races that attribute data usage to wrong network, such as new network with
+ * the same interface after SIM hot-swap, this function will not return until
+ * {@code NetworkStatsService} finishes its work of retrieving traffic statistics from
+ * all data sources.
*
* @param defaultNetworks the list of all networks that could be used by network traffic that
* does not explicitly select a network.
@@ -689,8 +692,7 @@ public class NetworkStatsManager {
Objects.requireNonNull(defaultNetworks);
Objects.requireNonNull(networkStateSnapshots);
Objects.requireNonNull(underlyingNetworkInfos);
- // TODO: Change internal namings after the name is decided.
- mService.forceUpdateIfaces(defaultNetworks.toArray(new Network[0]),
+ mService.notifyNetworkStatus(defaultNetworks.toArray(new Network[0]),
networkStateSnapshots.toArray(new NetworkStateSnapshot[0]), activeIface,
underlyingNetworkInfos.toArray(new UnderlyingNetworkInfo[0]));
} catch (RemoteException e) {
diff --git a/core/java/android/content/pm/parsing/result/ParseTypeImpl.java b/core/java/android/content/pm/parsing/result/ParseTypeImpl.java
index 14992fb2a4d1..3740ef7d5a92 100644
--- a/core/java/android/content/pm/parsing/result/ParseTypeImpl.java
+++ b/core/java/android/content/pm/parsing/result/ParseTypeImpl.java
@@ -119,6 +119,7 @@ public class ParseTypeImpl implements ParseInput, ParseResult<Object> {
// how many APKs they're going through.
mDeferredErrors.erase();
}
+ mTargetSdkVersion = null;
return this;
}
diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl
index dc3b88a7c3be..12937b5cb2c7 100644
--- a/core/java/android/net/INetworkStatsService.aidl
+++ b/core/java/android/net/INetworkStatsService.aidl
@@ -65,8 +65,8 @@ interface INetworkStatsService {
/** Increment data layer count of operations performed for UID and tag. */
void incrementOperationCount(int uid, int tag, int operationCount);
- /** Force update of ifaces. */
- void forceUpdateIfaces(
+ /** Notify {@code NetworkStatsService} about network status changed. */
+ void notifyNetworkStatus(
in Network[] defaultNetworks,
in NetworkStateSnapshot[] snapshots,
in String activeIface,
diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java
index 3bde6fa6913d..1d07a0330bc5 100644
--- a/core/java/android/net/NetworkIdentity.java
+++ b/core/java/android/net/NetworkIdentity.java
@@ -26,8 +26,10 @@ import android.service.NetworkIdentityProto;
import android.telephony.Annotation.NetworkType;
import android.util.proto.ProtoOutputStream;
+import com.android.net.module.util.NetworkCapabilitiesUtils;
import com.android.net.module.util.NetworkIdentityUtils;
+import java.util.ArrayList;
import java.util.Objects;
/**
@@ -121,11 +123,37 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> {
}
builder.append(", metered=").append(mMetered);
builder.append(", defaultNetwork=").append(mDefaultNetwork);
- // TODO(180557699): Print a human readable string for OEM managed state.
- builder.append(", oemManaged=").append(mOemManaged);
+ builder.append(", oemManaged=").append(getOemManagedNames(mOemManaged));
return builder.append("}").toString();
}
+ /**
+ * Get the human readable representation of a bitfield representing the OEM managed state of a
+ * network.
+ */
+ static String getOemManagedNames(int oemManaged) {
+ if (oemManaged == OEM_NONE) {
+ return "OEM_NONE";
+ }
+ final int[] bitPositions = NetworkCapabilitiesUtils.unpackBits(oemManaged);
+ final ArrayList<String> oemManagedNames = new ArrayList<String>();
+ for (int position : bitPositions) {
+ oemManagedNames.add(nameOfOemManaged(1 << position));
+ }
+ return String.join(",", oemManagedNames);
+ }
+
+ private static String nameOfOemManaged(int oemManagedBit) {
+ switch (oemManagedBit) {
+ case OEM_PAID:
+ return "OEM_PAID";
+ case OEM_PRIVATE:
+ return "OEM_PRIVATE";
+ default:
+ return "Invalid(" + oemManagedBit + ")";
+ }
+ }
+
public void dumpDebug(ProtoOutputStream proto, long tag) {
final long start = proto.start(tag);
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index d3c89574944f..352f2e99aa5e 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -274,11 +274,14 @@ public class NetworkTemplate implements Parcelable {
}
/**
- * Template to match all carrier networks with the given IMSI.
+ * Template to match all metered carrier networks with the given IMSI.
*/
- public static NetworkTemplate buildTemplateCarrier(@NonNull String subscriberId) {
+ public static NetworkTemplate buildTemplateCarrierMetered(@NonNull String subscriberId) {
Objects.requireNonNull(subscriberId);
- return new NetworkTemplate(MATCH_CARRIER, subscriberId, null);
+ return new NetworkTemplate(MATCH_CARRIER, subscriberId,
+ new String[] { subscriberId }, null /* networkId */, METERED_YES, ROAMING_ALL,
+ DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL,
+ SUBSCRIBER_ID_MATCH_RULE_EXACT);
}
private final int mMatchRule;
@@ -424,7 +427,7 @@ public class NetworkTemplate implements Parcelable {
builder.append(", subType=").append(mSubType);
}
if (mOemManaged != OEM_MANAGED_ALL) {
- builder.append(", oemManaged=").append(mOemManaged);
+ builder.append(", oemManaged=").append(getOemManagedNames(mOemManaged));
}
builder.append(", subscriberIdMatchRule=")
.append(subscriberIdMatchRuleToString(mSubscriberIdMatchRule));
@@ -774,6 +777,19 @@ public class NetworkTemplate implements Parcelable {
}
}
+ private static String getOemManagedNames(int oemManaged) {
+ switch (oemManaged) {
+ case OEM_MANAGED_ALL:
+ return "OEM_MANAGED_ALL";
+ case OEM_MANAGED_NO:
+ return "OEM_MANAGED_NO";
+ case OEM_MANAGED_YES:
+ return "OEM_MANAGED_YES";
+ default:
+ return NetworkIdentity.getOemManagedNames(oemManaged);
+ }
+ }
+
/**
* Examine the given template and normalize if it refers to a "merged"
* mobile subscriber. We pick the "lowest" merged subscriber as the primary
diff --git a/core/java/android/net/UnderlyingNetworkInfo.java b/core/java/android/net/UnderlyingNetworkInfo.java
index 459fdacef816..33f9375c03bf 100644
--- a/core/java/android/net/UnderlyingNetworkInfo.java
+++ b/core/java/android/net/UnderlyingNetworkInfo.java
@@ -71,13 +71,13 @@ public final class UnderlyingNetworkInfo implements Parcelable {
/** Get the interface name of this network. */
@NonNull
- public String getIface() {
+ public String getInterface() {
return mIface;
}
/** Get the names of the interfaces underlying this network. */
@NonNull
- public List<String> getUnderlyingIfaces() {
+ public List<String> getUnderlyingInterfaces() {
return mUnderlyingIfaces;
}
@@ -124,8 +124,8 @@ public final class UnderlyingNetworkInfo implements Parcelable {
if (!(o instanceof UnderlyingNetworkInfo)) return false;
final UnderlyingNetworkInfo that = (UnderlyingNetworkInfo) o;
return mOwnerUid == that.getOwnerUid()
- && Objects.equals(mIface, that.getIface())
- && Objects.equals(mUnderlyingIfaces, that.getUnderlyingIfaces());
+ && Objects.equals(mIface, that.getInterface())
+ && Objects.equals(mUnderlyingIfaces, that.getUnderlyingInterfaces());
}
@Override
diff --git a/core/java/android/net/vcn/OWNERS b/core/java/android/net/vcn/OWNERS
index 33b9f0f75f81..2441e772468c 100644
--- a/core/java/android/net/vcn/OWNERS
+++ b/core/java/android/net/vcn/OWNERS
@@ -3,5 +3,5 @@ set noparent
benedictwong@google.com
ckesting@google.com
evitayan@google.com
+junyin@google.com
nharold@google.com
-jchalard@google.com \ No newline at end of file
diff --git a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
index 2df3e6c7ecd6..d59ad6f88864 100644
--- a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
+++ b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
@@ -161,9 +161,6 @@ public final class VcnGatewayConnectionConfig {
private static final String EXPOSED_CAPABILITIES_KEY = "mExposedCapabilities";
@NonNull private final SortedSet<Integer> mExposedCapabilities;
- private static final String UNDERLYING_CAPABILITIES_KEY = "mUnderlyingCapabilities";
- @NonNull private final SortedSet<Integer> mUnderlyingCapabilities;
-
private static final String MAX_MTU_KEY = "mMaxMtu";
private final int mMaxMtu;
@@ -175,13 +172,11 @@ public final class VcnGatewayConnectionConfig {
@NonNull String gatewayConnectionName,
@NonNull IkeTunnelConnectionParams tunnelConnectionParams,
@NonNull Set<Integer> exposedCapabilities,
- @NonNull Set<Integer> underlyingCapabilities,
@NonNull long[] retryIntervalsMs,
@IntRange(from = MIN_MTU_V6) int maxMtu) {
mGatewayConnectionName = gatewayConnectionName;
mTunnelConnectionParams = tunnelConnectionParams;
mExposedCapabilities = new TreeSet(exposedCapabilities);
- mUnderlyingCapabilities = new TreeSet(underlyingCapabilities);
mRetryIntervalsMs = retryIntervalsMs;
mMaxMtu = maxMtu;
@@ -198,16 +193,12 @@ public final class VcnGatewayConnectionConfig {
final PersistableBundle exposedCapsBundle =
in.getPersistableBundle(EXPOSED_CAPABILITIES_KEY);
- final PersistableBundle underlyingCapsBundle =
- in.getPersistableBundle(UNDERLYING_CAPABILITIES_KEY);
mGatewayConnectionName = in.getString(GATEWAY_CONNECTION_NAME_KEY);
mTunnelConnectionParams =
TunnelConnectionParamsUtils.fromPersistableBundle(tunnelConnectionParamsBundle);
mExposedCapabilities = new TreeSet<>(PersistableBundleUtils.toList(
exposedCapsBundle, PersistableBundleUtils.INTEGER_DESERIALIZER));
- mUnderlyingCapabilities = new TreeSet<>(PersistableBundleUtils.toList(
- underlyingCapsBundle, PersistableBundleUtils.INTEGER_DESERIALIZER));
mRetryIntervalsMs = in.getLongArray(RETRY_INTERVAL_MS_KEY);
mMaxMtu = in.getInt(MAX_MTU_KEY);
@@ -307,36 +298,6 @@ public final class VcnGatewayConnectionConfig {
}
/**
- * Returns all capabilities required of underlying networks.
- *
- * <p>The returned integer-value capabilities will be sorted in ascending numerical order.
- *
- * @see Builder#addRequiredUnderlyingCapability(int)
- * @see Builder#removeRequiredUnderlyingCapability(int)
- * @hide
- */
- // TODO(b/182219992): Remove, and add when per-transport capabilities are supported
- @NonNull
- public int[] getRequiredUnderlyingCapabilities() {
- // Sorted set guarantees ordering
- return ArrayUtils.convertToIntArray(new ArrayList<>(mUnderlyingCapabilities));
- }
-
- /**
- * Returns all capabilities required of underlying networks.
- *
- * <p>Left to prevent the need to make major changes while changes are actively in flight.
- *
- * @deprecated use getRequiredUnderlyingCapabilities() instead
- * @hide
- */
- @Deprecated
- @NonNull
- public Set<Integer> getAllUnderlyingCapabilities() {
- return Collections.unmodifiableSet(mUnderlyingCapabilities);
- }
-
- /**
* Retrieves the configured retry intervals.
*
* @see Builder#setRetryIntervalsMillis(long[])
@@ -372,15 +333,10 @@ public final class VcnGatewayConnectionConfig {
PersistableBundleUtils.fromList(
new ArrayList<>(mExposedCapabilities),
PersistableBundleUtils.INTEGER_SERIALIZER);
- final PersistableBundle underlyingCapsBundle =
- PersistableBundleUtils.fromList(
- new ArrayList<>(mUnderlyingCapabilities),
- PersistableBundleUtils.INTEGER_SERIALIZER);
result.putString(GATEWAY_CONNECTION_NAME_KEY, mGatewayConnectionName);
result.putPersistableBundle(TUNNEL_CONNECTION_PARAMS_KEY, tunnelConnectionParamsBundle);
result.putPersistableBundle(EXPOSED_CAPABILITIES_KEY, exposedCapsBundle);
- result.putPersistableBundle(UNDERLYING_CAPABILITIES_KEY, underlyingCapsBundle);
result.putLongArray(RETRY_INTERVAL_MS_KEY, mRetryIntervalsMs);
result.putInt(MAX_MTU_KEY, mMaxMtu);
@@ -392,7 +348,6 @@ public final class VcnGatewayConnectionConfig {
return Objects.hash(
mGatewayConnectionName,
mExposedCapabilities,
- mUnderlyingCapabilities,
Arrays.hashCode(mRetryIntervalsMs),
mMaxMtu);
}
@@ -406,7 +361,6 @@ public final class VcnGatewayConnectionConfig {
final VcnGatewayConnectionConfig rhs = (VcnGatewayConnectionConfig) other;
return mGatewayConnectionName.equals(rhs.mGatewayConnectionName)
&& mExposedCapabilities.equals(rhs.mExposedCapabilities)
- && mUnderlyingCapabilities.equals(rhs.mUnderlyingCapabilities)
&& Arrays.equals(mRetryIntervalsMs, rhs.mRetryIntervalsMs)
&& mMaxMtu == rhs.mMaxMtu;
}
@@ -418,7 +372,6 @@ public final class VcnGatewayConnectionConfig {
@NonNull private final String mGatewayConnectionName;
@NonNull private final IkeTunnelConnectionParams mTunnelConnectionParams;
@NonNull private final Set<Integer> mExposedCapabilities = new ArraySet();
- @NonNull private final Set<Integer> mUnderlyingCapabilities = new ArraySet();
@NonNull private long[] mRetryIntervalsMs = DEFAULT_RETRY_INTERVALS_MS;
private int mMaxMtu = DEFAULT_MAX_MTU;
@@ -490,51 +443,6 @@ public final class VcnGatewayConnectionConfig {
}
/**
- * Require a capability for Networks underlying this VCN Gateway Connection.
- *
- * @param underlyingCapability the capability that a network MUST have in order to be an
- * underlying network for this VCN Gateway Connection.
- * @return this {@link Builder} instance, for chaining
- * @see VcnGatewayConnectionConfig for a list of capabilities may be required of underlying
- * networks
- * @hide
- */
- // TODO(b/182219992): Remove, and add when per-transport capabilities are supported
- @NonNull
- public Builder addRequiredUnderlyingCapability(
- @VcnSupportedCapability int underlyingCapability) {
- checkValidCapability(underlyingCapability);
-
- mUnderlyingCapabilities.add(underlyingCapability);
- return this;
- }
-
- /**
- * Remove a requirement of a capability for Networks underlying this VCN Gateway Connection.
- *
- * <p>Calling this method will allow Networks that do NOT have this capability to be
- * selected as an underlying network for this VCN Gateway Connection. However, underlying
- * networks MAY still have the removed capability.
- *
- * @param underlyingCapability the capability that a network DOES NOT need to have in order
- * to be an underlying network for this VCN Gateway Connection.
- * @return this {@link Builder} instance, for chaining
- * @see VcnGatewayConnectionConfig for a list of capabilities may be required of underlying
- * networks
- * @hide
- */
- // TODO(b/182219992): Remove, and add when per-transport capabilities are supported
- @NonNull
- @SuppressLint("BuilderSetStyle") // For consistency with NetCaps.Builder add/removeCap
- public Builder removeRequiredUnderlyingCapability(
- @VcnSupportedCapability int underlyingCapability) {
- checkValidCapability(underlyingCapability);
-
- mUnderlyingCapabilities.remove(underlyingCapability);
- return this;
- }
-
- /**
* Set the retry interval between VCN establishment attempts upon successive failures.
*
* <p>The last retry interval will be repeated until safe mode is entered, or a connection
@@ -598,7 +506,6 @@ public final class VcnGatewayConnectionConfig {
mGatewayConnectionName,
mTunnelConnectionParams,
mExposedCapabilities,
- mUnderlyingCapabilities,
mRetryIntervalsMs,
mMaxMtu);
}
diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java
index 9d1c1ff898e7..390c3b9453c2 100644
--- a/core/java/android/net/vcn/VcnManager.java
+++ b/core/java/android/net/vcn/VcnManager.java
@@ -74,6 +74,36 @@ import java.util.concurrent.Executor;
public class VcnManager {
@NonNull private static final String TAG = VcnManager.class.getSimpleName();
+ /**
+ * Key for WiFi entry RSSI thresholds
+ *
+ * <p>The VCN will only migrate to a Carrier WiFi network that has a signal strength greater
+ * than, or equal to this threshold.
+ *
+ * <p>WARNING: The VCN does not listen for changes to this key made after VCN startup.
+ *
+ * @hide
+ */
+ @NonNull
+ public static final String VCN_NETWORK_SELECTION_WIFI_ENTRY_RSSI_THRESHOLD_KEY =
+ "vcn_network_selection_wifi_entry_rssi_threshold";
+
+ /**
+ * Key for WiFi entry RSSI thresholds
+ *
+ * <p>If the VCN's selected Carrier WiFi network has a signal strength less than this threshold,
+ * the VCN will attempt to migrate away from the Carrier WiFi network.
+ *
+ * <p>WARNING: The VCN does not listen for changes to this key made after VCN startup.
+ *
+ * @hide
+ */
+ @NonNull
+ public static final String VCN_NETWORK_SELECTION_WIFI_EXIT_RSSI_THRESHOLD_KEY =
+ "vcn_network_selection_wifi_exit_rssi_threshold";
+
+ // TODO: Add separate signal strength thresholds for 2.4 GHz and 5GHz
+
private static final Map<
VcnNetworkPolicyChangeListener, VcnUnderlyingNetworkPolicyListenerBinder>
REGISTERED_POLICY_LISTENERS = new ConcurrentHashMap<>();
diff --git a/core/java/android/net/vcn/VcnTransportInfo.java b/core/java/android/net/vcn/VcnTransportInfo.java
index 0e9ccf144c2e..1f1818420b56 100644
--- a/core/java/android/net/vcn/VcnTransportInfo.java
+++ b/core/java/android/net/vcn/VcnTransportInfo.java
@@ -16,23 +16,17 @@
package android.net.vcn;
-import static android.net.NetworkCapabilities.REDACT_ALL;
-import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS;
+import static android.net.NetworkCapabilities.REDACT_NONE;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.net.NetworkCapabilities;
import android.net.TransportInfo;
import android.net.wifi.WifiInfo;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.SubscriptionManager;
-import com.android.internal.annotations.VisibleForTesting;
-
import java.util.Objects;
/**
@@ -55,32 +49,17 @@ public class VcnTransportInfo implements TransportInfo, Parcelable {
@Nullable private final WifiInfo mWifiInfo;
private final int mSubId;
- /**
- * The redaction scheme to use when parcelling.
- *
- * <p>The TransportInfo/NetworkCapabilities redaction mechanisms rely on redaction being
- * performed at parcelling time. This means that the redaction scheme must be stored for later
- * use.
- *
- * <p>Since the redaction scheme itself is not parcelled, this field is listed as a transient.
- *
- * <p>Defaults to REDACT_ALL when constructed using public constructors, or creating from
- * parcels.
- */
- private final transient long mRedactions;
-
public VcnTransportInfo(@NonNull WifiInfo wifiInfo) {
- this(wifiInfo, INVALID_SUBSCRIPTION_ID, REDACT_ALL);
+ this(wifiInfo, INVALID_SUBSCRIPTION_ID);
}
public VcnTransportInfo(int subId) {
- this(null /* wifiInfo */, subId, REDACT_ALL);
+ this(null /* wifiInfo */, subId);
}
- private VcnTransportInfo(@Nullable WifiInfo wifiInfo, int subId, long redactions) {
+ private VcnTransportInfo(@Nullable WifiInfo wifiInfo, int subId) {
mWifiInfo = wifiInfo;
mSubId = subId;
- mRedactions = redactions;
}
/**
@@ -102,25 +81,14 @@ public class VcnTransportInfo implements TransportInfo, Parcelable {
* SubscriptionManager#INVALID_SUBSCRIPTION_ID}.
*
* @return the Subscription ID if a cellular underlying Network is present, else {@link
- * android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID}.
+ * android.telephony.SubscriptionManager#INVALID_SUBSCRIPTION_ID}.
*/
public int getSubId() {
return mSubId;
}
- /**
- * Gets the redaction scheme
- *
- * @hide
- */
- @VisibleForTesting(visibility = PRIVATE)
- public long getRedaction() {
- return mRedactions;
- }
-
@Override
public int hashCode() {
- // mRedactions not hashed, as it is a transient, for control of parcelling
return Objects.hash(mWifiInfo, mSubId);
}
@@ -128,8 +96,6 @@ public class VcnTransportInfo implements TransportInfo, Parcelable {
public boolean equals(Object o) {
if (!(o instanceof VcnTransportInfo)) return false;
final VcnTransportInfo that = (VcnTransportInfo) o;
-
- // mRedactions not compared, as it is a transient, for control of parcelling
return Objects.equals(mWifiInfo, that.mWifiInfo) && mSubId == that.mSubId;
}
@@ -143,31 +109,19 @@ public class VcnTransportInfo implements TransportInfo, Parcelable {
@NonNull
public TransportInfo makeCopy(long redactions) {
return new VcnTransportInfo(
- mWifiInfo == null ? null : mWifiInfo.makeCopy(redactions), mSubId, redactions);
+ (mWifiInfo == null) ? null : mWifiInfo.makeCopy(redactions), mSubId);
}
@Override
public long getApplicableRedactions() {
- long redactions = REDACT_FOR_NETWORK_SETTINGS;
-
- // Add additional wifi redactions if necessary
- if (mWifiInfo != null) {
- redactions |= mWifiInfo.getApplicableRedactions();
- }
-
- return redactions;
- }
-
- private boolean shouldParcelNetworkSettingsFields() {
- return (mRedactions & NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS) == 0;
+ return (mWifiInfo == null) ? REDACT_NONE : mWifiInfo.getApplicableRedactions();
}
/** {@inheritDoc} */
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeInt(shouldParcelNetworkSettingsFields() ? mSubId : INVALID_SUBSCRIPTION_ID);
- dest.writeParcelable(
- shouldParcelNetworkSettingsFields() ? (Parcelable) mWifiInfo : null, flags);
+ dest.writeInt(mSubId);
+ dest.writeParcelable(mWifiInfo, flags);
}
@Override
@@ -181,17 +135,7 @@ public class VcnTransportInfo implements TransportInfo, Parcelable {
public VcnTransportInfo createFromParcel(Parcel in) {
final int subId = in.readInt();
final WifiInfo wifiInfo = in.readParcelable(null);
-
- // If all fields are their null values, return null TransportInfo to avoid
- // leaking information about this being a VCN Network (instead of macro
- // cellular, etc)
- if (wifiInfo == null && subId == INVALID_SUBSCRIPTION_ID) {
- return null;
- }
-
- // Prevent further forwarding by redacting everything in future parcels from
- // this VcnTransportInfo
- return new VcnTransportInfo(wifiInfo, subId, REDACT_ALL);
+ return new VcnTransportInfo(wifiInfo, subId);
}
public VcnTransportInfo[] newArray(int size) {
diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS
index d9665953dceb..cd02d297270a 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -63,3 +63,6 @@ per-file *Zygote* = file:/ZYGOTE_OWNERS
# RecoverySystem
per-file *Recovery* = file:/services/core/java/com/android/server/recoverysystem/OWNERS
+
+# Bugreporting
+per-file Bugreport* = file:/platform/frameworks/native:/cmds/dumpstate/OWNERS
diff --git a/core/java/android/os/incremental/OWNERS b/core/java/android/os/incremental/OWNERS
index 3795493b861f..47eee6406206 100644
--- a/core/java/android/os/incremental/OWNERS
+++ b/core/java/android/os/incremental/OWNERS
@@ -3,3 +3,4 @@ alexbuy@google.com
schfan@google.com
toddke@google.com
zyy@google.com
+patb@google.com
diff --git a/core/java/com/android/internal/app/procstats/OWNERS b/core/java/com/android/internal/app/procstats/OWNERS
new file mode 100644
index 000000000000..72c0a9e6e90c
--- /dev/null
+++ b/core/java/com/android/internal/app/procstats/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/am/OWNERS
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index c34b9f09ecaa..98082cb40f44 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -6126,6 +6126,17 @@ public class BatteryStatsImpl extends BatteryStats {
}
}
+ /**
+ * Records timing data related to an incoming Binder call in order to attribute
+ * the power consumption to the calling app.
+ */
+ public void noteBinderCallStats(int workSourceUid,
+ Collection<BinderCallsStats.CallStat> callStats) {
+ synchronized (this) {
+ getUidStatsLocked(workSourceUid).noteBinderCallStatsLocked(callStats);
+ }
+ }
+
public String[] getWifiIfaces() {
synchronized (mWifiNetworkLock) {
return mWifiIfaces;
@@ -8693,6 +8704,17 @@ public class BatteryStatsImpl extends BatteryStats {
}
/**
+ * Notes incoming binder call stats associated with this work source UID.
+ */
+ public void noteBinderCallStatsLocked(Collection<BinderCallsStats.CallStat> callStats) {
+ if (DEBUG) {
+ Slog.d(TAG, "noteBinderCalls() workSourceUid = [" + mUid + "], callStats = ["
+ + new ArrayList<>(callStats) + "]");
+ }
+ // TODO(dplotnikov): finish the implementation by actually remembering the stats
+ }
+
+ /**
* The statistics associated with a particular wake lock.
*/
public static class Wakelock extends BatteryStats.Uid.Wakelock {
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
index dbba469dda1a..4cb5b020915b 100644
--- a/core/java/com/android/internal/os/BinderCallsStats.java
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -19,10 +19,14 @@ package com.android.internal.os;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Binder;
+import android.os.Handler;
+import android.os.Looper;
import android.os.Process;
import android.os.SystemClock;
+import android.os.UserHandle;
import android.text.format.DateFormat;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
@@ -95,7 +99,33 @@ public class BinderCallsStats implements BinderInternal.Observer {
private CachedDeviceState.Readonly mDeviceState;
private CachedDeviceState.TimeInStateStopwatch mBatteryStopwatch;
+ private static final int CALL_STATS_OBSERVER_DEBOUNCE_MILLIS = 5000;
private BinderLatencyObserver mLatencyObserver;
+ private BinderInternal.CallStatsObserver mCallStatsObserver;
+ private ArraySet<Integer> mSendUidsToObserver = new ArraySet<>(32);
+ private final Handler mCallStatsObserverHandler;
+ private Runnable mCallStatsObserverRunnable = new Runnable() {
+ @Override
+ public void run() {
+ if (mCallStatsObserver == null) {
+ return;
+ }
+
+ noteCallsStatsDelayed();
+
+ synchronized (mLock) {
+ int size = mSendUidsToObserver.size();
+ for (int i = 0; i < size; i++) {
+ UidEntry uidEntry = mUidEntries.get(mSendUidsToObserver.valueAt(i));
+ if (uidEntry != null) {
+ mCallStatsObserver.noteCallStats(uidEntry.workSourceUid,
+ uidEntry.getCallStatsList());
+ }
+ }
+ mSendUidsToObserver.clear();
+ }
+ }
+ };
/** Injector for {@link BinderCallsStats}. */
public static class Injector {
@@ -103,6 +133,10 @@ public class BinderCallsStats implements BinderInternal.Observer {
return new Random();
}
+ public Handler getHandler() {
+ return new Handler(Looper.getMainLooper());
+ }
+
public BinderLatencyObserver getLatencyObserver() {
return new BinderLatencyObserver(new BinderLatencyObserver.Injector());
}
@@ -110,6 +144,7 @@ public class BinderCallsStats implements BinderInternal.Observer {
public BinderCallsStats(Injector injector) {
this.mRandom = injector.getRandomGenerator();
+ this.mCallStatsObserverHandler = injector.getHandler();
this.mLatencyObserver = injector.getLatencyObserver();
}
@@ -121,6 +156,24 @@ public class BinderCallsStats implements BinderInternal.Observer {
mBatteryStopwatch = deviceState.createTimeOnBatteryStopwatch();
}
+ /**
+ * Registers an observer for call stats, which is invoked periodically with accumulated
+ * binder call stats.
+ */
+ public void setCallStatsObserver(
+ BinderInternal.CallStatsObserver callStatsObserver) {
+ mCallStatsObserver = callStatsObserver;
+ noteCallsStatsDelayed();
+ }
+
+ private void noteCallsStatsDelayed() {
+ mCallStatsObserverHandler.removeCallbacks(mCallStatsObserverRunnable);
+ if (mCallStatsObserver != null) {
+ mCallStatsObserverHandler.postDelayed(mCallStatsObserverRunnable,
+ CALL_STATS_OBSERVER_DEBOUNCE_MILLIS);
+ }
+ }
+
@Override
@Nullable
public CallSession callStarted(Binder binder, int code, int workSourceUid) {
@@ -233,6 +286,9 @@ public class BinderCallsStats implements BinderInternal.Observer {
callStat.callCount++;
}
}
+ if (mCallStatsObserver != null && !UserHandle.isCore(workSourceUid)) {
+ mSendUidsToObserver.add(workSourceUid);
+ }
}
}
@@ -267,7 +323,7 @@ public class BinderCallsStats implements BinderInternal.Observer {
}
@Nullable
- private Method getDefaultTransactionNameMethod(Class<? extends Binder> binder) {
+ private static Method getDefaultTransactionNameMethod(Class<? extends Binder> binder) {
try {
return binder.getMethod("getDefaultTransactionName", int.class);
} catch (NoSuchMethodException e) {
@@ -277,16 +333,17 @@ public class BinderCallsStats implements BinderInternal.Observer {
}
@Nullable
- private String resolveTransactionCode(Method getDefaultTransactionName, int transactionCode) {
- if (getDefaultTransactionName == null) {
- return null;
- }
-
- try {
- return (String) getDefaultTransactionName.invoke(null, transactionCode);
- } catch (IllegalAccessException | InvocationTargetException | ClassCastException e) {
- throw new RuntimeException(e);
+ private static String resolveTransactionCode(Method getDefaultTransactionName,
+ int transactionCode) {
+ String resolvedCode = null;
+ if (getDefaultTransactionName != null) {
+ try {
+ resolvedCode = (String) getDefaultTransactionName.invoke(null, transactionCode);
+ } catch (IllegalAccessException | InvocationTargetException | ClassCastException e) {
+ throw new RuntimeException(e);
+ }
}
+ return resolvedCode == null ? String.valueOf(transactionCode) : resolvedCode;
}
/**
@@ -342,11 +399,8 @@ public class BinderCallsStats implements BinderInternal.Observer {
|| previous.transactionCode != exported.transactionCode;
final String methodName;
if (isClassDifferent || isCodeDifferent) {
- String resolvedCode = resolveTransactionCode(
+ methodName = resolveTransactionCode(
getDefaultTransactionName, exported.transactionCode);
- methodName = resolvedCode == null
- ? String.valueOf(exported.transactionCode)
- : resolvedCode;
} else {
methodName = previousMethodName;
}
@@ -657,6 +711,20 @@ public class BinderCallsStats implements BinderInternal.Observer {
this.transactionCode = transactionCode;
this.screenInteractive = screenInteractive;
}
+
+ @Override
+ public String toString() {
+ return "CallStat{"
+ + "callingUid=" + callingUid
+ + ", transaction=" + binderClass.getSimpleName()
+ + '.' + resolveTransactionCode(
+ getDefaultTransactionNameMethod(binderClass), transactionCode)
+ + ", callCount=" + callCount
+ + ", recordedCallCount=" + recordedCallCount
+ + ", cpuTimeMicros=" + cpuTimeMicros
+ + ", latencyMicros=" + latencyMicros
+ + '}';
+ }
}
/** Key used to store CallStat object in a Map. */
diff --git a/core/java/com/android/internal/os/BinderInternal.java b/core/java/com/android/internal/os/BinderInternal.java
index 95c36ca8429e..7253307feb63 100644
--- a/core/java/com/android/internal/os/BinderInternal.java
+++ b/core/java/com/android/internal/os/BinderInternal.java
@@ -31,6 +31,7 @@ import dalvik.system.VMRuntime;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.Collection;
/**
* Private and debugging Binder APIs.
@@ -134,6 +135,16 @@ public class BinderInternal {
}
/**
+ * Allows to track observe incoming binder call stats.
+ */
+ public interface CallStatsObserver {
+ /**
+ * Notes incoming binder call stats associated with this work source UID.
+ */
+ void noteCallStats(int workSourceUid, Collection<BinderCallsStats.CallStat> callStats);
+ }
+
+ /**
* Add the calling thread to the IPC thread pool. This function does
* not return until the current process is exiting.
*/
diff --git a/core/java/com/android/internal/os/BinderLatencyBuckets.java b/core/java/com/android/internal/os/BinderLatencyBuckets.java
index bdee4ca8a6b8..d7d2d6a8f9dd 100644
--- a/core/java/com/android/internal/os/BinderLatencyBuckets.java
+++ b/core/java/com/android/internal/os/BinderLatencyBuckets.java
@@ -20,8 +20,7 @@ import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
-import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Arrays;
/**
* Generates the bucket thresholds (with a custom logarithmic scale) for a histogram to store
@@ -29,7 +28,7 @@ import java.util.Collections;
*/
public class BinderLatencyBuckets {
private static final String TAG = "BinderLatencyBuckets";
- private ArrayList<Integer> mBuckets;
+ private final int[] mBuckets;
/**
* @param bucketCount the number of buckets the histogram should have
@@ -37,12 +36,11 @@ public class BinderLatencyBuckets {
* @param scaleFactor the rate in which each consecutive bucket increases (before rounding)
*/
public BinderLatencyBuckets(int bucketCount, int firstBucketSize, float scaleFactor) {
- mBuckets = new ArrayList<>(bucketCount - 1);
- mBuckets.add(firstBucketSize);
+ int[] buffer = new int[bucketCount - 1];
+ buffer[0] = firstBucketSize;
// Last value and the target are disjoint as we never want to create buckets smaller than 1.
double lastTarget = firstBucketSize;
- int lastValue = firstBucketSize;
// First bucket is already created and the last bucket is anything greater than the final
// bucket in the list, so create 'bucketCount' - 2 buckets.
@@ -50,29 +48,29 @@ public class BinderLatencyBuckets {
// Increase the target bucket limit value by the scale factor.
double nextTarget = lastTarget * scaleFactor;
- if (nextTarget > Integer.MAX_VALUE || lastValue == Integer.MAX_VALUE) {
+ if (nextTarget > Integer.MAX_VALUE) {
// Do not throw an exception here as this should not affect binder calls.
Slog.w(TAG, "Attempted to create a bucket larger than maxint");
+ mBuckets = Arrays.copyOfRange(buffer, 0, i);
return;
}
- if ((int) nextTarget > lastValue) {
+ if ((int) nextTarget > buffer[i - 1]) {
// Convert the target bucket limit value to an integer.
- mBuckets.add((int) nextTarget);
- lastValue = (int) nextTarget;
+ buffer[i] = (int) nextTarget;
} else {
// Avoid creating redundant buckets, so bucket size should be 1 at a minimum.
- mBuckets.add(lastValue + 1);
- lastValue = lastValue + 1;
+ buffer[i] = buffer[i - 1] + 1;
}
lastTarget = nextTarget;
}
+ mBuckets = buffer;
}
/** Gets the bucket index to insert the provided sample in. */
public int sampleToBucket(int sample) {
- if (sample > mBuckets.get(mBuckets.size() - 1)) {
- return mBuckets.size();
+ if (sample >= mBuckets[mBuckets.length - 1]) {
+ return mBuckets.length;
}
// Binary search returns the element index if it is contained in the list - in this case the
@@ -80,12 +78,12 @@ public class BinderLatencyBuckets {
// Otherwise, it returns (-(insertion point) - 1), where insertion point is the point where
// to insert the element so that the array remains sorted - in this case the bucket index
// is the insertion point.
- int searchResult = Collections.binarySearch(mBuckets, sample);
+ int searchResult = Arrays.binarySearch(mBuckets, sample);
return searchResult < 0 ? -(1 + searchResult) : searchResult + 1;
}
@VisibleForTesting
- public ArrayList<Integer> getBuckets() {
+ public int[] getBuckets() {
return mBuckets;
}
}
diff --git a/core/java/com/android/internal/os/WrapperInit.java b/core/java/com/android/internal/os/WrapperInit.java
index 6860759eea8a..508782b9f3dc 100644
--- a/core/java/com/android/internal/os/WrapperInit.java
+++ b/core/java/com/android/internal/os/WrapperInit.java
@@ -21,8 +21,8 @@ import android.os.Trace;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
-import android.system.StructCapUserData;
-import android.system.StructCapUserHeader;
+import android.system.StructUserCapData;
+import android.system.StructUserCapHeader;
import android.util.Slog;
import android.util.TimingsTraceLog;
@@ -187,9 +187,9 @@ public class WrapperInit {
* capabilities, which may make it crash, but not exceed its allowances.
*/
private static void preserveCapabilities() {
- StructCapUserHeader header = new StructCapUserHeader(
+ StructUserCapHeader header = new StructUserCapHeader(
OsConstants._LINUX_CAPABILITY_VERSION_3, 0);
- StructCapUserData[] data;
+ StructUserCapData[] data;
try {
data = Os.capget(header);
} catch (ErrnoException e) {
@@ -199,9 +199,9 @@ public class WrapperInit {
if (data[0].permitted != data[0].inheritable ||
data[1].permitted != data[1].inheritable) {
- data[0] = new StructCapUserData(data[0].effective, data[0].permitted,
+ data[0] = new StructUserCapData(data[0].effective, data[0].permitted,
data[0].permitted);
- data[1] = new StructCapUserData(data[1].effective, data[1].permitted,
+ data[1] = new StructUserCapData(data[1].effective, data[1].permitted,
data[1].permitted);
try {
Os.capset(header, data);
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index a54108957775..0121b789f39a 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -45,8 +45,8 @@ import android.security.keystore2.AndroidKeyStoreProvider;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
-import android.system.StructCapUserData;
-import android.system.StructCapUserHeader;
+import android.system.StructUserCapData;
+import android.system.StructUserCapHeader;
import android.text.Hyphenator;
import android.util.EventLog;
import android.util.Log;
@@ -742,9 +742,9 @@ public class ZygoteInit {
OsConstants.CAP_BLOCK_SUSPEND
);
/* Containers run without some capabilities, so drop any caps that are not available. */
- StructCapUserHeader header = new StructCapUserHeader(
+ StructUserCapHeader header = new StructUserCapHeader(
OsConstants._LINUX_CAPABILITY_VERSION_3, 0);
- StructCapUserData[] data;
+ StructUserCapData[] data;
try {
data = Os.capget(header);
} catch (ErrnoException ex) {
diff --git a/core/java/com/android/server/OWNERS b/core/java/com/android/server/OWNERS
index 1262925447b9..554e27890476 100644
--- a/core/java/com/android/server/OWNERS
+++ b/core/java/com/android/server/OWNERS
@@ -1 +1 @@
-per-file SystemConfig.java = toddke@google.com
+per-file SystemConfig.java = toddke@google.com,patb@google.com
diff --git a/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
index 24fef4881e4c..5fe96ede202e 100644
--- a/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
+++ b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
@@ -402,7 +402,7 @@ jboolean com_android_internal_os_ZygoteCommandBuffer_nativeForkRepeatedly(
socklen_t cred_size = sizeof credentials;
if (getsockopt(n_buffer->getFd(), SOL_SOCKET, SO_PEERCRED, &credentials, &cred_size) == -1
|| cred_size != sizeof credentials) {
- fail_fn_1("ForkMany failed to get initial credentials, %s", strerror(errno));
+ fail_fn_1(CREATE_ERROR("ForkMany failed to get initial credentials, %s", strerror(errno)));
}
bool first_time = true;
@@ -453,7 +453,7 @@ jboolean com_android_internal_os_ZygoteCommandBuffer_nativeForkRepeatedly(
close(session_socket);
int new_fd = accept(zygote_socket_fd, nullptr, nullptr);
if (new_fd == -1) {
- fail_fn_z("Accept(%d) failed: %s", zygote_socket_fd, strerror(errno));
+ fail_fn_z(CREATE_ERROR("Accept(%d) failed: %s", zygote_socket_fd, strerror(errno)));
}
if (new_fd != session_socket) {
// Move new_fd back to the old value, so that we don't have to change Java-level data
diff --git a/core/proto/OWNERS b/core/proto/OWNERS
index e62b5c102a59..44ea23fdf685 100644
--- a/core/proto/OWNERS
+++ b/core/proto/OWNERS
@@ -14,9 +14,10 @@ per-file settings_enums.proto=tmfang@google.com
# Frameworks
ogunwale@google.com
jjaggi@google.com
+kwekua@google.com
roosa@google.com
-per-file package_item_info.proto = toddke@google.com
-per-file usagestatsservice.proto, usagestatsservice_v2.proto = mwachens@google.com
+per-file package_item_info.proto = toddke@google.com,patb@google.com
+per-file usagestatsservice.proto, usagestatsservice_v2.proto = file:/core/java/android/app/usage/OWNERS
per-file apphibernationservice.proto = file:/core/java/android/apphibernation/OWNERS
# Biometrics
diff --git a/core/res/OWNERS b/core/res/OWNERS
index 9d739b90bcc5..7a8da36d8a7d 100644
--- a/core/res/OWNERS
+++ b/core/res/OWNERS
@@ -1,6 +1,7 @@
adamp@google.com
alanv@google.com
asc@google.com
+cinek@google.com
dsandler@android.com
dsandler@google.com
dupin@google.com
@@ -8,6 +9,7 @@ hackbod@android.com
hackbod@google.com
ilyamaty@google.com
jaggies@google.com
+jdemeulenaere@google.com
jsharkey@android.com
jsharkey@google.com
juliacr@google.com
@@ -17,7 +19,9 @@ nandana@google.com
narayan@google.com
ogunwale@google.com
patb@google.com
+shanh@google.com
svetoslavganov@android.com
svetoslavganov@google.com
toddke@google.com
+tsuji@google.com
yamasani@google.com
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
index cec62164e57a..ee6e6c00a4dc 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
@@ -16,10 +16,16 @@
package com.android.internal.os;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import android.os.Binder;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Process;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
import android.util.ArrayMap;
@@ -46,11 +52,12 @@ import java.util.Random;
@RunWith(AndroidJUnit4.class)
@Presubmit
public class BinderCallsStatsTest {
- private static final int WORKSOURCE_UID = 1;
+ private static final int WORKSOURCE_UID = Process.FIRST_APPLICATION_UID;
private static final int CALLING_UID = 2;
private static final int REQUEST_SIZE = 2;
private static final int REPLY_SIZE = 3;
private final CachedDeviceState mDeviceState = new CachedDeviceState(false, true);
+ private final TestHandler mHandler = new TestHandler();
@Test
public void testDetailedOff() {
@@ -754,6 +761,51 @@ public class BinderCallsStatsTest {
}
@Test
+ public void testCallStatsObserver() {
+ TestBinderCallsStats bcs = new TestBinderCallsStats();
+ bcs.setSamplingInterval(1);
+ bcs.setTrackScreenInteractive(false);
+
+ final ArrayList<BinderCallsStats.CallStat> callStatsList = new ArrayList<>();
+ bcs.setCallStatsObserver((workSourceUid, callStats) -> callStatsList.addAll(callStats));
+
+ Binder binder = new Binder();
+
+ CallSession callSession = bcs.callStarted(binder, 1, WORKSOURCE_UID);
+ bcs.time += 10;
+ bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID);
+
+ callSession = bcs.callStarted(binder, 1, WORKSOURCE_UID);
+ bcs.time += 20;
+ bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID);
+
+ callSession = bcs.callStarted(binder, 2, WORKSOURCE_UID);
+ bcs.time += 30;
+ bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID);
+
+ for (Runnable runnable: mHandler.mRunnables) {
+ // Execute all pending runnables. Ignore the delay.
+ runnable.run();
+ }
+
+ assertThat(callStatsList).hasSize(2);
+ for (int i = 0; i < 2; i++) {
+ BinderCallsStats.CallStat callStats = callStatsList.get(i);
+ if (callStats.transactionCode == 1) {
+ assertEquals(2, callStats.callCount);
+ assertEquals(2, callStats.recordedCallCount);
+ assertEquals(30, callStats.cpuTimeMicros);
+ assertEquals(20, callStats.maxCpuTimeMicros);
+ } else {
+ assertEquals(1, callStats.callCount);
+ assertEquals(1, callStats.recordedCallCount);
+ assertEquals(30, callStats.cpuTimeMicros);
+ assertEquals(30, callStats.maxCpuTimeMicros);
+ }
+ }
+ }
+
+ @Test
public void testLatencyCollectionEnabled() {
TestBinderCallsStats bcs = new TestBinderCallsStats();
bcs.setCollectLatencyData(true);
@@ -781,6 +833,20 @@ public class BinderCallsStatsTest {
assertEquals(0, bcs.getLatencyObserver().getLatencyHistograms().size());
}
+ private static class TestHandler extends Handler {
+ ArrayList<Runnable> mRunnables = new ArrayList<>();
+
+ TestHandler() {
+ super(Looper.getMainLooper());
+ }
+
+ @Override
+ public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
+ mRunnables.add(msg.getCallback());
+ return true;
+ }
+ }
+
class TestBinderCallsStats extends BinderCallsStats {
public int callingUid = CALLING_UID;
public long time = 1234;
@@ -803,6 +869,10 @@ public class BinderCallsStatsTest {
};
}
+ public Handler getHandler() {
+ return mHandler;
+ }
+
public BinderLatencyObserver getLatencyObserver() {
return new BinderLatencyObserverTest.TestBinderLatencyObserver();
}
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderLatencyBucketsTest.java b/core/tests/coretests/src/com/android/internal/os/BinderLatencyBucketsTest.java
index 00443a967c79..b2054f1ee9ad 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderLatencyBucketsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderLatencyBucketsTest.java
@@ -36,6 +36,7 @@ public class BinderLatencyBucketsTest {
public void testBucketThresholds() {
BinderLatencyBuckets latencyBuckets = new BinderLatencyBuckets(10, 2, 1.45f);
assertThat(latencyBuckets.getBuckets())
+ .asList()
.containsExactly(2, 3, 4, 6, 8, 12, 18, 26, 39)
.inOrder();
}
@@ -58,6 +59,7 @@ public class BinderLatencyBucketsTest {
public void testMaxIntBuckets() {
BinderLatencyBuckets latencyBuckets = new BinderLatencyBuckets(5, Integer.MAX_VALUE / 2, 2);
assertThat(latencyBuckets.getBuckets())
+ .asList()
.containsExactly(Integer.MAX_VALUE / 2, Integer.MAX_VALUE - 1)
.inOrder();
diff --git a/core/tests/utiltests/src/com/android/internal/util/FileRotatorTest.java b/core/tests/utiltests/src/com/android/internal/util/FileRotatorTest.java
index 3f9e62e7b180..952721320c90 100644
--- a/core/tests/utiltests/src/com/android/internal/util/FileRotatorTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/FileRotatorTest.java
@@ -29,6 +29,8 @@ import android.util.Log;
import com.android.internal.util.FileRotator.Reader;
import com.android.internal.util.FileRotator.Writer;
+import com.android.internal.util.test.FsUtil;
+
import com.google.android.collect.Lists;
import java.io.DataInputStream;
@@ -38,15 +40,10 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.net.ProtocolException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
-import junit.framework.Assert;
-
-import libcore.io.IoUtils;
-
/**
* Tests for {@link FileRotator}.
*/
@@ -67,7 +64,7 @@ public class FileRotatorTest extends AndroidTestCase {
super.setUp();
mBasePath = getContext().getFilesDir();
- IoUtils.deleteContents(mBasePath);
+ FsUtil.deleteContents(mBasePath);
}
public void testEmpty() throws Exception {
diff --git a/data/etc/OWNERS b/data/etc/OWNERS
index 5aacfddab28c..ea23aba16d12 100644
--- a/data/etc/OWNERS
+++ b/data/etc/OWNERS
@@ -10,6 +10,7 @@ svetoslavganov@android.com
svetoslavganov@google.com
toddke@android.com
toddke@google.com
+patb@google.com
yamasani@google.com
per-file preinstalled-packages* = file:/MULTIUSER_OWNERS
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java
index fe05989c3846..97592b44ba2e 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java
@@ -252,7 +252,9 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi {
blockModes,
userAuthenticationRequired,
(int) userAuthenticationValidityDurationSeconds,
- keymasterHwEnforcedUserAuthenticators,
+ userAuthenticationRequirementEnforcedBySecureHardware
+ ? keymasterHwEnforcedUserAuthenticators
+ : keymasterSwEnforcedUserAuthenticators,
userAuthenticationRequirementEnforcedBySecureHardware,
userAuthenticationValidWhileOnBody,
trustedUserPresenceRequired,
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
index 3e2fb94f0387..f3cfcf18dec1 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
@@ -41,6 +41,8 @@ import android.system.keystore2.KeyMetadata;
import android.system.keystore2.ResponseCode;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -974,7 +976,6 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
}
private Set<String> getUniqueAliases() {
-
try {
final KeyDescriptor[] keys = mKeyStore.list(
getTargetDomain(),
@@ -987,7 +988,7 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
return aliases;
} catch (android.security.KeyStoreException e) {
Log.e(TAG, "Failed to list keystore entries.", e);
- return null;
+ return new HashSet<>();
}
}
@@ -1099,6 +1100,17 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
return caAlias;
}
+ /**
+ * Used by Tests to initialize with a fake KeyStore2.
+ * @hide
+ * @param keystore
+ */
+ @VisibleForTesting
+ public void initForTesting(KeyStore2 keystore) {
+ mKeyStore = keystore;
+ mNamespace = KeyProperties.NAMESPACE_APPLICATION;
+ }
+
@Override
public void engineStore(OutputStream stream, char[] password) throws IOException,
NoSuchAlgorithmException, CertificateException {
diff --git a/keystore/tests/Android.bp b/keystore/tests/Android.bp
index 2315a8568c64..7de45233494b 100644
--- a/keystore/tests/Android.bp
+++ b/keystore/tests/Android.bp
@@ -28,6 +28,7 @@ android_test {
static_libs: [
"androidx.test.rules",
"hamcrest-library",
+ "mockito-target-minus-junit4",
],
platform_apis: true,
libs: ["android.test.runner"],
diff --git a/keystore/tests/src/android/security/ParcelableKeyGenParameterSpecTest.java b/keystore/tests/src/android/security/ParcelableKeyGenParameterSpecTest.java
index b7d72fce6eba..2ae61ab3b38d 100644
--- a/keystore/tests/src/android/security/ParcelableKeyGenParameterSpecTest.java
+++ b/keystore/tests/src/android/security/ParcelableKeyGenParameterSpecTest.java
@@ -43,7 +43,6 @@ public final class ParcelableKeyGenParameterSpecTest {
static final String ALIAS = "keystore-alias";
static final String ANOTHER_ALIAS = "another-keystore-alias";
static final int KEY_PURPOSES = KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY;
- static final int UID = 1230;
static final int KEYSIZE = 2048;
static final X500Principal SUBJECT = new X500Principal("CN=subject");
static final BigInteger SERIAL = new BigInteger("1234567890");
@@ -61,7 +60,7 @@ public final class ParcelableKeyGenParameterSpecTest {
public static KeyGenParameterSpec configureDefaultSpec() {
return new KeyGenParameterSpec.Builder(ALIAS, KEY_PURPOSES)
- .setUid(UID)
+ .setNamespace(KeyProperties.NAMESPACE_WIFI)
.setKeySize(KEYSIZE)
.setCertificateSubject(SUBJECT)
.setCertificateSerialNumber(SERIAL)
@@ -88,10 +87,11 @@ public final class ParcelableKeyGenParameterSpecTest {
.build();
}
- public static void validateSpecValues(KeyGenParameterSpec spec, int uid, String alias) {
+ public static void validateSpecValues(KeyGenParameterSpec spec,
+ @KeyProperties.Namespace int namespace, String alias) {
assertThat(spec.getKeystoreAlias(), is(alias));
assertThat(spec.getPurposes(), is(KEY_PURPOSES));
- assertThat(spec.getUid(), is(uid));
+ assertThat(spec.getNamespace(), is(namespace));
assertThat(spec.getKeySize(), is(KEYSIZE));
assertThat(spec.getCertificateSubject(), is(SUBJECT));
assertThat(spec.getCertificateSerialNumber(), is(SERIAL));
@@ -134,7 +134,7 @@ public final class ParcelableKeyGenParameterSpecTest {
Parcel parcel = parcelForReading(spec);
ParcelableKeyGenParameterSpec fromParcel =
ParcelableKeyGenParameterSpec.CREATOR.createFromParcel(parcel);
- validateSpecValues(fromParcel.getSpec(), UID, ALIAS);
+ validateSpecValues(fromParcel.getSpec(), KeyProperties.NAMESPACE_WIFI, ALIAS);
assertThat(parcel.dataAvail(), is(0));
}
diff --git a/keystore/tests/src/android/security/keystore/KeyGenParameterSpecTest.java b/keystore/tests/src/android/security/keystore/KeyGenParameterSpecTest.java
index b2edfd05d13f..ddbb1d8c097c 100644
--- a/keystore/tests/src/android/security/keystore/KeyGenParameterSpecTest.java
+++ b/keystore/tests/src/android/security/keystore/KeyGenParameterSpecTest.java
@@ -21,8 +21,6 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import android.security.ParcelableKeyGenParameterSpecTest;
-import android.security.keystore.KeyGenParameterSpec;
-import android.security.keystore.KeyProperties;
import androidx.test.runner.AndroidJUnit4;
@@ -41,7 +39,7 @@ public final class KeyGenParameterSpecTest {
KeyGenParameterSpec copiedSpec =
new KeyGenParameterSpec.Builder(spec).build();
ParcelableKeyGenParameterSpecTest.validateSpecValues(
- copiedSpec, spec.getUid(), spec.getKeystoreAlias());
+ copiedSpec, spec.getNamespace(), spec.getKeystoreAlias());
}
@Test
diff --git a/keystore/tests/src/android/security/keystore2/AndroidKeyStoreSpiTest.java b/keystore/tests/src/android/security/keystore2/AndroidKeyStoreSpiTest.java
new file mode 100644
index 000000000000..1bd3069f483a
--- /dev/null
+++ b/keystore/tests/src/android/security/keystore2/AndroidKeyStoreSpiTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keystore2;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyLong;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.security.KeyStore2;
+import android.security.KeyStoreException;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+public class AndroidKeyStoreSpiTest {
+
+ @Mock
+ private KeyStore2 mKeystore2;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void testEngineAliasesReturnsEmptySetOnKeyStoreError() throws Exception {
+ when(mKeystore2.list(anyInt(), anyLong()))
+ .thenThrow(new KeyStoreException(6, "Some Error"));
+ AndroidKeyStoreSpi spi = new AndroidKeyStoreSpi();
+ spi.initForTesting(mKeystore2);
+
+ assertThat("Empty collection expected", !spi.engineAliases().hasMoreElements());
+
+ verify(mKeystore2).list(anyInt(), anyLong());
+ }
+
+}
diff --git a/libs/androidfw/OWNERS b/libs/androidfw/OWNERS
index bc056df23a36..610fd80fe73c 100644
--- a/libs/androidfw/OWNERS
+++ b/libs/androidfw/OWNERS
@@ -1,6 +1,7 @@
set noparent
toddke@google.com
rtmitchell@google.com
+patb@google.com
per-file CursorWindow.cpp=omakoto@google.com
per-file LocaleDataTables.cpp=vichang@google.com,ngeoffray@google.com,nikitai@google.com
diff --git a/packages/Connectivity/framework/api/module-lib-current.txt b/packages/Connectivity/framework/api/module-lib-current.txt
index b219375aed70..6c454bcd4cd7 100644
--- a/packages/Connectivity/framework/api/module-lib-current.txt
+++ b/packages/Connectivity/framework/api/module-lib-current.txt
@@ -48,6 +48,7 @@ package android.net {
public class ConnectivitySettingsManager {
method public static void clearGlobalProxy(@NonNull android.content.Context);
+ method @NonNull public static java.util.Set<java.lang.String> getAppsAllowedOnRestrictedNetworks(@NonNull android.content.Context);
method @Nullable public static String getCaptivePortalHttpUrl(@NonNull android.content.Context);
method public static int getCaptivePortalMode(@NonNull android.content.Context, int);
method @NonNull public static java.time.Duration getConnectivityKeepPendingIntentDuration(@NonNull android.content.Context, @NonNull java.time.Duration);
@@ -65,9 +66,9 @@ package android.net {
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 @NonNull public static java.util.Set<java.lang.String> getRestrictedAllowedApps(@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);
@@ -85,7 +86,6 @@ package android.net {
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 setRestrictedAllowedApps(@NonNull android.content.Context, @NonNull java.util.Set<java.lang.String>);
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
diff --git a/packages/Connectivity/framework/api/system-current.txt b/packages/Connectivity/framework/api/system-current.txt
index 5750845c5863..27bf114b5229 100644
--- a/packages/Connectivity/framework/api/system-current.txt
+++ b/packages/Connectivity/framework/api/system-current.txt
@@ -294,7 +294,6 @@ package android.net {
method @NonNull public android.net.NetworkCapabilities.Builder addCapability(int);
method @NonNull public android.net.NetworkCapabilities.Builder addTransportType(int);
method @NonNull public android.net.NetworkCapabilities build();
- method @NonNull public android.net.NetworkCapabilities.Builder clearAll();
method @NonNull public android.net.NetworkCapabilities.Builder removeCapability(int);
method @NonNull public android.net.NetworkCapabilities.Builder removeTransportType(int);
method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setAdministratorUids(@NonNull int[]);
@@ -308,6 +307,7 @@ package android.net {
method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setSsid(@Nullable String);
method @NonNull public android.net.NetworkCapabilities.Builder setSubscriptionIds(@NonNull java.util.Set<java.lang.Integer>);
method @NonNull public android.net.NetworkCapabilities.Builder setTransportInfo(@Nullable android.net.TransportInfo);
+ method @NonNull public static android.net.NetworkCapabilities.Builder withoutDefaultCapabilities();
}
public class NetworkProvider {
@@ -381,6 +381,7 @@ package android.net {
public abstract class QosFilter {
method @NonNull public abstract android.net.Network getNetwork();
method public abstract boolean matchesLocalAddress(@NonNull java.net.InetAddress, int, int);
+ method public abstract boolean matchesRemoteAddress(@NonNull java.net.InetAddress, int, int);
}
public final class QosSession implements android.os.Parcelable {
@@ -403,6 +404,7 @@ package android.net {
method public int describeContents();
method @NonNull public java.net.InetSocketAddress getLocalSocketAddress();
method @NonNull public android.net.Network getNetwork();
+ method @Nullable public java.net.InetSocketAddress getRemoteSocketAddress();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.QosSocketInfo> CREATOR;
}
diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
index 0a3e23123702..1a6b37bfdb42 100644
--- a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
+++ b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
@@ -3337,7 +3337,60 @@ public class ConnectivityManager {
provider.setProviderId(NetworkProvider.ID_NONE);
}
+ /**
+ * Register or update a network offer with ConnectivityService.
+ *
+ * ConnectivityService keeps track of offers made by the various providers and matches
+ * them to networking requests made by apps or the system. The provider supplies a score
+ * and the capabilities of the network it might be able to bring up ; these act as filters
+ * used by ConnectivityService to only send those requests that can be fulfilled by the
+ * provider.
+ *
+ * The provider is under no obligation to be able to bring up the network it offers at any
+ * given time. Instead, this mechanism is meant to limit requests received by providers
+ * to those they actually have a chance to fulfill, as providers don't have a way to compare
+ * the quality of the network satisfying a given request to their own offer.
+ *
+ * An offer can be updated by calling this again with the same callback object. This is
+ * similar to calling unofferNetwork and offerNetwork again, but will only update the
+ * provider with the changes caused by the changes in the offer.
+ *
+ * @param provider The provider making this offer.
+ * @param score The prospective score of the network.
+ * @param caps The prospective capabilities of the network.
+ * @param callback The callback to call when this offer is needed or unneeded.
+ * @hide
+ */
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_FACTORY})
+ public void offerNetwork(@NonNull final NetworkProvider provider,
+ @NonNull final NetworkScore score, @NonNull final NetworkCapabilities caps,
+ @NonNull final INetworkOfferCallback callback) {
+ try {
+ mService.offerNetwork(Objects.requireNonNull(provider.getMessenger(), "null messenger"),
+ Objects.requireNonNull(score, "null score"),
+ Objects.requireNonNull(caps, "null caps"),
+ Objects.requireNonNull(callback, "null callback"));
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ /**
+ * Withdraw a network offer made with {@link #offerNetwork}.
+ *
+ * @param callback The callback passed at registration time. This must be the same object
+ * that was passed to {@link #offerNetwork}
+ * @hide
+ */
+ public void unofferNetwork(@NonNull final INetworkOfferCallback callback) {
+ try {
+ mService.unofferNetwork(Objects.requireNonNull(callback));
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
/** @hide exposed via the NetworkProvider class. */
@RequiresPermission(anyOf = {
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
diff --git a/packages/Connectivity/framework/src/android/net/ConnectivitySettingsManager.java b/packages/Connectivity/framework/src/android/net/ConnectivitySettingsManager.java
index 07754e4af2ff..762f24f7e79a 100644
--- a/packages/Connectivity/framework/src/android/net/ConnectivitySettingsManager.java
+++ b/packages/Connectivity/framework/src/android/net/ConnectivitySettingsManager.java
@@ -43,7 +43,6 @@ import java.time.Duration;
import java.util.List;
import java.util.Set;
import java.util.StringJoiner;
-import java.util.regex.Pattern;
/**
* A manager class for connectivity module settings.
@@ -375,11 +374,12 @@ public class ConnectivitySettingsManager {
private static final String PRIVATE_DNS_MODE_PROVIDER_HOSTNAME_STRING = "hostname";
/**
- * A list of apps that should be granted netd system permission for using restricted networks.
+ * A list of apps that is allowed on restricted networks.
*
* @hide
*/
- public static final String RESTRICTED_ALLOWED_APPS = "restricted_allowed_apps";
+ public static final String APPS_ALLOWED_ON_RESTRICTED_NETWORKS =
+ "apps_allowed_on_restricted_networks";
/**
* Get mobile data activity timeout from {@link Settings}.
@@ -1047,17 +1047,16 @@ public class ConnectivitySettingsManager {
}
/**
- * Get the list of apps(from {@link Settings}) that should be granted netd system permission for
- * using restricted networks.
+ * 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 should be granted netd system permission for using restricted
- * networks or null if no setting value.
+ * @return A list of apps that is allowed on restricted networks or null if no setting
+ * value.
*/
@NonNull
- public static Set<String> getRestrictedAllowedApps(@NonNull Context context) {
+ public static Set<String> getAppsAllowedOnRestrictedNetworks(@NonNull Context context) {
final String appList = Settings.Secure.getString(
- context.getContentResolver(), RESTRICTED_ALLOWED_APPS);
+ context.getContentResolver(), APPS_ALLOWED_ON_RESTRICTED_NETWORKS);
if (TextUtils.isEmpty(appList)) {
return new ArraySet<>();
}
@@ -1065,27 +1064,24 @@ public class ConnectivitySettingsManager {
}
/**
- * Set the list of apps(from {@link Settings}) that should be granted netd system permission for
- * using restricted networks.
+ * 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 should be granted netd system permission for using
- * restricted networks.
+ * @param list A list of apps that is allowed on restricted networks.
*/
- public static void setRestrictedAllowedApps(@NonNull Context context,
+ public static void setAppsAllowedOnRestrictedNetworks(@NonNull Context context,
@NonNull Set<String> list) {
- final Pattern appPattern = Pattern.compile("[a-zA-Z_0-9]+([.][a-zA-Z_0-9]+)*");
final StringJoiner joiner = new StringJoiner(";");
for (String app : list) {
- if (!appPattern.matcher(app).matches()) {
+ if (app == null || app.contains(";")) {
throw new IllegalArgumentException("Invalid app(package name)");
}
joiner.add(app);
}
- Settings.Secure.putString(
- context.getContentResolver(), RESTRICTED_ALLOWED_APPS, joiner.toString());
+ Settings.Secure.putString(context.getContentResolver(), APPS_ALLOWED_ON_RESTRICTED_NETWORKS,
+ joiner.toString());
}
}
diff --git a/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl b/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl
index a7cb618f9790..d937c9cd78c0 100644
--- a/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl
+++ b/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl
@@ -23,6 +23,7 @@ import android.net.IConnectivityDiagnosticsCallback;
import android.net.INetworkAgent;
import android.net.IOnCompleteListener;
import android.net.INetworkActivityListener;
+import android.net.INetworkOfferCallback;
import android.net.IQosCallback;
import android.net.ISocketKeepaliveCallback;
import android.net.LinkProperties;
@@ -221,4 +222,8 @@ interface IConnectivityManager
in IOnCompleteListener listener);
int getRestrictBackgroundStatusByCaller();
+
+ void offerNetwork(in Messenger messenger, in NetworkScore score,
+ in NetworkCapabilities caps, in INetworkOfferCallback callback);
+ void unofferNetwork(in INetworkOfferCallback callback);
}
diff --git a/packages/Connectivity/framework/src/android/net/INetworkOfferCallback.aidl b/packages/Connectivity/framework/src/android/net/INetworkOfferCallback.aidl
new file mode 100644
index 000000000000..67d2d405dbed
--- /dev/null
+++ b/packages/Connectivity/framework/src/android/net/INetworkOfferCallback.aidl
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.net.NetworkRequest;
+
+/**
+ * A callback registered with connectivity by network providers together with
+ * a NetworkOffer.
+ *
+ * When the offer is needed to satisfy some application or system component,
+ * connectivity will call onOfferNeeded on this callback. When this happens,
+ * the provider should try and bring up the network.
+ *
+ * When the offer is no longer needed, for example because the application has
+ * withdrawn the request or if the request is being satisfied by a network
+ * that this offer will never be able to beat, connectivity calls
+ * onOfferUnneeded. When this happens, the provider should stop trying to
+ * bring up the network, or tear it down if it has already been brought up.
+ *
+ * When NetworkProvider#offerNetwork is called, the provider can expect to
+ * immediately receive all requests that can be fulfilled by that offer and
+ * are not already satisfied by a better network. It is possible no such
+ * request is currently outstanding, because no requests have been made that
+ * can be satisfied by this offer, or because all such requests are already
+ * satisfied by a better network.
+ * onOfferNeeded can be called at any time after registration and until the
+ * offer is withdrawn with NetworkProvider#unofferNetwork is called. This
+ * typically happens when a new network request is filed by an application,
+ * or when the network satisfying a request disconnects and this offer now
+ * stands a chance to be the best network for it.
+ *
+ * @hide
+ */
+oneway interface INetworkOfferCallback {
+ /**
+ * Informs the registrant that the offer is needed to fulfill this request.
+ * @param networkRequest the request to satisfy
+ * @param providerId the ID of the provider currently satisfying
+ * this request, or NetworkProvider.ID_NONE if none.
+ */
+ void onOfferNeeded(in NetworkRequest networkRequest, int providerId);
+
+ /**
+ * Informs the registrant that the offer is no longer needed to fulfill this request.
+ */
+ void onOfferUnneeded(in NetworkRequest networkRequest);
+}
diff --git a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java
index 4a99d290f38c..90d821bd3b1e 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java
@@ -139,19 +139,13 @@ public final class NetworkCapabilities implements Parcelable {
*/
private String mRequestorPackageName;
- /**
- * Indicates what fields should be redacted from this instance.
- */
- private final @RedactionType long mRedactions;
-
public NetworkCapabilities() {
- mRedactions = REDACT_ALL;
clearAll();
mNetworkCapabilities = DEFAULT_CAPABILITIES;
}
public NetworkCapabilities(NetworkCapabilities nc) {
- this(nc, REDACT_ALL);
+ this(nc, REDACT_NONE);
}
/**
@@ -163,10 +157,12 @@ public final class NetworkCapabilities implements Parcelable {
* @hide
*/
public NetworkCapabilities(@Nullable NetworkCapabilities nc, @RedactionType long redactions) {
- mRedactions = redactions;
if (nc != null) {
set(nc);
}
+ if (mTransportInfo != null) {
+ mTransportInfo = nc.mTransportInfo.makeCopy(redactions);
+ }
}
/**
@@ -175,14 +171,6 @@ public final class NetworkCapabilities implements Parcelable {
* @hide
*/
public void clearAll() {
- // Ensures that the internal copies maintained by the connectivity stack does not set it to
- // anything other than |REDACT_ALL|.
- if (mRedactions != REDACT_ALL) {
- // This is needed because the current redaction mechanism relies on redaction while
- // parceling.
- throw new UnsupportedOperationException(
- "Cannot clear NetworkCapabilities when mRedactions is set");
- }
mNetworkCapabilities = mTransportTypes = mForbiddenNetworkCapabilities = 0;
mLinkUpBandwidthKbps = mLinkDownBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED;
mNetworkSpecifier = null;
@@ -211,7 +199,7 @@ public final class NetworkCapabilities implements Parcelable {
mLinkDownBandwidthKbps = nc.mLinkDownBandwidthKbps;
mNetworkSpecifier = nc.mNetworkSpecifier;
if (nc.getTransportInfo() != null) {
- setTransportInfo(nc.getTransportInfo().makeCopy(mRedactions));
+ setTransportInfo(nc.getTransportInfo());
} else {
setTransportInfo(null);
}
@@ -2411,6 +2399,11 @@ public final class NetworkCapabilities implements Parcelable {
return mTransportInfo.getApplicableRedactions();
}
+ private NetworkCapabilities removeDefaultCapabilites() {
+ mNetworkCapabilities &= ~DEFAULT_CAPABILITIES;
+ return this;
+ }
+
/**
* Builder class for NetworkCapabilities.
*
@@ -2447,6 +2440,16 @@ public final class NetworkCapabilities implements Parcelable {
}
/**
+ * Creates a new Builder without the default capabilities.
+ */
+ @NonNull
+ public static Builder withoutDefaultCapabilities() {
+ final NetworkCapabilities nc = new NetworkCapabilities();
+ nc.removeDefaultCapabilites();
+ return new Builder(nc);
+ }
+
+ /**
* Adds the given transport type.
*
* Multiple transports may be added. Note that when searching for a network to satisfy a
@@ -2507,17 +2510,6 @@ public final class NetworkCapabilities implements Parcelable {
}
/**
- * Completely clears the contents of this object, removing even the capabilities that are
- * set by default when the object is constructed.
- * @return this builder
- */
- @NonNull
- public Builder clearAll() {
- mCaps.clearAll();
- return this;
- }
-
- /**
* Sets the owner UID.
*
* The default value is {@link Process#INVALID_UID}. Pass this value to reset.
diff --git a/packages/Connectivity/framework/src/android/net/NetworkProvider.java b/packages/Connectivity/framework/src/android/net/NetworkProvider.java
index 14cb51c85d06..8f93047cf850 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkProvider.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkProvider.java
@@ -28,6 +28,11 @@ import android.os.Message;
import android.os.Messenger;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.ArrayList;
+import java.util.concurrent.Executor;
+
/**
* Base class for network providers such as telephony or Wi-Fi. NetworkProviders connect the device
* to networks and makes them available to the core network stack by creating
@@ -78,7 +83,9 @@ public class NetworkProvider {
*/
@SystemApi
public NetworkProvider(@NonNull Context context, @NonNull Looper looper, @NonNull String name) {
- Handler handler = new Handler(looper) {
+ // TODO (b/174636568) : this class should be able to cache an instance of
+ // ConnectivityManager so it doesn't have to fetch it again every time.
+ final Handler handler = new Handler(looper) {
@Override
public void handleMessage(Message m) {
switch (m.what) {
@@ -159,4 +166,148 @@ public class NetworkProvider {
public void declareNetworkRequestUnfulfillable(@NonNull NetworkRequest request) {
ConnectivityManager.from(mContext).declareNetworkRequestUnfulfillable(request);
}
+
+ /** @hide */
+ // TODO : make @SystemApi when the impl is complete
+ public interface NetworkOfferCallback {
+ /** Called by the system when this offer is needed to satisfy some networking request. */
+ void onOfferNeeded(@NonNull NetworkRequest request, int providerId);
+ /** Called by the system when this offer is no longer needed. */
+ void onOfferUnneeded(@NonNull NetworkRequest request);
+ }
+
+ private class NetworkOfferCallbackProxy extends INetworkOfferCallback.Stub {
+ @NonNull public final NetworkOfferCallback callback;
+ @NonNull private final Executor mExecutor;
+
+ NetworkOfferCallbackProxy(@NonNull final NetworkOfferCallback callback,
+ @NonNull final Executor executor) {
+ this.callback = callback;
+ this.mExecutor = executor;
+ }
+
+ @Override
+ public void onOfferNeeded(final @NonNull NetworkRequest request,
+ final int providerId) {
+ mExecutor.execute(() -> callback.onOfferNeeded(request, providerId));
+ }
+
+ @Override
+ public void onOfferUnneeded(final @NonNull NetworkRequest request) {
+ mExecutor.execute(() -> callback.onOfferUnneeded(request));
+ }
+ }
+
+ @GuardedBy("mProxies")
+ @NonNull private final ArrayList<NetworkOfferCallbackProxy> mProxies = new ArrayList<>();
+
+ // Returns the proxy associated with this callback, or null if none.
+ @Nullable
+ private NetworkOfferCallbackProxy findProxyForCallback(@NonNull final NetworkOfferCallback cb) {
+ synchronized (mProxies) {
+ for (final NetworkOfferCallbackProxy p : mProxies) {
+ if (p.callback == cb) return p;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Register or update an offer for network with the passed caps and score.
+ *
+ * A NetworkProvider's job is to provide networks. This function is how a provider tells the
+ * connectivity stack what kind of network it may provide. The score and caps arguments act
+ * as filters that the connectivity stack uses to tell when the offer is necessary. When an
+ * offer might be advantageous over existing networks, the provider will receive a call to
+ * the associated callback's {@link NetworkOfferCallback#onOfferNeeded} method. The provider
+ * should then try to bring up this network. When an offer is no longer needed, the stack
+ * will inform the provider by calling {@link NetworkOfferCallback#onOfferUnneeded}. The
+ * provider should stop trying to bring up such a network, or disconnect it if it already has
+ * one.
+ *
+ * The stack determines what offers are needed according to what networks are currently
+ * available to the system, and what networking requests are made by applications. If an
+ * offer looks like it could be a better choice than any existing network for any particular
+ * request, that's when the stack decides the offer is needed. If the current networking
+ * requests are all satisfied by networks that this offer can't possibly be a better match
+ * for, that's when the offer is unneeded. An offer starts off as unneeded ; the provider
+ * should not try to bring up the network until {@link NetworkOfferCallback#onOfferNeeded}
+ * is called.
+ *
+ * Note that the offers are non-binding to the providers, in particular because providers
+ * often don't know if they will be able to bring up such a network at any given time. For
+ * example, no wireless network may be in range when the offer is needed. This is fine and
+ * expected ; the provider should simply continue to try to bring up the network and do so
+ * if/when it becomes possible. In the mean time, the stack will continue to satisfy requests
+ * with the best network currently available, or if none, keep the apps informed that no
+ * network can currently satisfy this request. When/if the provider can bring up the network,
+ * the connectivity stack will match it against requests, and inform interested apps of the
+ * availability of this network. This may, in turn, render the offer of some other provider
+ * unneeded if all requests it used to satisfy are now better served by this network.
+ *
+ * A network can become unneeded for a reason like the above : whether the provider managed
+ * to bring up the offered network after it became needed or not, some other provider may
+ * bring up a better network than this one, making this offer unneeded. A network may also
+ * become unneeded if the application making the request withdrew it (for example, after it
+ * is done transferring data, or if the user canceled an operation).
+ *
+ * The capabilities and score act as filters as to what requests the provider will see.
+ * They are not promises, but for best performance, the providers should strive to put
+ * as much known information as possible in the offer. For capabilities in particular, it
+ * should put all NetworkAgent-managed capabilities a network may have, even if it doesn't
+ * have them at first. This applies to INTERNET, for example ; if a provider thinks the
+ * network it can bring up for this offer may offer Internet access it should include the
+ * INTERNET bit. It's fine if the brought up network ends up not actually having INTERNET.
+ *
+ * TODO : in the future, to avoid possible infinite loops, there should be constraints on
+ * what can be put in capabilities of networks brought up for an offer. If a provider might
+ * bring up a network with or without INTERNET, then it should file two offers : this will
+ * let it know precisely what networks are needed, so it can avoid bringing up networks that
+ * won't actually satisfy requests and remove the risk for bring-up-bring-down loops.
+ *
+ * @hide
+ */
+ // TODO : make @SystemApi when the impl is complete
+ @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+ public void offerNetwork(@NonNull final NetworkScore score,
+ @NonNull final NetworkCapabilities caps, @NonNull final Executor executor,
+ @NonNull final NetworkOfferCallback callback) {
+ NetworkOfferCallbackProxy proxy = null;
+ synchronized (mProxies) {
+ for (final NetworkOfferCallbackProxy existingProxy : mProxies) {
+ if (existingProxy.callback == callback) {
+ proxy = existingProxy;
+ break;
+ }
+ }
+ if (null == proxy) {
+ proxy = new NetworkOfferCallbackProxy(callback, executor);
+ mProxies.add(proxy);
+ }
+ }
+ mContext.getSystemService(ConnectivityManager.class).offerNetwork(this, score, caps, proxy);
+ }
+
+ /**
+ * Withdraw a network offer previously made to the networking stack.
+ *
+ * If a provider can no longer provide a network they offered, it should call this method.
+ * An example of usage could be if the hardware necessary to bring up the network was turned
+ * off in UI by the user. Note that because offers are never binding, the provider might
+ * alternatively decide not to withdraw this offer and simply refuse to bring up the network
+ * even when it's needed. However, withdrawing the request is slightly more resource-efficient
+ * because the networking stack won't have to compare this offer to exiting networks to see
+ * if it could beat any of them, and may be advantageous to the provider's implementation that
+ * can rely on no longer receiving callbacks for a network that they can't bring up anyways.
+ *
+ * @hide
+ */
+ // TODO : make @SystemApi when the impl is complete
+ @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+ public void unofferNetwork(final @NonNull NetworkOfferCallback callback) {
+ final NetworkOfferCallbackProxy proxy = findProxyForCallback(callback);
+ if (null == proxy) return;
+ mProxies.remove(proxy);
+ mContext.getSystemService(ConnectivityManager.class).unofferNetwork(proxy);
+ }
}
diff --git a/packages/Connectivity/framework/src/android/net/NetworkRequest.java b/packages/Connectivity/framework/src/android/net/NetworkRequest.java
index dd88c5a5c94e..e6a96ef74869 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkRequest.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkRequest.java
@@ -200,8 +200,9 @@ public class NetworkRequest implements Parcelable {
private final NetworkCapabilities mNetworkCapabilities;
- // A boolean that represents the user modified NOT_VCN_MANAGED capability.
- private boolean mModifiedNotVcnManaged = false;
+ // A boolean that represents whether the NOT_VCN_MANAGED capability should be deduced when
+ // the NetworkRequest object is built.
+ private boolean mShouldDeduceNotVcnManaged = true;
/**
* Default constructor for Builder.
@@ -223,7 +224,7 @@ public class NetworkRequest implements Parcelable {
// If the caller constructed the builder from a request, it means the user
// might explicitly want the capabilities from the request. Thus, the NOT_VCN_MANAGED
// capabilities should not be touched later.
- mModifiedNotVcnManaged = true;
+ mShouldDeduceNotVcnManaged = false;
}
/**
@@ -254,7 +255,7 @@ public class NetworkRequest implements Parcelable {
public Builder addCapability(@NetworkCapabilities.NetCapability int capability) {
mNetworkCapabilities.addCapability(capability);
if (capability == NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) {
- mModifiedNotVcnManaged = true;
+ mShouldDeduceNotVcnManaged = false;
}
return this;
}
@@ -268,7 +269,7 @@ public class NetworkRequest implements Parcelable {
public Builder removeCapability(@NetworkCapabilities.NetCapability int capability) {
mNetworkCapabilities.removeCapability(capability);
if (capability == NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) {
- mModifiedNotVcnManaged = true;
+ mShouldDeduceNotVcnManaged = false;
}
return this;
}
@@ -352,7 +353,7 @@ public class NetworkRequest implements Parcelable {
mNetworkCapabilities.clearAll();
// If the caller explicitly clear all capabilities, the NOT_VCN_MANAGED capabilities
// should not be add back later.
- mModifiedNotVcnManaged = true;
+ mShouldDeduceNotVcnManaged = false;
return this;
}
@@ -453,6 +454,9 @@ public class NetworkRequest implements Parcelable {
throw new IllegalArgumentException("A MatchAllNetworkSpecifier is not permitted");
}
mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
+ // Do not touch NOT_VCN_MANAGED if the caller needs to access to a very specific
+ // Network.
+ mShouldDeduceNotVcnManaged = false;
return this;
}
@@ -486,12 +490,13 @@ public class NetworkRequest implements Parcelable {
* {@link #VCN_SUPPORTED_CAPABILITIES}, add the NET_CAPABILITY_NOT_VCN_MANAGED to
* allow the callers automatically utilize VCN networks if available.
* 2. For the requests that explicitly add or remove NET_CAPABILITY_NOT_VCN_MANAGED,
+ * or has clear intention of tracking specific network,
* do not alter them to allow user fire request that suits their need.
*
* @hide
*/
private void deduceNotVcnManagedCapability(final NetworkCapabilities nc) {
- if (mModifiedNotVcnManaged) return;
+ if (!mShouldDeduceNotVcnManaged) return;
for (final int cap : nc.getCapabilities()) {
if (!VCN_SUPPORTED_CAPABILITIES.contains(cap)) return;
}
diff --git a/packages/Connectivity/framework/src/android/net/QosFilter.java b/packages/Connectivity/framework/src/android/net/QosFilter.java
index ab55002e02b3..957c867f206d 100644
--- a/packages/Connectivity/framework/src/android/net/QosFilter.java
+++ b/packages/Connectivity/framework/src/android/net/QosFilter.java
@@ -71,5 +71,16 @@ public abstract class QosFilter {
*/
public abstract boolean matchesLocalAddress(@NonNull InetAddress address,
int startPort, int endPort);
+
+ /**
+ * Determines whether or not the parameters is a match for the filter.
+ *
+ * @param address the remote address
+ * @param startPort the start of the port range
+ * @param endPort the end of the port range
+ * @return whether the parameters match the remote address of the filter
+ */
+ public abstract boolean matchesRemoteAddress(@NonNull InetAddress address,
+ int startPort, int endPort);
}
diff --git a/packages/Connectivity/framework/src/android/net/QosSocketFilter.java b/packages/Connectivity/framework/src/android/net/QosSocketFilter.java
index 2080e68f5fba..69da7f440185 100644
--- a/packages/Connectivity/framework/src/android/net/QosSocketFilter.java
+++ b/packages/Connectivity/framework/src/android/net/QosSocketFilter.java
@@ -138,13 +138,26 @@ public class QosSocketFilter extends QosFilter {
if (mQosSocketInfo.getLocalSocketAddress() == null) {
return false;
}
+ return matchesAddress(mQosSocketInfo.getLocalSocketAddress(), address, startPort,
+ endPort);
+ }
- return matchesLocalAddress(mQosSocketInfo.getLocalSocketAddress(), address, startPort,
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public boolean matchesRemoteAddress(@NonNull final InetAddress address, final int startPort,
+ final int endPort) {
+ if (mQosSocketInfo.getRemoteSocketAddress() == null) {
+ return false;
+ }
+ return matchesAddress(mQosSocketInfo.getRemoteSocketAddress(), address, startPort,
endPort);
}
/**
- * Called from {@link QosSocketFilter#matchesLocalAddress(InetAddress, int, int)} with the
+ * Called from {@link QosSocketFilter#matchesLocalAddress(InetAddress, int, int)}
+ * and {@link QosSocketFilter#matchesRemoteAddress(InetAddress, int, int)} with the
* filterSocketAddress coming from {@link QosSocketInfo#getLocalSocketAddress()}.
* <p>
* This method exists for testing purposes since {@link QosSocketInfo} couldn't be mocked
@@ -156,7 +169,7 @@ public class QosSocketFilter extends QosFilter {
* @param endPort the end of the port range to check
*/
@VisibleForTesting
- public static boolean matchesLocalAddress(@NonNull final InetSocketAddress filterSocketAddress,
+ public static boolean matchesAddress(@NonNull final InetSocketAddress filterSocketAddress,
@NonNull final InetAddress address,
final int startPort, final int endPort) {
return startPort <= filterSocketAddress.getPort()
diff --git a/packages/Connectivity/framework/src/android/net/QosSocketInfo.java b/packages/Connectivity/framework/src/android/net/QosSocketInfo.java
index 53d966937a70..a45d5075d6c7 100644
--- a/packages/Connectivity/framework/src/android/net/QosSocketInfo.java
+++ b/packages/Connectivity/framework/src/android/net/QosSocketInfo.java
@@ -17,6 +17,7 @@
package android.net;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
@@ -32,7 +33,8 @@ import java.util.Objects;
/**
* Used in conjunction with
* {@link ConnectivityManager#registerQosCallback}
- * in order to receive Qos Sessions related to the local address and port of a bound {@link Socket}.
+ * in order to receive Qos Sessions related to the local address and port of a bound {@link Socket}
+ * and/or remote address and port of a connected {@link Socket}.
*
* @hide
*/
@@ -48,6 +50,9 @@ public final class QosSocketInfo implements Parcelable {
@NonNull
private final InetSocketAddress mLocalSocketAddress;
+ @Nullable
+ private final InetSocketAddress mRemoteSocketAddress;
+
/**
* The {@link Network} the socket is on.
*
@@ -81,6 +86,18 @@ public final class QosSocketInfo implements Parcelable {
}
/**
+ * The remote address of the socket passed into {@link QosSocketInfo(Network, Socket)}.
+ * The value does not reflect any changes that occur to the socket after it is first set
+ * in the constructor.
+ *
+ * @return the remote address of the socket if socket is connected, null otherwise
+ */
+ @Nullable
+ public InetSocketAddress getRemoteSocketAddress() {
+ return mRemoteSocketAddress;
+ }
+
+ /**
* Creates a {@link QosSocketInfo} given a {@link Network} and bound {@link Socket}. The
* {@link Socket} must remain bound in order to receive {@link QosSession}s.
*
@@ -95,6 +112,12 @@ public final class QosSocketInfo implements Parcelable {
mParcelFileDescriptor = ParcelFileDescriptor.fromSocket(socket);
mLocalSocketAddress =
new InetSocketAddress(socket.getLocalAddress(), socket.getLocalPort());
+
+ if (socket.isConnected()) {
+ mRemoteSocketAddress = (InetSocketAddress) socket.getRemoteSocketAddress();
+ } else {
+ mRemoteSocketAddress = null;
+ }
}
/* Parcelable methods */
@@ -102,11 +125,15 @@ public final class QosSocketInfo implements Parcelable {
mNetwork = Objects.requireNonNull(Network.CREATOR.createFromParcel(in));
mParcelFileDescriptor = ParcelFileDescriptor.CREATOR.createFromParcel(in);
- final int addressLength = in.readInt();
- mLocalSocketAddress = readSocketAddress(in, addressLength);
+ final int localAddressLength = in.readInt();
+ mLocalSocketAddress = readSocketAddress(in, localAddressLength);
+
+ final int remoteAddressLength = in.readInt();
+ mRemoteSocketAddress = remoteAddressLength == 0 ? null
+ : readSocketAddress(in, remoteAddressLength);
}
- private InetSocketAddress readSocketAddress(final Parcel in, final int addressLength) {
+ private @NonNull InetSocketAddress readSocketAddress(final Parcel in, final int addressLength) {
final byte[] address = new byte[addressLength];
in.readByteArray(address);
final int port = in.readInt();
@@ -130,10 +157,19 @@ public final class QosSocketInfo implements Parcelable {
mNetwork.writeToParcel(dest, 0);
mParcelFileDescriptor.writeToParcel(dest, 0);
- final byte[] address = mLocalSocketAddress.getAddress().getAddress();
- dest.writeInt(address.length);
- dest.writeByteArray(address);
+ final byte[] localAddress = mLocalSocketAddress.getAddress().getAddress();
+ dest.writeInt(localAddress.length);
+ dest.writeByteArray(localAddress);
dest.writeInt(mLocalSocketAddress.getPort());
+
+ if (mRemoteSocketAddress == null) {
+ dest.writeInt(0);
+ } else {
+ final byte[] remoteAddress = mRemoteSocketAddress.getAddress().getAddress();
+ dest.writeInt(remoteAddress.length);
+ dest.writeByteArray(remoteAddress);
+ dest.writeInt(mRemoteSocketAddress.getPort());
+ }
}
@NonNull
diff --git a/packages/Connectivity/service/Android.bp b/packages/Connectivity/service/Android.bp
index 1330e719e774..513de1956952 100644
--- a/packages/Connectivity/service/Android.bp
+++ b/packages/Connectivity/service/Android.bp
@@ -52,8 +52,8 @@ cc_library_shared {
java_library {
name: "service-connectivity-pre-jarjar",
srcs: [
+ "src/**/*.java",
":framework-connectivity-shared-srcs",
- ":connectivity-service-srcs",
],
libs: [
"android.net.ipsec.ike",
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/packages/Connectivity/service/src/com/android/server/ConnectivityService.java
index 39a990cf5d73..e192c8fae266 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/packages/Connectivity/service/src/com/android/server/ConnectivityService.java
@@ -15,7 +15,6 @@
*/
package com.android.server;
-
import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
import static android.content.pm.PackageManager.FEATURE_BLUETOOTH;
import static android.content.pm.PackageManager.FEATURE_WATCH;
@@ -125,6 +124,7 @@ import android.net.INetworkActivityListener;
import android.net.INetworkAgent;
import android.net.INetworkMonitor;
import android.net.INetworkMonitorCallbacks;
+import android.net.INetworkOfferCallback;
import android.net.IOnCompleteListener;
import android.net.IQosCallback;
import android.net.ISocketKeepaliveCallback;
@@ -234,6 +234,7 @@ import com.android.net.module.util.PermissionUtils;
import com.android.server.connectivity.AutodestructReference;
import com.android.server.connectivity.DnsManager;
import com.android.server.connectivity.DnsManager.PrivateDnsValidationUpdate;
+import com.android.server.connectivity.FullScore;
import com.android.server.connectivity.KeepaliveTracker;
import com.android.server.connectivity.LingerMonitor;
import com.android.server.connectivity.MockableSystemProperties;
@@ -241,6 +242,7 @@ import com.android.server.connectivity.NetworkAgentInfo;
import com.android.server.connectivity.NetworkDiagnostics;
import com.android.server.connectivity.NetworkNotificationManager;
import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
+import com.android.server.connectivity.NetworkOffer;
import com.android.server.connectivity.NetworkRanker;
import com.android.server.connectivity.PermissionMonitor;
import com.android.server.connectivity.ProfileNetworkPreferences;
@@ -604,6 +606,18 @@ public class ConnectivityService extends IConnectivityManager.Stub
private static final int EVENT_UID_BLOCKED_REASON_CHANGED = 51;
/**
+ * Event to register a new network offer
+ * obj = NetworkOffer
+ */
+ private static final int EVENT_REGISTER_NETWORK_OFFER = 52;
+
+ /**
+ * Event to unregister an existing network offer
+ * obj = INetworkOfferCallback
+ */
+ private static final int EVENT_UNREGISTER_NETWORK_OFFER = 53;
+
+ /**
* Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
* should be shown.
*/
@@ -1031,14 +1045,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
} else {
// ConnectivityService publishes binder service using publishBinderService() with
// no priority assigned will be treated as NORMAL priority. Dumpsys does not send
- // "--dump-priority" arguments to the service. Thus, dump both NORMAL and HIGH to
- // align the legacy design.
+ // "--dump-priority" arguments to the service. Thus, dump NORMAL only to align the
+ // legacy output for dumpsys connectivity.
// TODO: Integrate into signal dump.
dumpNormal(fd, pw, args);
- pw.println();
- pw.println("DUMP OF SERVICE HIGH connectivity");
- pw.println();
- dumpHigh(fd, pw);
}
}
}
@@ -1380,7 +1390,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// arguments like the handler or the DnsResolver.
// TODO : remove this ; it is probably better handled with a sentinel request.
mNoServiceNetwork = new NetworkAgentInfo(null,
- new Network(NO_SERVICE_NET_ID),
+ new Network(INetd.UNREACHABLE_NET_ID),
new NetworkInfo(TYPE_NONE, 0, "", ""),
new LinkProperties(), new NetworkCapabilities(),
new NetworkScore.Builder().setLegacyInt(0).build(), mContext, null,
@@ -4684,6 +4694,18 @@ public class ConnectivityService extends IConnectivityManager.Stub
handleUnregisterNetworkProvider((Messenger) msg.obj);
break;
}
+ case EVENT_REGISTER_NETWORK_OFFER: {
+ handleRegisterNetworkOffer((NetworkOffer) msg.obj);
+ break;
+ }
+ case EVENT_UNREGISTER_NETWORK_OFFER: {
+ final NetworkOfferInfo offer =
+ findNetworkOfferInfoByCallback((INetworkOfferCallback) msg.obj);
+ if (null != offer) {
+ handleUnregisterNetworkOffer(offer);
+ }
+ break;
+ }
case EVENT_REGISTER_NETWORK_AGENT: {
final Pair<NetworkAgentInfo, INetworkMonitor> arg =
(Pair<NetworkAgentInfo, INetworkMonitor>) msg.obj;
@@ -6214,12 +6236,37 @@ public class ConnectivityService extends IConnectivityManager.Stub
mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_PROVIDER, messenger));
}
+ @Override
+ public void offerNetwork(@NonNull final Messenger providerMessenger,
+ @NonNull final NetworkScore score, @NonNull final NetworkCapabilities caps,
+ @NonNull final INetworkOfferCallback callback) {
+ final NetworkOffer offer = new NetworkOffer(
+ FullScore.makeProspectiveScore(score, caps), caps, callback, providerMessenger);
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_OFFER, offer));
+ }
+
+ @Override
+ public void unofferNetwork(@NonNull final INetworkOfferCallback callback) {
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_OFFER, callback));
+ }
+
private void handleUnregisterNetworkProvider(Messenger messenger) {
NetworkProviderInfo npi = mNetworkProviderInfos.remove(messenger);
if (npi == null) {
loge("Failed to find Messenger in unregisterNetworkProvider");
return;
}
+ // Unregister all the offers from this provider
+ final ArrayList<NetworkOfferInfo> toRemove = new ArrayList<>();
+ for (final NetworkOfferInfo noi : mNetworkOffers) {
+ if (noi.offer.provider == messenger) {
+ // Can't call handleUnregisterNetworkOffer here because iteration is in progress
+ toRemove.add(noi);
+ }
+ }
+ for (NetworkOfferInfo noi : toRemove) {
+ handleUnregisterNetworkOffer(noi);
+ }
if (DBG) log("unregisterNetworkProvider for " + npi.name);
}
@@ -6258,6 +6305,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
// (on the handler thread).
private volatile List<UidRange> mVpnBlockedUidRanges = new ArrayList<>();
+ // Must only be accessed on the handler thread
+ @NonNull
+ private final ArrayList<NetworkOfferInfo> mNetworkOffers = new ArrayList<>();
+
@GuardedBy("mBlockedAppUids")
private final HashSet<Integer> mBlockedAppUids = new HashSet<>();
@@ -6433,8 +6484,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
// Request used to optionally keep vehicle internal network always active
private final NetworkRequest mDefaultVehicleRequest;
- // TODO replace with INetd.UNREACHABLE_NET_ID when available.
- private static final int NO_SERVICE_NET_ID = 52;
// Sentinel NAI used to direct apps with default networks that should have no connectivity to a
// network with no service. This NAI should never be matched against, nor should any public API
// ever return the associated network. For this reason, this NAI is not in the list of available
@@ -6582,6 +6631,65 @@ public class ConnectivityService extends IConnectivityManager.Stub
updateUids(nai, null, nai.networkCapabilities);
}
+ private class NetworkOfferInfo implements IBinder.DeathRecipient {
+ @NonNull public final NetworkOffer offer;
+
+ NetworkOfferInfo(@NonNull final NetworkOffer offer) {
+ this.offer = offer;
+ }
+
+ @Override
+ public void binderDied() {
+ mHandler.post(() -> handleUnregisterNetworkOffer(this));
+ }
+ }
+
+ /**
+ * Register or update a network offer.
+ * @param newOffer The new offer. If the callback member is the same as an existing
+ * offer, it is an update of that offer.
+ */
+ private void handleRegisterNetworkOffer(@NonNull final NetworkOffer newOffer) {
+ ensureRunningOnConnectivityServiceThread();
+ if (null == mNetworkProviderInfos.get(newOffer.provider)) {
+ // This may actually happen if a provider updates its score or registers and then
+ // immediately unregisters. The offer would still be in the handler queue, but the
+ // provider would have been removed.
+ if (DBG) log("Received offer from an unregistered provider");
+ return;
+ }
+
+ final NetworkOfferInfo existingOffer = findNetworkOfferInfoByCallback(newOffer.callback);
+ if (null != existingOffer) {
+ handleUnregisterNetworkOffer(existingOffer);
+ newOffer.migrateFrom(existingOffer.offer);
+ }
+ final NetworkOfferInfo noi = new NetworkOfferInfo(newOffer);
+ try {
+ noi.offer.provider.getBinder().linkToDeath(noi, 0 /* flags */);
+ } catch (RemoteException e) {
+ noi.binderDied();
+ return;
+ }
+ mNetworkOffers.add(noi);
+ // TODO : send requests to the provider.
+ }
+
+ private void handleUnregisterNetworkOffer(@NonNull final NetworkOfferInfo noi) {
+ ensureRunningOnConnectivityServiceThread();
+ mNetworkOffers.remove(noi);
+ noi.offer.provider.getBinder().unlinkToDeath(noi, 0 /* flags */);
+ }
+
+ @Nullable private NetworkOfferInfo findNetworkOfferInfoByCallback(
+ @NonNull final INetworkOfferCallback callback) {
+ ensureRunningOnConnectivityServiceThread();
+ for (final NetworkOfferInfo noi : mNetworkOffers) {
+ if (noi.offer.callback.equals(callback)) return noi;
+ }
+ return null;
+ }
+
/**
* Called when receiving LinkProperties directly from a NetworkAgent.
* Stores into |nai| any data coming from the agent that might also be written to the network's
@@ -8476,11 +8584,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
final UnderlyingNetworkInfo[] underlyingNetworkInfos = getAllVpnInfo();
try {
final ArrayList<NetworkStateSnapshot> snapshots = new ArrayList<>();
- // TODO: Directly use NetworkStateSnapshot when feasible.
- for (final NetworkState state : getAllNetworkState()) {
- final NetworkStateSnapshot snapshot = new NetworkStateSnapshot(state.network,
- state.networkCapabilities, state.linkProperties, state.subscriberId,
- state.legacyNetworkType);
+ for (final NetworkStateSnapshot snapshot : getAllNetworkStateSnapshots()) {
snapshots.add(snapshot);
}
mStatsManager.notifyNetworkStatus(getDefaultNetworks(),
@@ -9041,7 +9145,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
private NetworkCapabilities getNetworkCapabilitiesWithoutUids(@NonNull NetworkCapabilities nc) {
- final NetworkCapabilities sanitized = new NetworkCapabilities(nc);
+ final NetworkCapabilities sanitized = new NetworkCapabilities(nc,
+ NetworkCapabilities.REDACT_ALL);
sanitized.setUids(null);
sanitized.setAdministratorUids(new int[0]);
sanitized.setOwnerUid(Process.INVALID_UID);
diff --git a/services/core/java/com/android/server/ConnectivityServiceInitializer.java b/packages/Connectivity/service/src/com/android/server/ConnectivityServiceInitializer.java
index 2465479aadd8..2465479aadd8 100644
--- a/services/core/java/com/android/server/ConnectivityServiceInitializer.java
+++ b/packages/Connectivity/service/src/com/android/server/ConnectivityServiceInitializer.java
diff --git a/services/core/java/com/android/server/NetIdManager.java b/packages/Connectivity/service/src/com/android/server/NetIdManager.java
index 61925c80a22b..61925c80a22b 100644
--- a/services/core/java/com/android/server/NetIdManager.java
+++ b/packages/Connectivity/service/src/com/android/server/NetIdManager.java
diff --git a/services/core/java/com/android/server/TestNetworkService.java b/packages/Connectivity/service/src/com/android/server/TestNetworkService.java
index f5662772f59f..f5662772f59f 100644
--- a/services/core/java/com/android/server/TestNetworkService.java
+++ b/packages/Connectivity/service/src/com/android/server/TestNetworkService.java
diff --git a/services/core/java/com/android/server/connectivity/AutodestructReference.java b/packages/Connectivity/service/src/com/android/server/connectivity/AutodestructReference.java
index 009a43e58285..009a43e58285 100644
--- a/services/core/java/com/android/server/connectivity/AutodestructReference.java
+++ b/packages/Connectivity/service/src/com/android/server/connectivity/AutodestructReference.java
diff --git a/services/core/java/com/android/server/connectivity/ConnectivityConstants.java b/packages/Connectivity/service/src/com/android/server/connectivity/ConnectivityConstants.java
index 325a2cd7bd69..325a2cd7bd69 100644
--- a/services/core/java/com/android/server/connectivity/ConnectivityConstants.java
+++ b/packages/Connectivity/service/src/com/android/server/connectivity/ConnectivityConstants.java
diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/packages/Connectivity/service/src/com/android/server/connectivity/DnsManager.java
index 05b12bad5589..05b12bad5589 100644
--- a/services/core/java/com/android/server/connectivity/DnsManager.java
+++ b/packages/Connectivity/service/src/com/android/server/connectivity/DnsManager.java
diff --git a/services/core/java/com/android/server/connectivity/FullScore.java b/packages/Connectivity/service/src/com/android/server/connectivity/FullScore.java
index 028cfee36593..9326d692f6e4 100644
--- a/services/core/java/com/android/server/connectivity/FullScore.java
+++ b/packages/Connectivity/service/src/com/android/server/connectivity/FullScore.java
@@ -16,6 +16,7 @@
package com.android.server.connectivity;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
@@ -116,6 +117,33 @@ public class FullScore {
}
/**
+ * Given a score supplied by the NetworkAgent, produce a prospective score for an offer.
+ *
+ * NetworkOffers have score filters that are compared to the scores of actual networks
+ * to see if they could possibly beat the current satisfier. Some things the agent can't
+ * know in advance ; a good example is the validation bit – some networks will validate,
+ * others won't. For comparison purposes, assume the best, so all possibly beneficial
+ * networks will be brought up.
+ *
+ * @param score the score supplied by the agent for this offer
+ * @param caps the capabilities supplied by the agent for this offer
+ * @return a FullScore appropriate for comparing to actual network's scores.
+ */
+ public static FullScore makeProspectiveScore(@NonNull final NetworkScore score,
+ @NonNull final NetworkCapabilities caps) {
+ // If the network offers Internet access, it may validate.
+ final boolean mayValidate = caps.hasCapability(NET_CAPABILITY_INTERNET);
+ // VPN transports are known in advance.
+ final boolean vpn = caps.hasTransport(TRANSPORT_VPN);
+ // The network hasn't been chosen by the user (yet, at least).
+ final boolean everUserSelected = false;
+ // Don't assume the user will accept unvalidated connectivity.
+ final boolean acceptUnvalidated = false;
+ return withPolicies(score.getLegacyInt(), mayValidate, vpn, everUserSelected,
+ acceptUnvalidated);
+ }
+
+ /**
* Return a new score given updated caps and config.
*
* @param caps the NetworkCapabilities of the network
diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/packages/Connectivity/service/src/com/android/server/connectivity/KeepaliveTracker.java
index acf39f05a541..acf39f05a541 100644
--- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
+++ b/packages/Connectivity/service/src/com/android/server/connectivity/KeepaliveTracker.java
diff --git a/services/core/java/com/android/server/connectivity/LingerMonitor.java b/packages/Connectivity/service/src/com/android/server/connectivity/LingerMonitor.java
index 032612c6f093..032612c6f093 100644
--- a/services/core/java/com/android/server/connectivity/LingerMonitor.java
+++ b/packages/Connectivity/service/src/com/android/server/connectivity/LingerMonitor.java
diff --git a/services/core/java/com/android/server/connectivity/MockableSystemProperties.java b/packages/Connectivity/service/src/com/android/server/connectivity/MockableSystemProperties.java
index a25b89ac039a..a25b89ac039a 100644
--- a/services/core/java/com/android/server/connectivity/MockableSystemProperties.java
+++ b/packages/Connectivity/service/src/com/android/server/connectivity/MockableSystemProperties.java
diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/packages/Connectivity/service/src/com/android/server/connectivity/Nat464Xlat.java
index c66a280f2b02..c66a280f2b02 100644
--- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java
+++ b/packages/Connectivity/service/src/com/android/server/connectivity/Nat464Xlat.java
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/packages/Connectivity/service/src/com/android/server/connectivity/NetworkAgentInfo.java
index ee32fbf00dfe..ee32fbf00dfe 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/packages/Connectivity/service/src/com/android/server/connectivity/NetworkAgentInfo.java
diff --git a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java b/packages/Connectivity/service/src/com/android/server/connectivity/NetworkDiagnostics.java
index 2e51be39bfae..2e51be39bfae 100644
--- a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
+++ b/packages/Connectivity/service/src/com/android/server/connectivity/NetworkDiagnostics.java
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/packages/Connectivity/service/src/com/android/server/connectivity/NetworkNotificationManager.java
index 0c0d45995a2b..0c0d45995a2b 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/packages/Connectivity/service/src/com/android/server/connectivity/NetworkNotificationManager.java
diff --git a/packages/Connectivity/service/src/com/android/server/connectivity/NetworkOffer.java b/packages/Connectivity/service/src/com/android/server/connectivity/NetworkOffer.java
new file mode 100644
index 000000000000..fa2d465fff1d
--- /dev/null
+++ b/packages/Connectivity/service/src/com/android/server/connectivity/NetworkOffer.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.INetworkOfferCallback;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
+import android.os.Messenger;
+
+import java.util.Objects;
+
+
+/**
+ * Represents an offer made by a NetworkProvider to create a network if a need arises.
+ *
+ * This class contains the prospective score and capabilities of the network. The provider
+ * is not obligated to caps able to create a network satisfying this, nor to build a network
+ * with the exact score and/or capabilities passed ; after all, not all providers know in
+ * advance what a network will look like after it's connected. Instead, this is meant as a
+ * filter to limit requests sent to the provider by connectivity to those that this offer stands
+ * a chance to fulfill.
+ *
+ * @see NetworkProvider#offerNetwork.
+ *
+ * @hide
+ */
+public class NetworkOffer {
+ @NonNull public final FullScore score;
+ @NonNull public final NetworkCapabilities caps;
+ @NonNull public final INetworkOfferCallback callback;
+ @NonNull public final Messenger provider;
+
+ private static NetworkCapabilities emptyCaps() {
+ final NetworkCapabilities nc = new NetworkCapabilities();
+ return nc;
+ }
+
+ // Ideally the caps argument would be non-null, but null has historically meant no filter
+ // and telephony passes null. Keep backward compatibility.
+ public NetworkOffer(@NonNull final FullScore score,
+ @Nullable final NetworkCapabilities caps,
+ @NonNull final INetworkOfferCallback callback,
+ @NonNull final Messenger provider) {
+ this.score = Objects.requireNonNull(score);
+ this.caps = null != caps ? caps : emptyCaps();
+ this.callback = Objects.requireNonNull(callback);
+ this.provider = Objects.requireNonNull(provider);
+ }
+
+ /**
+ * Migrate from, and take over, a previous offer.
+ *
+ * When an updated offer is sent from a provider, call this method on the new offer, passing
+ * the old one, to take over the state.
+ *
+ * @param previousOffer
+ */
+ public void migrateFrom(@NonNull final NetworkOffer previousOffer) {
+ if (!callback.equals(previousOffer.callback)) {
+ throw new IllegalArgumentException("Can only migrate from a previous version of"
+ + " the same offer");
+ }
+ }
+
+ /**
+ * Returns whether an offer can satisfy a NetworkRequest, according to its capabilities.
+ * @param request The request to test against.
+ * @return Whether this offer can satisfy the request.
+ */
+ public final boolean canSatisfy(@NonNull final NetworkRequest request) {
+ return request.networkCapabilities.satisfiedByNetworkCapabilities(caps);
+ }
+
+ @Override
+ public String toString() {
+ return "NetworkOffer [ Score " + score + " ]";
+ }
+}
diff --git a/services/core/java/com/android/server/connectivity/NetworkRanker.java b/packages/Connectivity/service/src/com/android/server/connectivity/NetworkRanker.java
index d0aabf95d572..d0aabf95d572 100644
--- a/services/core/java/com/android/server/connectivity/NetworkRanker.java
+++ b/packages/Connectivity/service/src/com/android/server/connectivity/NetworkRanker.java
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/packages/Connectivity/service/src/com/android/server/connectivity/PermissionMonitor.java
index 506cadb2b1d2..673c80417b8d 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/packages/Connectivity/service/src/com/android/server/connectivity/PermissionMonitor.java
@@ -24,6 +24,7 @@ import static android.Manifest.permission.UPDATE_DEVICE_STATS;
import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
import static android.content.pm.PackageManager.GET_PERMISSIONS;
import static android.content.pm.PackageManager.MATCH_ANY_USER;
+import static android.net.ConnectivitySettingsManager.APPS_ALLOWED_ON_RESTRICTED_NETWORKS;
import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
import static android.os.Process.INVALID_UID;
import static android.os.Process.SYSTEM_UID;
@@ -39,6 +40,8 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.database.ContentObserver;
+import android.net.ConnectivitySettingsManager;
import android.net.INetd;
import android.net.UidRange;
import android.net.Uri;
@@ -48,7 +51,9 @@ import android.os.ServiceSpecificException;
import android.os.SystemConfigManager;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.Settings;
import android.system.OsConstants;
+import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseIntArray;
@@ -66,7 +71,6 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
-
/**
* A utility class to inform Netd of UID permisisons.
* Does a mass update at boot and then monitors for app install/remove.
@@ -105,6 +109,14 @@ public class PermissionMonitor {
@GuardedBy("this")
private final Set<Integer> mAllApps = new HashSet<>();
+ // A set of apps which are allowed to use restricted networks. These apps can't hold the
+ // CONNECTIVITY_USE_RESTRICTED_NETWORKS permission because they can't be signature|privileged
+ // apps. However, these apps should still be able to use restricted networks under certain
+ // conditions (e.g. government app using emergency services). So grant netd system permission
+ // to uids whose package name is listed in APPS_ALLOWED_ON_RESTRICTED_NETWORKS setting.
+ @GuardedBy("this")
+ private final Set<String> mAppsAllowedOnRestrictedNetworks = new ArraySet<>();
+
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -135,6 +147,22 @@ public class PermissionMonitor {
public int getDeviceFirstSdkInt() {
return Build.VERSION.FIRST_SDK_INT;
}
+
+ /**
+ * Get apps allowed to use restricted networks via ConnectivitySettingsManager.
+ */
+ public Set<String> getAppsAllowedOnRestrictedNetworks(@NonNull Context context) {
+ return ConnectivitySettingsManager.getAppsAllowedOnRestrictedNetworks(context);
+ }
+
+ /**
+ * Register ContentObserver for given Uri.
+ */
+ public void registerContentObserver(@NonNull Context context, @NonNull Uri uri,
+ boolean notifyForDescendants, @NonNull ContentObserver observer) {
+ context.getContentResolver().registerContentObserver(
+ uri, notifyForDescendants, observer);
+ }
}
public PermissionMonitor(@NonNull final Context context, @NonNull final INetd netd) {
@@ -157,14 +185,31 @@ public class PermissionMonitor {
public synchronized void startMonitoring() {
log("Monitoring");
+ final Context userAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */);
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
intentFilter.addDataScheme("package");
- mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */).registerReceiver(
+ userAllContext.registerReceiver(
mIntentReceiver, intentFilter, null /* broadcastPermission */,
null /* scheduler */);
+ // Register APPS_ALLOWED_ON_RESTRICTED_NETWORKS setting observer
+ mDeps.registerContentObserver(
+ userAllContext,
+ Settings.Secure.getUriFor(APPS_ALLOWED_ON_RESTRICTED_NETWORKS),
+ false /* notifyForDescendants */,
+ new ContentObserver(null) {
+ @Override
+ public void onChange(boolean selfChange) {
+ onSettingChanged();
+ }
+ });
+
+ // Read APPS_ALLOWED_ON_RESTRICTED_NETWORKS setting and update
+ // mAppsAllowedOnRestrictedNetworks.
+ updateAppsAllowedOnRestrictedNetworks(mDeps.getAppsAllowedOnRestrictedNetworks(mContext));
+
List<PackageInfo> apps = mPackageManager.getInstalledPackages(GET_PERMISSIONS
| MATCH_ANY_USER);
if (apps == null) {
@@ -220,11 +265,33 @@ public class PermissionMonitor {
}
@VisibleForTesting
+ void updateAppsAllowedOnRestrictedNetworks(final Set<String> apps) {
+ mAppsAllowedOnRestrictedNetworks.clear();
+ mAppsAllowedOnRestrictedNetworks.addAll(apps);
+ }
+
+ @VisibleForTesting
static boolean isVendorApp(@NonNull ApplicationInfo appInfo) {
return appInfo.isVendor() || appInfo.isOem() || appInfo.isProduct();
}
@VisibleForTesting
+ boolean isCarryoverPackage(final ApplicationInfo appInfo) {
+ if (appInfo == null) return false;
+ return (appInfo.targetSdkVersion < VERSION_Q && isVendorApp(appInfo))
+ // Backward compatibility for b/114245686, on devices that launched before Q daemons
+ // and apps running as the system UID are exempted from this check.
+ || (appInfo.uid == SYSTEM_UID && mDeps.getDeviceFirstSdkInt() < VERSION_Q);
+ }
+
+ @VisibleForTesting
+ boolean isAppAllowedOnRestrictedNetworks(@NonNull final PackageInfo app) {
+ // Check whether package name is in allowed on restricted networks app list. If so, this app
+ // can have netd system permission.
+ return mAppsAllowedOnRestrictedNetworks.contains(app.packageName);
+ }
+
+ @VisibleForTesting
boolean hasPermission(@NonNull final PackageInfo app, @NonNull final String permission) {
if (app.requestedPermissions == null || app.requestedPermissionsFlags == null) {
return false;
@@ -241,22 +308,10 @@ public class PermissionMonitor {
@VisibleForTesting
boolean hasRestrictedNetworkPermission(@NonNull final PackageInfo app) {
- // TODO : remove this check in the future(b/31479477). All apps should just
- // request the appropriate permission for their use case since android Q.
- if (app.applicationInfo != null) {
- // Backward compatibility for b/114245686, on devices that launched before Q daemons
- // and apps running as the system UID are exempted from this check.
- if (app.applicationInfo.uid == SYSTEM_UID && mDeps.getDeviceFirstSdkInt() < VERSION_Q) {
- return true;
- }
-
- if (app.applicationInfo.targetSdkVersion < VERSION_Q
- && isVendorApp(app.applicationInfo)) {
- return true;
- }
- }
-
- return hasPermission(app, PERMISSION_MAINLINE_NETWORK_STACK)
+ // TODO : remove carryover package check in the future(b/31479477). All apps should just
+ // request the appropriate permission for their use case since android Q.
+ return isCarryoverPackage(app.applicationInfo) || isAppAllowedOnRestrictedNetworks(app)
+ || hasPermission(app, PERMISSION_MAINLINE_NETWORK_STACK)
|| hasPermission(app, NETWORK_STACK)
|| hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS);
}
@@ -410,6 +465,20 @@ public class PermissionMonitor {
mAllApps.add(UserHandle.getAppId(uid));
}
+ private Boolean highestUidNetworkPermission(int uid) {
+ Boolean permission = null;
+ final String[] packages = mPackageManager.getPackagesForUid(uid);
+ if (!CollectionUtils.isEmpty(packages)) {
+ for (String name : packages) {
+ permission = highestPermissionForUid(permission, name);
+ if (permission == SYSTEM) {
+ break;
+ }
+ }
+ }
+ return permission;
+ }
+
/**
* Called when a package is removed.
*
@@ -440,19 +509,14 @@ public class PermissionMonitor {
}
Map<Integer, Boolean> apps = new HashMap<>();
- Boolean permission = null;
- String[] packages = mPackageManager.getPackagesForUid(uid);
- if (packages != null && packages.length > 0) {
- for (String name : packages) {
- permission = highestPermissionForUid(permission, name);
- if (permission == SYSTEM) {
- // An app with this UID still has the SYSTEM permission.
- // Therefore, this UID must already have the SYSTEM permission.
- // Nothing to do.
- return;
- }
- }
+ final Boolean permission = highestUidNetworkPermission(uid);
+ if (permission == SYSTEM) {
+ // An app with this UID still has the SYSTEM permission.
+ // Therefore, this UID must already have the SYSTEM permission.
+ // Nothing to do.
+ return;
}
+
if (permission == mApps.get(uid)) {
// The permissions of this UID have not changed. Nothing to do.
return;
@@ -705,6 +769,38 @@ public class PermissionMonitor {
return mVpnUidRanges.get(iface);
}
+ private synchronized void onSettingChanged() {
+ // Step1. Update apps allowed to use restricted networks and compute the set of packages to
+ // update.
+ final Set<String> packagesToUpdate = new ArraySet<>(mAppsAllowedOnRestrictedNetworks);
+ updateAppsAllowedOnRestrictedNetworks(mDeps.getAppsAllowedOnRestrictedNetworks(mContext));
+ packagesToUpdate.addAll(mAppsAllowedOnRestrictedNetworks);
+
+ final Map<Integer, Boolean> updatedApps = new HashMap<>();
+ final Map<Integer, Boolean> removedApps = new HashMap<>();
+
+ // Step2. For each package to update, find out its new permission.
+ for (String app : packagesToUpdate) {
+ final PackageInfo info = getPackageInfo(app);
+ if (info == null || info.applicationInfo == null) continue;
+
+ final int uid = info.applicationInfo.uid;
+ final Boolean permission = highestUidNetworkPermission(uid);
+
+ if (null == permission) {
+ removedApps.put(uid, NETWORK); // Doesn't matter which permission is set here.
+ mApps.remove(uid);
+ } else {
+ updatedApps.put(uid, permission);
+ mApps.put(uid, permission);
+ }
+ }
+
+ // Step3. Update or revoke permission for uids with netd.
+ update(mUsers, updatedApps, true /* add */);
+ update(mUsers, removedApps, false /* add */);
+ }
+
/** Dump info to dumpsys */
public void dump(IndentingPrintWriter pw) {
pw.println("Interface filtering rules:");
diff --git a/services/core/java/com/android/server/connectivity/ProfileNetworkPreferences.java b/packages/Connectivity/service/src/com/android/server/connectivity/ProfileNetworkPreferences.java
index dd2815d9e2e3..dd2815d9e2e3 100644
--- a/services/core/java/com/android/server/connectivity/ProfileNetworkPreferences.java
+++ b/packages/Connectivity/service/src/com/android/server/connectivity/ProfileNetworkPreferences.java
diff --git a/services/core/java/com/android/server/connectivity/ProxyTracker.java b/packages/Connectivity/service/src/com/android/server/connectivity/ProxyTracker.java
index f572b46a9b58..f572b46a9b58 100644
--- a/services/core/java/com/android/server/connectivity/ProxyTracker.java
+++ b/packages/Connectivity/service/src/com/android/server/connectivity/ProxyTracker.java
diff --git a/services/core/java/com/android/server/connectivity/QosCallbackAgentConnection.java b/packages/Connectivity/service/src/com/android/server/connectivity/QosCallbackAgentConnection.java
index 534dbe7699a7..534dbe7699a7 100644
--- a/services/core/java/com/android/server/connectivity/QosCallbackAgentConnection.java
+++ b/packages/Connectivity/service/src/com/android/server/connectivity/QosCallbackAgentConnection.java
diff --git a/services/core/java/com/android/server/connectivity/QosCallbackTracker.java b/packages/Connectivity/service/src/com/android/server/connectivity/QosCallbackTracker.java
index b6ab47b276e3..b6ab47b276e3 100644
--- a/services/core/java/com/android/server/connectivity/QosCallbackTracker.java
+++ b/packages/Connectivity/service/src/com/android/server/connectivity/QosCallbackTracker.java
diff --git a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java b/packages/Connectivity/service/src/com/android/server/connectivity/TcpKeepaliveController.java
index c480594b8c60..c480594b8c60 100644
--- a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
+++ b/packages/Connectivity/service/src/com/android/server/connectivity/TcpKeepaliveController.java
diff --git a/packages/Connectivity/tests/common/java/android/net/NetworkCapabilitiesTest.java b/packages/Connectivity/tests/common/java/android/net/NetworkCapabilitiesTest.java
index b178bad7123d..d74b802c8729 100644
--- a/packages/Connectivity/tests/common/java/android/net/NetworkCapabilitiesTest.java
+++ b/packages/Connectivity/tests/common/java/android/net/NetworkCapabilitiesTest.java
@@ -340,7 +340,7 @@ public class NetworkCapabilitiesTest {
private void testParcelSane(NetworkCapabilities cap) {
if (isAtLeastS()) {
- assertParcelSane(cap, 17);
+ assertParcelSane(cap, 16);
} else if (isAtLeastR()) {
assertParcelSane(cap, 15);
} else {
diff --git a/packages/Connectivity/tests/common/java/android/net/UnderlyingNetworkInfoTest.kt b/packages/Connectivity/tests/common/java/android/net/UnderlyingNetworkInfoTest.kt
index 87cfb345e5e0..f23ba26d0039 100644
--- a/packages/Connectivity/tests/common/java/android/net/UnderlyingNetworkInfoTest.kt
+++ b/packages/Connectivity/tests/common/java/android/net/UnderlyingNetworkInfoTest.kt
@@ -36,15 +36,15 @@ class UnderlyingNetworkInfoTest {
@Test
fun testParcelUnparcel() {
val testInfo = UnderlyingNetworkInfo(TEST_OWNER_UID, TEST_IFACE, TEST_IFACE_LIST)
- assertEquals(TEST_OWNER_UID, testInfo.ownerUid)
- assertEquals(TEST_IFACE, testInfo.iface)
- assertEquals(TEST_IFACE_LIST, testInfo.underlyingIfaces)
+ assertEquals(TEST_OWNER_UID, testInfo.getOwnerUid())
+ assertEquals(TEST_IFACE, testInfo.getInterface())
+ assertEquals(TEST_IFACE_LIST, testInfo.getUnderlyingInterfaces())
assertParcelSane(testInfo, 3)
val emptyInfo = UnderlyingNetworkInfo(0, String(), listOf())
- assertEquals(0, emptyInfo.ownerUid)
- assertEquals(String(), emptyInfo.iface)
- assertEquals(listOf(), emptyInfo.underlyingIfaces)
+ assertEquals(0, emptyInfo.getOwnerUid())
+ assertEquals(String(), emptyInfo.getInterface())
+ assertEquals(listOf(), emptyInfo.getUnderlyingInterfaces())
assertParcelSane(emptyInfo, 3)
}
} \ No newline at end of file
diff --git a/packages/Connectivity/tests/unit/java/android/net/NetworkTemplateTest.kt b/packages/Connectivity/tests/unit/java/android/net/NetworkTemplateTest.kt
index ab6b2f409867..cb39a0c819f2 100644
--- a/packages/Connectivity/tests/unit/java/android/net/NetworkTemplateTest.kt
+++ b/packages/Connectivity/tests/unit/java/android/net/NetworkTemplateTest.kt
@@ -40,7 +40,7 @@ import android.net.NetworkTemplate.OEM_MANAGED_YES
import android.net.NetworkTemplate.SUBSCRIBER_ID_MATCH_RULE_EXACT
import android.net.NetworkTemplate.buildTemplateWifi
import android.net.NetworkTemplate.buildTemplateWifiWildcard
-import android.net.NetworkTemplate.buildTemplateCarrier
+import android.net.NetworkTemplate.buildTemplateCarrierMetered
import android.net.NetworkTemplate.buildTemplateMobileWithRatType
import android.telephony.TelephonyManager
import com.android.testutils.assertParcelSane
@@ -73,11 +73,12 @@ class NetworkTemplateTest {
type: Int,
subscriberId: String? = null,
ssid: String? = null,
- oemManaged: Int = OEM_NONE
+ oemManaged: Int = OEM_NONE,
+ metered: Boolean = true
): NetworkStateSnapshot {
val lp = LinkProperties()
val caps = NetworkCapabilities().apply {
- setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, false)
+ setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, !metered)
setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true)
setSSID(ssid)
setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID,
@@ -167,25 +168,38 @@ class NetworkTemplateTest {
}
@Test
- fun testCarrierMatches() {
- val templateCarrierImsi1 = buildTemplateCarrier(TEST_IMSI1)
-
- val identMobile1 = buildNetworkIdentity(mockContext, buildMobileNetworkState(TEST_IMSI1),
- false, TelephonyManager.NETWORK_TYPE_UMTS)
- val identMobile2 = buildNetworkIdentity(mockContext, buildMobileNetworkState(TEST_IMSI2),
- false, TelephonyManager.NETWORK_TYPE_UMTS)
- val identWifiSsid1 = buildNetworkIdentity(
- mockContext, buildWifiNetworkState(null, TEST_SSID1), true, 0)
- val identCarrierWifiImsi1 = buildNetworkIdentity(
- mockContext, buildWifiNetworkState(TEST_IMSI1, TEST_SSID1), true, 0)
- val identCarrierWifiImsi2 = buildNetworkIdentity(
- mockContext, buildWifiNetworkState(TEST_IMSI2, TEST_SSID1), true, 0)
-
- templateCarrierImsi1.assertMatches(identCarrierWifiImsi1)
- templateCarrierImsi1.assertDoesNotMatch(identCarrierWifiImsi2)
- templateCarrierImsi1.assertDoesNotMatch(identWifiSsid1)
- templateCarrierImsi1.assertMatches(identMobile1)
- templateCarrierImsi1.assertDoesNotMatch(identMobile2)
+ fun testCarrierMeteredMatches() {
+ val templateCarrierImsi1Metered = buildTemplateCarrierMetered(TEST_IMSI1)
+
+ val mobileImsi1 = buildMobileNetworkState(TEST_IMSI1)
+ val mobileImsi1Unmetered = buildNetworkState(TYPE_MOBILE, TEST_IMSI1, null /* ssid */,
+ OEM_NONE, false /* metered */)
+ val mobileImsi2 = buildMobileNetworkState(TEST_IMSI2)
+ val wifiSsid1 = buildWifiNetworkState(null /* subscriberId */, TEST_SSID1)
+ val wifiImsi1Ssid1 = buildWifiNetworkState(TEST_IMSI1, TEST_SSID1)
+ val wifiImsi1Ssid1Unmetered = buildNetworkState(TYPE_WIFI, TEST_IMSI1, TEST_SSID1,
+ OEM_NONE, false /* metered */)
+
+ val identMobileImsi1Metered = buildNetworkIdentity(mockContext,
+ mobileImsi1, false /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS)
+ val identMobileImsi1Unmetered = buildNetworkIdentity(mockContext,
+ mobileImsi1Unmetered, false /* defaultNetwork */,
+ TelephonyManager.NETWORK_TYPE_UMTS)
+ val identMobileImsi2Metered = buildNetworkIdentity(mockContext,
+ mobileImsi2, false /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS)
+ val identWifiSsid1Metered = buildNetworkIdentity(
+ mockContext, wifiSsid1, true /* defaultNetwork */, 0 /* subType */)
+ val identCarrierWifiImsi1Metered = buildNetworkIdentity(
+ mockContext, wifiImsi1Ssid1, true /* defaultNetwork */, 0 /* subType */)
+ val identCarrierWifiImsi1NonMetered = buildNetworkIdentity(mockContext,
+ wifiImsi1Ssid1Unmetered, true /* defaultNetwork */, 0 /* subType */)
+
+ templateCarrierImsi1Metered.assertMatches(identMobileImsi1Metered)
+ templateCarrierImsi1Metered.assertDoesNotMatch(identMobileImsi1Unmetered)
+ templateCarrierImsi1Metered.assertDoesNotMatch(identMobileImsi2Metered)
+ templateCarrierImsi1Metered.assertDoesNotMatch(identWifiSsid1Metered)
+ templateCarrierImsi1Metered.assertMatches(identCarrierWifiImsi1Metered)
+ templateCarrierImsi1Metered.assertDoesNotMatch(identCarrierWifiImsi1NonMetered)
}
@Test
diff --git a/packages/Connectivity/tests/unit/java/android/net/QosSocketFilterTest.java b/packages/Connectivity/tests/unit/java/android/net/QosSocketFilterTest.java
index ad58960eaadd..40f8f1b8d09a 100644
--- a/packages/Connectivity/tests/unit/java/android/net/QosSocketFilterTest.java
+++ b/packages/Connectivity/tests/unit/java/android/net/QosSocketFilterTest.java
@@ -35,7 +35,7 @@ public class QosSocketFilterTest {
public void testPortExactMatch() {
final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4");
final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.4");
- assertTrue(QosSocketFilter.matchesLocalAddress(
+ assertTrue(QosSocketFilter.matchesAddress(
new InetSocketAddress(addressA, 10), addressB, 10, 10));
}
@@ -44,7 +44,7 @@ public class QosSocketFilterTest {
public void testPortLessThanStart() {
final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4");
final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.4");
- assertFalse(QosSocketFilter.matchesLocalAddress(
+ assertFalse(QosSocketFilter.matchesAddress(
new InetSocketAddress(addressA, 8), addressB, 10, 10));
}
@@ -52,7 +52,7 @@ public class QosSocketFilterTest {
public void testPortGreaterThanEnd() {
final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4");
final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.4");
- assertFalse(QosSocketFilter.matchesLocalAddress(
+ assertFalse(QosSocketFilter.matchesAddress(
new InetSocketAddress(addressA, 18), addressB, 10, 10));
}
@@ -60,7 +60,7 @@ public class QosSocketFilterTest {
public void testPortBetweenStartAndEnd() {
final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4");
final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.4");
- assertTrue(QosSocketFilter.matchesLocalAddress(
+ assertTrue(QosSocketFilter.matchesAddress(
new InetSocketAddress(addressA, 10), addressB, 8, 18));
}
@@ -68,7 +68,7 @@ public class QosSocketFilterTest {
public void testAddressesDontMatch() {
final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4");
final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.5");
- assertFalse(QosSocketFilter.matchesLocalAddress(
+ assertFalse(QosSocketFilter.matchesAddress(
new InetSocketAddress(addressA, 10), addressB, 10, 10));
}
}
diff --git a/packages/Connectivity/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/packages/Connectivity/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index ab5079820611..41458f16baa4 100644
--- a/packages/Connectivity/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/packages/Connectivity/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -19,6 +19,7 @@ package com.android.server;
import static android.Manifest.permission.CHANGE_NETWORK_STATE;
import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
import static android.Manifest.permission.DUMP;
+import static android.Manifest.permission.LOCAL_MAC_ADDRESS;
import static android.Manifest.permission.NETWORK_FACTORY;
import static android.Manifest.permission.NETWORK_SETTINGS;
import static android.app.PendingIntent.FLAG_IMMUTABLE;
@@ -126,6 +127,7 @@ import static com.android.testutils.MiscAsserts.assertContainsExactly;
import static com.android.testutils.MiscAsserts.assertEmpty;
import static com.android.testutils.MiscAsserts.assertLength;
import static com.android.testutils.MiscAsserts.assertRunsInAtMost;
+import static com.android.testutils.MiscAsserts.assertSameElements;
import static com.android.testutils.MiscAsserts.assertThrows;
import static org.junit.Assert.assertEquals;
@@ -5805,20 +5807,8 @@ public class ConnectivityServiceTest {
mCm.unregisterNetworkCallback(networkCallback);
}
- private <T> void assertSameElementsNoDuplicates(T[] expected, T[] actual) {
- // Easier to implement than a proper "assertSameElements" method that also correctly deals
- // with duplicates.
- final String msg = Arrays.toString(expected) + " != " + Arrays.toString(actual);
- assertEquals(msg, expected.length, actual.length);
- Set expectedSet = new ArraySet<>(Arrays.asList(expected));
- assertEquals("expected contains duplicates", expectedSet.size(), expected.length);
- // actual cannot have duplicates because it's the same length and has the same elements.
- Set actualSet = new ArraySet<>(Arrays.asList(actual));
- assertEquals(expectedSet, actualSet);
- }
-
- private void expectNetworkStatus(Network[] networks, String defaultIface,
- Integer vpnUid, String vpnIfname, String[] underlyingIfaces) throws Exception {
+ private void expectNotifyNetworkStatus(List<Network> networks, String defaultIface,
+ Integer vpnUid, String vpnIfname, List<String> underlyingIfaces) throws Exception {
ArgumentCaptor<List<Network>> networksCaptor = ArgumentCaptor.forClass(List.class);
ArgumentCaptor<List<UnderlyingNetworkInfo>> vpnInfosCaptor =
ArgumentCaptor.forClass(List.class);
@@ -5826,26 +5816,24 @@ public class ConnectivityServiceTest {
verify(mStatsManager, atLeastOnce()).notifyNetworkStatus(networksCaptor.capture(),
any(List.class), eq(defaultIface), vpnInfosCaptor.capture());
- assertSameElementsNoDuplicates(networksCaptor.getValue().toArray(), networks);
+ assertSameElements(networksCaptor.getValue(), networks);
- UnderlyingNetworkInfo[] infos =
- vpnInfosCaptor.getValue().toArray(new UnderlyingNetworkInfo[0]);
+ List<UnderlyingNetworkInfo> infos = vpnInfosCaptor.getValue();
if (vpnUid != null) {
- assertEquals("Should have exactly one VPN:", 1, infos.length);
- UnderlyingNetworkInfo info = infos[0];
+ assertEquals("Should have exactly one VPN:", 1, infos.size());
+ UnderlyingNetworkInfo info = infos.get(0);
assertEquals("Unexpected VPN owner:", (int) vpnUid, info.getOwnerUid());
- assertEquals("Unexpected VPN interface:", vpnIfname, info.getIface());
- assertSameElementsNoDuplicates(underlyingIfaces,
- info.getUnderlyingIfaces().toArray(new String[0]));
+ assertEquals("Unexpected VPN interface:", vpnIfname, info.getInterface());
+ assertSameElements(underlyingIfaces, info.getUnderlyingInterfaces());
} else {
- assertEquals(0, infos.length);
+ assertEquals(0, infos.size());
return;
}
}
- private void expectNetworkStatus(
- Network[] networks, String defaultIface) throws Exception {
- expectNetworkStatus(networks, defaultIface, null, null, new String[0]);
+ private void expectNotifyNetworkStatus(
+ List<Network> networks, String defaultIface) throws Exception {
+ expectNotifyNetworkStatus(networks, defaultIface, null, null, List.of());
}
@Test
@@ -5853,8 +5841,8 @@ public class ConnectivityServiceTest {
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
- final Network[] onlyCell = new Network[] {mCellNetworkAgent.getNetwork()};
- final Network[] onlyWifi = new Network[] {mWiFiNetworkAgent.getNetwork()};
+ final List<Network> onlyCell = List.of(mCellNetworkAgent.getNetwork());
+ final List<Network> onlyWifi = List.of(mWiFiNetworkAgent.getNetwork());
LinkProperties cellLp = new LinkProperties();
cellLp.setInterfaceName(MOBILE_IFNAME);
@@ -5865,7 +5853,7 @@ public class ConnectivityServiceTest {
mCellNetworkAgent.connect(false);
mCellNetworkAgent.sendLinkProperties(cellLp);
waitForIdle();
- expectNetworkStatus(onlyCell, MOBILE_IFNAME);
+ expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME);
reset(mStatsManager);
// Default network switch should update ifaces.
@@ -5873,37 +5861,37 @@ public class ConnectivityServiceTest {
mWiFiNetworkAgent.sendLinkProperties(wifiLp);
waitForIdle();
assertEquals(wifiLp, mService.getActiveLinkProperties());
- expectNetworkStatus(onlyWifi, WIFI_IFNAME);
+ expectNotifyNetworkStatus(onlyWifi, WIFI_IFNAME);
reset(mStatsManager);
// Disconnect should update ifaces.
mWiFiNetworkAgent.disconnect();
waitForIdle();
- expectNetworkStatus(onlyCell, MOBILE_IFNAME);
+ expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME);
reset(mStatsManager);
// Metered change should update ifaces
mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
waitForIdle();
- expectNetworkStatus(onlyCell, MOBILE_IFNAME);
+ expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME);
reset(mStatsManager);
mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
waitForIdle();
- expectNetworkStatus(onlyCell, MOBILE_IFNAME);
+ expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME);
reset(mStatsManager);
// Temp metered change shouldn't update ifaces
mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
waitForIdle();
- verify(mStatsManager, never()).notifyNetworkStatus(eq(Arrays.asList(onlyCell)),
+ verify(mStatsManager, never()).notifyNetworkStatus(eq(onlyCell),
any(List.class), eq(MOBILE_IFNAME), any(List.class));
reset(mStatsManager);
// Roaming change should update ifaces
mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
waitForIdle();
- expectNetworkStatus(onlyCell, MOBILE_IFNAME);
+ expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME);
reset(mStatsManager);
// Test VPNs.
@@ -5913,29 +5901,29 @@ public class ConnectivityServiceTest {
mMockVpn.establishForMyUid(lp);
assertUidRangesUpdatedForMyUid(true);
- final Network[] cellAndVpn = new Network[] {
- mCellNetworkAgent.getNetwork(), mMockVpn.getNetwork()};
+ final List<Network> cellAndVpn =
+ List.of(mCellNetworkAgent.getNetwork(), mMockVpn.getNetwork());
// A VPN with default (null) underlying networks sets the underlying network's interfaces...
- expectNetworkStatus(cellAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
- new String[]{MOBILE_IFNAME});
+ expectNotifyNetworkStatus(cellAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
+ List.of(MOBILE_IFNAME));
// ...and updates them as the default network switches.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
mWiFiNetworkAgent.sendLinkProperties(wifiLp);
final Network[] onlyNull = new Network[]{null};
- final Network[] wifiAndVpn = new Network[] {
- mWiFiNetworkAgent.getNetwork(), mMockVpn.getNetwork()};
- final Network[] cellAndWifi = new Network[] {
- mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork()};
- final Network[] cellNullAndWifi = new Network[] {
- mCellNetworkAgent.getNetwork(), null, mWiFiNetworkAgent.getNetwork()};
+ final List<Network> wifiAndVpn =
+ List.of(mWiFiNetworkAgent.getNetwork(), mMockVpn.getNetwork());
+ final List<Network> cellAndWifi =
+ List.of(mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork());
+ final Network[] cellNullAndWifi =
+ new Network[]{mCellNetworkAgent.getNetwork(), null, mWiFiNetworkAgent.getNetwork()};
waitForIdle();
assertEquals(wifiLp, mService.getActiveLinkProperties());
- expectNetworkStatus(wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME,
- new String[]{WIFI_IFNAME});
+ expectNotifyNetworkStatus(wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME,
+ List.of(WIFI_IFNAME));
reset(mStatsManager);
// A VPN that sets its underlying networks passes the underlying interfaces, and influences
@@ -5944,23 +5932,23 @@ public class ConnectivityServiceTest {
// MOBILE_IFNAME even though the default network is wifi.
// TODO: fix this to pass in the actual default network interface. Whether or not the VPN
// applies to the system server UID should not have any bearing on network stats.
- mMockVpn.setUnderlyingNetworks(onlyCell);
+ mMockVpn.setUnderlyingNetworks(onlyCell.toArray(new Network[0]));
waitForIdle();
- expectNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
- new String[]{MOBILE_IFNAME});
+ expectNotifyNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
+ List.of(MOBILE_IFNAME));
reset(mStatsManager);
- mMockVpn.setUnderlyingNetworks(cellAndWifi);
+ mMockVpn.setUnderlyingNetworks(cellAndWifi.toArray(new Network[0]));
waitForIdle();
- expectNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
- new String[]{MOBILE_IFNAME, WIFI_IFNAME});
+ expectNotifyNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
+ List.of(MOBILE_IFNAME, WIFI_IFNAME));
reset(mStatsManager);
// Null underlying networks are ignored.
mMockVpn.setUnderlyingNetworks(cellNullAndWifi);
waitForIdle();
- expectNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
- new String[]{MOBILE_IFNAME, WIFI_IFNAME});
+ expectNotifyNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
+ List.of(MOBILE_IFNAME, WIFI_IFNAME));
reset(mStatsManager);
// If an underlying network disconnects, that interface should no longer be underlying.
@@ -5973,15 +5961,15 @@ public class ConnectivityServiceTest {
mCellNetworkAgent.disconnect();
waitForIdle();
assertNull(mService.getLinkProperties(mCellNetworkAgent.getNetwork()));
- expectNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
- new String[]{MOBILE_IFNAME, WIFI_IFNAME});
+ expectNotifyNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
+ List.of(MOBILE_IFNAME, WIFI_IFNAME));
// Confirm that we never tell NetworkStatsService that cell is no longer the underlying
// network for the VPN...
verify(mStatsManager, never()).notifyNetworkStatus(any(List.class),
any(List.class), any() /* anyString() doesn't match null */,
- argThat(infos -> infos.get(0).getUnderlyingIfaces().size() == 1
- && WIFI_IFNAME.equals(infos.get(0).getUnderlyingIfaces().get(0))));
+ argThat(infos -> infos.get(0).getUnderlyingInterfaces().size() == 1
+ && WIFI_IFNAME.equals(infos.get(0).getUnderlyingInterfaces().get(0))));
verifyNoMoreInteractions(mStatsManager);
reset(mStatsManager);
@@ -5994,8 +5982,8 @@ public class ConnectivityServiceTest {
waitForIdle();
verify(mStatsManager).notifyNetworkStatus(any(List.class),
any(List.class), any() /* anyString() doesn't match null */,
- argThat(vpnInfos -> vpnInfos.get(0).getUnderlyingIfaces().size() == 1
- && WIFI_IFNAME.equals(vpnInfos.get(0).getUnderlyingIfaces().get(0))));
+ argThat(vpnInfos -> vpnInfos.get(0).getUnderlyingInterfaces().size() == 1
+ && WIFI_IFNAME.equals(vpnInfos.get(0).getUnderlyingInterfaces().get(0))));
mEthernetNetworkAgent.disconnect();
waitForIdle();
reset(mStatsManager);
@@ -6008,26 +5996,26 @@ public class ConnectivityServiceTest {
// Also, for the same reason as above, the active interface passed in is null.
mMockVpn.setUnderlyingNetworks(new Network[0]);
waitForIdle();
- expectNetworkStatus(wifiAndVpn, null);
+ expectNotifyNetworkStatus(wifiAndVpn, null);
reset(mStatsManager);
// Specifying only a null underlying network is the same as no networks.
mMockVpn.setUnderlyingNetworks(onlyNull);
waitForIdle();
- expectNetworkStatus(wifiAndVpn, null);
+ expectNotifyNetworkStatus(wifiAndVpn, null);
reset(mStatsManager);
// Specifying networks that are all disconnected is the same as specifying no networks.
- mMockVpn.setUnderlyingNetworks(onlyCell);
+ mMockVpn.setUnderlyingNetworks(onlyCell.toArray(new Network[0]));
waitForIdle();
- expectNetworkStatus(wifiAndVpn, null);
+ expectNotifyNetworkStatus(wifiAndVpn, null);
reset(mStatsManager);
// Passing in null again means follow the default network again.
mMockVpn.setUnderlyingNetworks(null);
waitForIdle();
- expectNetworkStatus(wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME,
- new String[]{WIFI_IFNAME});
+ expectNotifyNetworkStatus(wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME,
+ List.of(WIFI_IFNAME));
reset(mStatsManager);
}
@@ -9407,9 +9395,9 @@ public class ConnectivityServiceTest {
@Override
public TransportInfo makeCopy(@NetworkCapabilities.RedactionType long redactions) {
return new TestTransportInfo(
- (redactions & REDACT_FOR_ACCESS_FINE_LOCATION) != 0,
- (redactions & REDACT_FOR_LOCAL_MAC_ADDRESS) != 0,
- (redactions & REDACT_FOR_NETWORK_SETTINGS) != 0
+ locationRedacted | (redactions & REDACT_FOR_ACCESS_FINE_LOCATION) != 0,
+ localMacAddressRedacted | (redactions & REDACT_FOR_LOCAL_MAC_ADDRESS) != 0,
+ settingsRedacted | (redactions & REDACT_FOR_NETWORK_SETTINGS) != 0
);
}
@@ -9432,8 +9420,26 @@ public class ConnectivityServiceTest {
public int hashCode() {
return Objects.hash(locationRedacted, localMacAddressRedacted, settingsRedacted);
}
+
+ @Override
+ public String toString() {
+ return String.format(
+ "TestTransportInfo{locationRedacted=%s macRedacted=%s settingsRedacted=%s}",
+ locationRedacted, localMacAddressRedacted, settingsRedacted);
+ }
+ }
+
+ private TestTransportInfo getTestTransportInfo(NetworkCapabilities nc) {
+ return (TestTransportInfo) nc.getTransportInfo();
+ }
+
+ private TestTransportInfo getTestTransportInfo(TestNetworkAgentWrapper n) {
+ final NetworkCapabilities nc = mCm.getNetworkCapabilities(n.getNetwork());
+ assertNotNull(nc);
+ return getTestTransportInfo(nc);
}
+
private void verifyNetworkCallbackLocationDataInclusionUsingTransportInfoAndOwnerUidInNetCaps(
@NonNull TestNetworkCallback wifiNetworkCallback, int actualOwnerUid,
@NonNull TransportInfo actualTransportInfo, int expectedOwnerUid,
@@ -9462,7 +9468,6 @@ public class ConnectivityServiceTest {
wifiNetworkCallback.expectCapabilitiesThat(mWiFiNetworkAgent,
nc -> Objects.equals(expectedOwnerUid, nc.getOwnerUid())
&& Objects.equals(expectedTransportInfo, nc.getTransportInfo()));
-
}
@Test
@@ -9483,6 +9488,40 @@ public class ConnectivityServiceTest {
wifiNetworkCallack, ownerUid, transportInfo, INVALID_UID, sanitizedTransportInfo);
}
+ @Test
+ public void testTransportInfoRedactionInSynchronousCalls() throws Exception {
+ final NetworkCapabilities ncTemplate = new NetworkCapabilities()
+ .addTransportType(TRANSPORT_WIFI)
+ .setTransportInfo(new TestTransportInfo());
+
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(),
+ ncTemplate);
+ mWiFiNetworkAgent.connect(true /* validated; waits for callback */);
+
+ // NETWORK_SETTINGS redaction is controlled by the NETWORK_SETTINGS permission
+ assertTrue(getTestTransportInfo(mWiFiNetworkAgent).settingsRedacted);
+ withPermission(NETWORK_SETTINGS, () -> {
+ assertFalse(getTestTransportInfo(mWiFiNetworkAgent).settingsRedacted);
+ });
+ assertTrue(getTestTransportInfo(mWiFiNetworkAgent).settingsRedacted);
+
+ // LOCAL_MAC_ADDRESS redaction is controlled by the LOCAL_MAC_ADDRESS permission
+ assertTrue(getTestTransportInfo(mWiFiNetworkAgent).localMacAddressRedacted);
+ withPermission(LOCAL_MAC_ADDRESS, () -> {
+ assertFalse(getTestTransportInfo(mWiFiNetworkAgent).localMacAddressRedacted);
+ });
+ assertTrue(getTestTransportInfo(mWiFiNetworkAgent).localMacAddressRedacted);
+
+ // Synchronous getNetworkCapabilities calls never return unredacted location-sensitive
+ // information.
+ assertTrue(getTestTransportInfo(mWiFiNetworkAgent).locationRedacted);
+ setupLocationPermissions(Build.VERSION_CODES.S, true, AppOpsManager.OPSTR_FINE_LOCATION,
+ Manifest.permission.ACCESS_FINE_LOCATION);
+ assertTrue(getTestTransportInfo(mWiFiNetworkAgent).locationRedacted);
+ denyAllLocationPrivilegedPermissions();
+ assertTrue(getTestTransportInfo(mWiFiNetworkAgent).locationRedacted);
+ }
+
private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
throws Exception {
final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
@@ -9840,12 +9879,27 @@ public class ConnectivityServiceTest {
// Connect the cell agent verify that it notifies TestNetworkCallback that it is available
final TestNetworkCallback callback = new TestNetworkCallback();
mCm.registerDefaultNetworkCallback(callback);
- mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+
+ final NetworkCapabilities ncTemplate = new NetworkCapabilities()
+ .addTransportType(TRANSPORT_CELLULAR)
+ .setTransportInfo(new TestTransportInfo());
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(),
+ ncTemplate);
mCellNetworkAgent.connect(true);
callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
callback.assertNoCallback();
}
+ private boolean areConnDiagCapsRedacted(NetworkCapabilities nc) {
+ TestTransportInfo ti = (TestTransportInfo) nc.getTransportInfo();
+ return nc.getUids() == null
+ && nc.getAdministratorUids().length == 0
+ && nc.getOwnerUid() == Process.INVALID_UID
+ && getTestTransportInfo(nc).locationRedacted
+ && getTestTransportInfo(nc).localMacAddressRedacted
+ && getTestTransportInfo(nc).settingsRedacted;
+ }
+
@Test
public void testConnectivityDiagnosticsCallbackOnConnectivityReportAvailable()
throws Exception {
@@ -9856,12 +9910,7 @@ public class ConnectivityServiceTest {
// Verify onConnectivityReport fired
verify(mConnectivityDiagnosticsCallback).onConnectivityReportAvailable(
- argThat(report -> {
- final NetworkCapabilities nc = report.getNetworkCapabilities();
- return nc.getUids() == null
- && nc.getAdministratorUids().length == 0
- && nc.getOwnerUid() == Process.INVALID_UID;
- }));
+ argThat(report -> areConnDiagCapsRedacted(report.getNetworkCapabilities())));
}
@Test
@@ -9877,12 +9926,7 @@ public class ConnectivityServiceTest {
// Verify onDataStallSuspected fired
verify(mConnectivityDiagnosticsCallback).onDataStallSuspected(
- argThat(report -> {
- final NetworkCapabilities nc = report.getNetworkCapabilities();
- return nc.getUids() == null
- && nc.getAdministratorUids().length == 0
- && nc.getOwnerUid() == Process.INVALID_UID;
- }));
+ argThat(report -> areConnDiagCapsRedacted(report.getNetworkCapabilities())));
}
@Test
diff --git a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
index 02a58080fefd..c75618f43cde 100644
--- a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -30,6 +30,8 @@ import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_REQUIRED;
import static android.content.pm.PackageManager.GET_PERMISSIONS;
import static android.content.pm.PackageManager.MATCH_ANY_USER;
+import static android.net.ConnectivitySettingsManager.APPS_ALLOWED_ON_RESTRICTED_NETWORKS;
+import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
import static android.os.Process.SYSTEM_UID;
import static com.android.server.connectivity.PermissionMonitor.NETWORK;
@@ -43,8 +45,10 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.AdditionalMatchers.aryEq;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
@@ -61,6 +65,7 @@ import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.database.ContentObserver;
import android.net.INetd;
import android.net.UidRange;
import android.net.Uri;
@@ -68,6 +73,7 @@ import android.os.Build;
import android.os.SystemConfigManager;
import android.os.UserHandle;
import android.os.UserManager;
+import android.util.ArraySet;
import android.util.SparseIntArray;
import androidx.test.InstrumentationRegistry;
@@ -136,6 +142,7 @@ public class PermissionMonitorTest {
final Context asUserCtx = mock(Context.class, AdditionalAnswers.delegatesTo(mContext));
doReturn(UserHandle.ALL).when(asUserCtx).getUser();
when(mContext.createContextAsUser(eq(UserHandle.ALL), anyInt())).thenReturn(asUserCtx);
+ when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn(new ArraySet<>());
mPermissionMonitor = spy(new PermissionMonitor(mContext, mNetdService, mDeps));
@@ -145,8 +152,15 @@ public class PermissionMonitorTest {
private boolean hasRestrictedNetworkPermission(String partition, int targetSdkVersion, int uid,
String... permissions) {
+ return hasRestrictedNetworkPermission(
+ partition, targetSdkVersion, "" /* packageName */, uid, permissions);
+ }
+
+ private boolean hasRestrictedNetworkPermission(String partition, int targetSdkVersion,
+ String packageName, int uid, String... permissions) {
final PackageInfo packageInfo =
packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED, permissions, partition);
+ packageInfo.packageName = packageName;
packageInfo.applicationInfo.targetSdkVersion = targetSdkVersion;
packageInfo.applicationInfo.uid = uid;
return mPermissionMonitor.hasRestrictedNetworkPermission(packageInfo);
@@ -280,6 +294,8 @@ public class PermissionMonitorTest {
PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
assertFalse(hasRestrictedNetworkPermission(
PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CHANGE_WIFI_STATE));
+ assertTrue(hasRestrictedNetworkPermission(
+ PARTITION_SYSTEM, VERSION_P, MOCK_UID1, PERMISSION_MAINLINE_NETWORK_STACK));
assertFalse(hasRestrictedNetworkPermission(PARTITION_SYSTEM, VERSION_Q, MOCK_UID1));
assertFalse(hasRestrictedNetworkPermission(
@@ -324,6 +340,90 @@ public class PermissionMonitorTest {
PARTITION_VENDOR, VERSION_Q, MOCK_UID1, CHANGE_NETWORK_STATE));
}
+ @Test
+ public void testHasRestrictedNetworkPermissionAppAllowedOnRestrictedNetworks() {
+ mPermissionMonitor.updateAppsAllowedOnRestrictedNetworks(
+ new ArraySet<>(new String[] { MOCK_PACKAGE1 }));
+ assertTrue(hasRestrictedNetworkPermission(
+ PARTITION_VENDOR, VERSION_Q, MOCK_PACKAGE1, MOCK_UID1));
+ assertTrue(hasRestrictedNetworkPermission(
+ PARTITION_VENDOR, VERSION_Q, MOCK_PACKAGE1, MOCK_UID1, CHANGE_NETWORK_STATE));
+ assertTrue(hasRestrictedNetworkPermission(
+ PARTITION_VENDOR, VERSION_Q, MOCK_PACKAGE1, MOCK_UID1, CONNECTIVITY_INTERNAL));
+
+ assertFalse(hasRestrictedNetworkPermission(
+ PARTITION_VENDOR, VERSION_Q, MOCK_PACKAGE2, MOCK_UID1));
+ assertFalse(hasRestrictedNetworkPermission(
+ PARTITION_VENDOR, VERSION_Q, MOCK_PACKAGE2, MOCK_UID1, CHANGE_NETWORK_STATE));
+ assertFalse(hasRestrictedNetworkPermission(
+ PARTITION_VENDOR, VERSION_Q, MOCK_PACKAGE2, MOCK_UID1, CONNECTIVITY_INTERNAL));
+
+ }
+
+ private boolean wouldBeCarryoverPackage(String partition, int targetSdkVersion, int uid) {
+ final PackageInfo packageInfo = packageInfoWithPermissions(
+ REQUESTED_PERMISSION_GRANTED, new String[] {}, partition);
+ packageInfo.applicationInfo.targetSdkVersion = targetSdkVersion;
+ packageInfo.applicationInfo.uid = uid;
+ return mPermissionMonitor.isCarryoverPackage(packageInfo.applicationInfo);
+ }
+
+ @Test
+ public void testIsCarryoverPackage() {
+ doReturn(VERSION_P).when(mDeps).getDeviceFirstSdkInt();
+ assertTrue(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_P, SYSTEM_UID));
+ assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_P, SYSTEM_UID));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_P, MOCK_UID1));
+ assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_P, MOCK_UID1));
+ assertTrue(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID));
+ assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_Q, SYSTEM_UID));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_Q, MOCK_UID1));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_Q, MOCK_UID1));
+
+ doReturn(VERSION_Q).when(mDeps).getDeviceFirstSdkInt();
+ assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_P, SYSTEM_UID));
+ assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_P, SYSTEM_UID));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_P, MOCK_UID1));
+ assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_P, MOCK_UID1));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_Q, SYSTEM_UID));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_Q, MOCK_UID1));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_Q, MOCK_UID1));
+
+ assertFalse(wouldBeCarryoverPackage(PARTITION_OEM, VERSION_Q, SYSTEM_UID));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_PRODUCT, VERSION_Q, SYSTEM_UID));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_OEM, VERSION_Q, MOCK_UID1));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_PRODUCT, VERSION_Q, MOCK_UID1));
+ }
+
+ private boolean wouldBeAppAllowedOnRestrictedNetworks(String packageName) {
+ final PackageInfo packageInfo = new PackageInfo();
+ packageInfo.packageName = packageName;
+ return mPermissionMonitor.isAppAllowedOnRestrictedNetworks(packageInfo);
+ }
+
+ @Test
+ public void testIsAppAllowedOnRestrictedNetworks() {
+ mPermissionMonitor.updateAppsAllowedOnRestrictedNetworks(new ArraySet<>());
+ assertFalse(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE1));
+ assertFalse(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE2));
+
+ mPermissionMonitor.updateAppsAllowedOnRestrictedNetworks(
+ new ArraySet<>(new String[] { MOCK_PACKAGE1 }));
+ assertTrue(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE1));
+ assertFalse(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE2));
+
+ mPermissionMonitor.updateAppsAllowedOnRestrictedNetworks(
+ new ArraySet<>(new String[] { MOCK_PACKAGE2 }));
+ assertFalse(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE1));
+ assertTrue(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE2));
+
+ mPermissionMonitor.updateAppsAllowedOnRestrictedNetworks(
+ new ArraySet<>(new String[] { "com.android.test" }));
+ assertFalse(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE1));
+ assertFalse(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE2));
+ }
+
private void assertBackgroundPermission(boolean hasPermission, String name, int uid,
String... permissions) throws Exception {
when(mPackageManager.getPackageInfo(eq(name), anyInt()))
@@ -800,4 +900,102 @@ public class PermissionMonitorTest {
mNetdServiceMonitor.expectPermission(INetd.PERMISSION_UNINSTALLED, new int[] { MOCK_UID1 });
}
-}
+ @Test
+ public void testAppsAllowedOnRestrictedNetworksChanged() throws Exception {
+ final NetdMonitor mNetdMonitor = new NetdMonitor(mNetdService);
+ final ArgumentCaptor<ContentObserver> captor =
+ ArgumentCaptor.forClass(ContentObserver.class);
+ verify(mDeps, times(1)).registerContentObserver(any(),
+ argThat(uri -> uri.getEncodedPath().contains(APPS_ALLOWED_ON_RESTRICTED_NETWORKS)),
+ anyBoolean(), captor.capture());
+ final ContentObserver contentObserver = captor.getValue();
+
+ mPermissionMonitor.onUserAdded(MOCK_USER1);
+ // Prepare PackageInfo for MOCK_PACKAGE1
+ final PackageInfo packageInfo = buildPackageInfo(
+ false /* hasSystemPermission */, MOCK_UID1, MOCK_USER1);
+ packageInfo.packageName = MOCK_PACKAGE1;
+ when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE1), anyInt())).thenReturn(packageInfo);
+ when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{MOCK_PACKAGE1});
+ // Prepare PackageInfo for MOCK_PACKAGE2
+ final PackageInfo packageInfo2 = buildPackageInfo(
+ false /* hasSystemPermission */, MOCK_UID2, MOCK_USER1);
+ packageInfo2.packageName = MOCK_PACKAGE2;
+ when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE2), anyInt())).thenReturn(packageInfo2);
+ when(mPackageManager.getPackagesForUid(MOCK_UID2)).thenReturn(new String[]{MOCK_PACKAGE2});
+
+ // MOCK_PACKAGE1 is listed in setting that allow to use restricted networks, MOCK_UID1
+ // should have SYSTEM permission.
+ when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn(
+ new ArraySet<>(new String[] { MOCK_PACKAGE1 }));
+ contentObserver.onChange(true /* selfChange */);
+ mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
+ mNetdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID2});
+
+ // MOCK_PACKAGE2 is listed in setting that allow to use restricted networks, MOCK_UID2
+ // should have SYSTEM permission but MOCK_UID1 should revoke permission.
+ when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn(
+ new ArraySet<>(new String[] { MOCK_PACKAGE2 }));
+ contentObserver.onChange(true /* selfChange */);
+ mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID2});
+ mNetdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
+
+ // No app lists in setting, should revoke permission from all uids.
+ when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn(new ArraySet<>());
+ contentObserver.onChange(true /* selfChange */);
+ mNetdMonitor.expectNoPermission(
+ new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1, MOCK_UID2});
+ }
+
+ @Test
+ public void testAppsAllowedOnRestrictedNetworksChangedWithSharedUid() throws Exception {
+ final NetdMonitor mNetdMonitor = new NetdMonitor(mNetdService);
+ final ArgumentCaptor<ContentObserver> captor =
+ ArgumentCaptor.forClass(ContentObserver.class);
+ verify(mDeps, times(1)).registerContentObserver(any(),
+ argThat(uri -> uri.getEncodedPath().contains(APPS_ALLOWED_ON_RESTRICTED_NETWORKS)),
+ anyBoolean(), captor.capture());
+ final ContentObserver contentObserver = captor.getValue();
+
+ mPermissionMonitor.onUserAdded(MOCK_USER1);
+ // Prepare PackageInfo for MOCK_PACKAGE1 and MOCK_PACKAGE2 with shared uid MOCK_UID1.
+ final PackageInfo packageInfo = systemPackageInfoWithPermissions(CHANGE_NETWORK_STATE);
+ packageInfo.applicationInfo.uid = MOCK_USER1.getUid(MOCK_UID1);
+ packageInfo.packageName = MOCK_PACKAGE1;
+ final PackageInfo packageInfo2 = buildPackageInfo(
+ false /* hasSystemPermission */, MOCK_UID1, MOCK_USER1);
+ packageInfo2.packageName = MOCK_PACKAGE2;
+ when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE1), anyInt())).thenReturn(packageInfo);
+ when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE2), anyInt())).thenReturn(packageInfo2);
+ when(mPackageManager.getPackagesForUid(MOCK_UID1))
+ .thenReturn(new String[]{MOCK_PACKAGE1, MOCK_PACKAGE2});
+
+ // MOCK_PACKAGE1 have CHANGE_NETWORK_STATE, MOCK_UID1 should have NETWORK permission.
+ addPackageForUsers(new UserHandle[]{MOCK_USER1}, MOCK_PACKAGE1, MOCK_UID1);
+ mNetdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
+
+ // MOCK_PACKAGE2 is listed in setting that allow to use restricted networks, MOCK_UID1
+ // should upgrade to SYSTEM permission.
+ when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn(
+ new ArraySet<>(new String[] { MOCK_PACKAGE2 }));
+ contentObserver.onChange(true /* selfChange */);
+ mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
+
+ // MOCK_PACKAGE1 is listed in setting that allow to use restricted networks, MOCK_UID1
+ // should still have SYSTEM permission.
+ when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn(
+ new ArraySet<>(new String[] { MOCK_PACKAGE1 }));
+ contentObserver.onChange(true /* selfChange */);
+ mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
+
+ // No app lists in setting, MOCK_UID1 should downgrade to NETWORK permission.
+ when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn(new ArraySet<>());
+ contentObserver.onChange(true /* selfChange */);
+ mNetdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
+
+ // MOCK_PACKAGE1 removed, should revoke permission from MOCK_UID1.
+ when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{MOCK_PACKAGE2});
+ removePackageForUsers(new UserHandle[]{MOCK_USER1}, MOCK_PACKAGE1, MOCK_UID1);
+ mNetdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
+ }
+} \ No newline at end of file
diff --git a/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java
index f3ae9b051e7c..93599f3c376d 100644
--- a/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java
+++ b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java
@@ -43,6 +43,7 @@ import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.frameworks.tests.net.R;
+import com.android.internal.util.test.FsUtil;
import libcore.io.IoUtils;
import libcore.io.Streams;
@@ -71,7 +72,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest {
public void setUp() throws Exception {
mTestProc = new File(InstrumentationRegistry.getContext().getFilesDir(), "proc");
if (mTestProc.exists()) {
- IoUtils.deleteContents(mTestProc);
+ FsUtil.deleteContents(mTestProc);
}
// The libandroid_servers which have the native method is not available to
@@ -87,7 +88,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest {
mFactory = null;
if (mTestProc.exists()) {
- IoUtils.deleteContents(mTestProc);
+ FsUtil.deleteContents(mTestProc);
}
}
diff --git a/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
index fd374bc9e68f..0ba5f7d8241e 100644
--- a/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -112,13 +112,12 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.test.BroadcastInterceptingContext;
+import com.android.internal.util.test.FsUtil;
import com.android.server.net.NetworkStatsService.NetworkStatsSettings;
import com.android.server.net.NetworkStatsService.NetworkStatsSettings.Config;
import com.android.testutils.HandlerUtils;
import com.android.testutils.TestableNetworkStatsProviderBinder;
-import libcore.io.IoUtils;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
@@ -152,6 +151,8 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
private static final String TEST_SSID = "AndroidAP";
private static NetworkTemplate sTemplateWifi = buildTemplateWifi(TEST_SSID);
+ private static NetworkTemplate sTemplateCarrierWifi1 =
+ buildTemplateWifi(NetworkTemplate.WIFI_NETWORKID_ALL, IMSI_1);
private static NetworkTemplate sTemplateImsi1 = buildTemplateMobileAll(IMSI_1);
private static NetworkTemplate sTemplateImsi2 = buildTemplateMobileAll(IMSI_2);
@@ -213,7 +214,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
mServiceContext = new MockContext(context);
mStatsDir = context.getFilesDir();
if (mStatsDir.exists()) {
- IoUtils.deleteContents(mStatsDir);
+ FsUtil.deleteContents(mStatsDir);
}
PowerManager powerManager = (PowerManager) mServiceContext.getSystemService(
@@ -283,7 +284,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
@After
public void tearDown() throws Exception {
- IoUtils.deleteContents(mStatsDir);
+ FsUtil.deleteContents(mStatsDir);
mServiceContext = null;
mStatsDir = null;
@@ -297,45 +298,82 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
mHandlerThread.quitSafely();
}
- @Test
- public void testNetworkStatsWifi() throws Exception {
+ private void initWifiStats(NetworkStateSnapshot snapshot) throws Exception {
// pretend that wifi network comes online; service should ask about full
// network state, and poll any existing interfaces before updating.
expectDefaultSettings();
- NetworkStateSnapshot[] states = new NetworkStateSnapshot[] {buildWifiState()};
+ NetworkStateSnapshot[] states = new NetworkStateSnapshot[] {snapshot};
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
+ }
- // verify service has empty history for wifi
- assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0);
-
- // modify some number on wifi, and trigger poll event
- incrementCurrentTime(HOUR_IN_MILLIS);
+ private void incrementWifiStats(long durationMillis, String iface,
+ long rxb, long rxp, long txb, long txp) throws Exception {
+ incrementCurrentTime(durationMillis);
expectDefaultSettings();
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
- .insertEntry(TEST_IFACE, 1024L, 1L, 2048L, 2L));
+ .insertEntry(iface, rxb, rxp, txb, txp));
expectNetworkStatsUidDetail(buildEmptyStats());
forcePollAndWaitForIdle();
+ }
+
+ @Test
+ public void testNetworkStatsCarrierWifi() throws Exception {
+ initWifiStats(buildWifiState(true, TEST_IFACE, IMSI_1));
+ // verify service has empty history for carrier merged wifi and non-carrier wifi
+ assertNetworkTotal(sTemplateCarrierWifi1, 0L, 0L, 0L, 0L, 0);
+ assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0);
+
+ // modify some number on wifi, and trigger poll event
+ incrementWifiStats(HOUR_IN_MILLIS, TEST_IFACE, 1024L, 1L, 2048L, 2L);
// verify service recorded history
- assertNetworkTotal(sTemplateWifi, 1024L, 1L, 2048L, 2L, 0);
+ assertNetworkTotal(sTemplateCarrierWifi1, 1024L, 1L, 2048L, 2L, 0);
+
+ // verify service recorded history for wifi with SSID filter
+ assertNetworkTotal(sTemplateWifi, 1024L, 1L, 2048L, 2L, 0);
// and bump forward again, with counters going higher. this is
// important, since polling should correctly subtract last snapshot.
- incrementCurrentTime(DAY_IN_MILLIS);
- expectDefaultSettings();
- expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
- .insertEntry(TEST_IFACE, 4096L, 4L, 8192L, 8L));
- expectNetworkStatsUidDetail(buildEmptyStats());
- forcePollAndWaitForIdle();
+ incrementWifiStats(DAY_IN_MILLIS, TEST_IFACE, 4096L, 4L, 8192L, 8L);
// verify service recorded history
+ assertNetworkTotal(sTemplateCarrierWifi1, 4096L, 4L, 8192L, 8L, 0);
+ // verify service recorded history for wifi with SSID filter
assertNetworkTotal(sTemplateWifi, 4096L, 4L, 8192L, 8L, 0);
+ }
+
+ @Test
+ public void testNetworkStatsNonCarrierWifi() throws Exception {
+ initWifiStats(buildWifiState());
+
+ // verify service has empty history for wifi
+ assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0);
+ // verify service has empty history for carrier merged wifi
+ assertNetworkTotal(sTemplateCarrierWifi1, 0L, 0L, 0L, 0L, 0);
+
+ // modify some number on wifi, and trigger poll event
+ incrementWifiStats(HOUR_IN_MILLIS, TEST_IFACE, 1024L, 1L, 2048L, 2L);
+ // verify service recorded history
+ assertNetworkTotal(sTemplateWifi, 1024L, 1L, 2048L, 2L, 0);
+ // verify service has empty history for carrier wifi since current network is non carrier
+ // wifi
+ assertNetworkTotal(sTemplateCarrierWifi1, 0L, 0L, 0L, 0L, 0);
+
+ // and bump forward again, with counters going higher. this is
+ // important, since polling should correctly subtract last snapshot.
+ incrementWifiStats(DAY_IN_MILLIS, TEST_IFACE, 4096L, 4L, 8192L, 8L);
+
+ // verify service recorded history
+ assertNetworkTotal(sTemplateWifi, 4096L, 4L, 8192L, 8L, 0);
+ // verify service has empty history for carrier wifi since current network is non carrier
+ // wifi
+ assertNetworkTotal(sTemplateCarrierWifi1, 0L, 0L, 0L, 0L, 0);
}
@Test
@@ -349,7 +387,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// verify service has empty history for wifi
@@ -423,7 +461,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// modify some number on wifi, and trigger poll event
@@ -464,7 +502,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// create some traffic on first network
@@ -499,7 +537,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
.insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
.insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L));
- mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
forcePollAndWaitForIdle();
@@ -539,7 +577,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// create some traffic
@@ -607,7 +645,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
expectNetworkStatsUidDetail(buildEmptyStats());
setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_UMTS);
- mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// Create some traffic.
@@ -699,7 +737,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
new int[]{NetworkCapabilities.NET_CAPABILITY_OEM_PAID})};
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// Create some traffic.
@@ -714,7 +752,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
new int[]{NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE})};
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// Create some traffic.
@@ -730,7 +768,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
NetworkCapabilities.NET_CAPABILITY_OEM_PAID})};
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// Create some traffic.
@@ -744,7 +782,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
states = new NetworkStateSnapshot[]{buildOemManagedMobileState(IMSI_1, false, new int[]{})};
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// Create some traffic.
@@ -797,7 +835,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// create some traffic for two apps
@@ -856,7 +894,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
NetworkStats.Entry entry1 = new NetworkStats.Entry(
@@ -900,7 +938,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
NetworkStats.Entry uidStats = new NetworkStats.Entry(
@@ -931,7 +969,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
// mStatsFactory#readNetworkStatsDetail() has the following invocations:
// 1) NetworkStatsService#systemReady from #setUp.
- // 2) mService#forceUpdateIfaces in the test above.
+ // 2) mService#notifyNetworkStatus in the test above.
//
// Additionally, we should have one call from the above call to mService#getDetailedUidStats
// with the augmented ifaceFilter.
@@ -955,7 +993,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// create some initial traffic
@@ -1013,7 +1051,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// create some initial traffic
@@ -1053,7 +1091,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// Create some traffic
@@ -1092,7 +1130,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// create some tethering traffic
@@ -1149,7 +1187,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// verify service has empty history for wifi
@@ -1255,7 +1293,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
mService.registerNetworkStatsProvider("TEST", provider);
assertNotNull(cb);
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// Verifies that one requestStatsUpdate will be called during iface update.
@@ -1320,7 +1358,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
mService.registerNetworkStatsProvider("TEST", provider);
assertNotNull(cb);
- mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// Verifies that one requestStatsUpdate will be called during iface update.
@@ -1378,7 +1416,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
expectDefaultSettings();
NetworkStateSnapshot[] states =
new NetworkStateSnapshot[]{buildWifiState(true /* isMetered */, TEST_IFACE)};
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// Register custom provider and retrieve callback.
@@ -1428,7 +1466,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
// 3G network comes online.
setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_UMTS);
- mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// Create some traffic.
@@ -1450,7 +1488,8 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
setCombineSubtypeEnabled(true);
// Call handleOnCollapsedRatTypeChanged manually to simulate the callback fired
- // when stopping monitor, this is needed by NetworkStatsService to trigger updateIfaces.
+ // when stopping monitor, this is needed by NetworkStatsService to trigger
+ // handleNotifyNetworkStatus.
mService.handleOnCollapsedRatTypeChanged();
HandlerUtils.waitForIdle(mHandlerThread, WAIT_TIMEOUT);
// Create some traffic.
@@ -1499,7 +1538,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
NetworkStateSnapshot[] states = new NetworkStateSnapshot[]{
buildWifiState(true /*isMetered*/, TEST_IFACE2), buildMobile3gState(IMSI_1)};
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
// Create some traffic on mobile network.
@@ -1661,10 +1700,15 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
}
private static NetworkStateSnapshot buildWifiState() {
- return buildWifiState(false, TEST_IFACE);
+ return buildWifiState(false, TEST_IFACE, null);
}
private static NetworkStateSnapshot buildWifiState(boolean isMetered, @NonNull String iface) {
+ return buildWifiState(isMetered, iface, null);
+ }
+
+ private static NetworkStateSnapshot buildWifiState(boolean isMetered, @NonNull String iface,
+ String subscriberId) {
final LinkProperties prop = new LinkProperties();
prop.setInterfaceName(iface);
final NetworkCapabilities capabilities = new NetworkCapabilities();
@@ -1672,7 +1716,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true);
capabilities.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
capabilities.setSSID(TEST_SSID);
- return new NetworkStateSnapshot(WIFI_NETWORK, capabilities, prop, null, TYPE_WIFI);
+ return new NetworkStateSnapshot(WIFI_NETWORK, capabilities, prop, subscriberId, TYPE_WIFI);
}
private static NetworkStateSnapshot buildMobile3gState(String subscriberId) {
diff --git a/packages/CtsShim/OWNERS b/packages/CtsShim/OWNERS
index ba9f2b97678a..94197715150d 100644
--- a/packages/CtsShim/OWNERS
+++ b/packages/CtsShim/OWNERS
@@ -1,2 +1,3 @@
ioffe@google.com
-toddke@google.com \ No newline at end of file
+toddke@google.com
+patb@google.com \ No newline at end of file
diff --git a/packages/PackageInstaller/OWNERS b/packages/PackageInstaller/OWNERS
index 8e1774b0baa2..c6331133367a 100644
--- a/packages/PackageInstaller/OWNERS
+++ b/packages/PackageInstaller/OWNERS
@@ -1,5 +1,6 @@
svetoslavganov@google.com
toddke@google.com
+patb@google.com
suprabh@google.com
# For automotive related changes
diff --git a/packages/SettingsProvider/OWNERS b/packages/SettingsProvider/OWNERS
index cf9799c6a026..6c61d4b91d36 100644
--- a/packages/SettingsProvider/OWNERS
+++ b/packages/SettingsProvider/OWNERS
@@ -4,3 +4,4 @@ narayan@google.com
svetoslavganov@google.com
schfan@google.com
toddke@google.com
+patb@google.com
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 27df92f0832b..2a12ce2854b6 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/Shell/OWNERS b/packages/Shell/OWNERS
index 6d738f8d4d43..177f86b08864 100644
--- a/packages/Shell/OWNERS
+++ b/packages/Shell/OWNERS
@@ -7,6 +7,7 @@ svetoslavganov@google.com
hackbod@google.com
yamasani@google.com
toddke@google.com
+patb@google.com
cbrubaker@google.com
omakoto@google.com
michaelwr@google.com
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
index 5a525974f3cb..9e603561acf1 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -114,7 +114,7 @@ class ControlsUiControllerImpl @Inject constructor (
private val onSeedingComplete = Consumer<Boolean> {
accepted ->
if (accepted) {
- selectedStructure = controlsController.get().getFavorites().maxBy {
+ selectedStructure = controlsController.get().getFavorites().maxByOrNull {
it.controls.size
} ?: EMPTY_STRUCTURE
updatePreferences(selectedStructure)
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipBuilder.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipBuilder.kt
index 1d2e74703b42..eec69f98b9be 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipBuilder.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipBuilder.kt
@@ -28,7 +28,7 @@ class PrivacyChipBuilder(private val context: Context, itemsList: List<PrivacyIt
appsAndTypes = itemsList.groupBy({ it.application }, { it.privacyType })
.toList()
.sortedWith(compareBy({ -it.second.size }, // Sort by number of AppOps
- { it.second.min() })) // Sort by "smallest" AppOpp (Location is largest)
+ { it.second.minOrNull() })) // Sort by "smallest" AppOpp (Location is largest)
types = itemsList.map { it.privacyType }.distinct().sorted()
}
diff --git a/services/OWNERS b/services/OWNERS
index 03e0807eea62..3b972e922e95 100644
--- a/services/OWNERS
+++ b/services/OWNERS
@@ -3,4 +3,4 @@ per-file Android.bp = file:platform/build/soong:/OWNERS
# art-team@ manages the system server profile
per-file art-profile* = calin@google.com, mathieuc@google.com, ngeoffray@google.com
-per-file java/com/android/server/* = toddke@google.com
+per-file java/com/android/server/* = toddke@google.com,patb@google.com
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 0ac8f74ff831..706f738d754d 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -10,7 +10,6 @@ package {
filegroup {
name: "services.core-sources",
srcs: ["java/**/*.java"],
- exclude_srcs: [":connectivity-service-srcs"],
path: "java",
visibility: ["//frameworks/base/services"],
}
@@ -200,29 +199,3 @@ prebuilt_etc {
src: ":services.core.json.gz",
}
-// TODO: Move connectivity service sources to independent directory.
-filegroup {
- name: "connectivity-service-srcs",
- srcs: [
- "java/com/android/server/ConnectivityService.java",
- "java/com/android/server/ConnectivityServiceInitializer.java",
- "java/com/android/server/TestNetworkService.java",
- "java/com/android/server/connectivity/AutodestructReference.java",
- "java/com/android/server/connectivity/ConnectivityConstants.java",
- "java/com/android/server/connectivity/DnsManager.java",
- "java/com/android/server/connectivity/FullScore.java",
- "java/com/android/server/connectivity/KeepaliveTracker.java",
- "java/com/android/server/connectivity/LingerMonitor.java",
- "java/com/android/server/connectivity/MockableSystemProperties.java",
- "java/com/android/server/connectivity/Nat464Xlat.java",
- "java/com/android/server/connectivity/NetworkAgentInfo.java",
- "java/com/android/server/connectivity/NetworkDiagnostics.java",
- "java/com/android/server/connectivity/NetworkNotificationManager.java",
- "java/com/android/server/connectivity/NetworkRanker.java",
- "java/com/android/server/connectivity/PermissionMonitor.java",
- "java/com/android/server/connectivity/ProxyTracker.java",
- "java/com/android/server/connectivity/QosCallbackAgentConnection.java",
- "java/com/android/server/connectivity/QosCallbackTracker.java",
- "java/com/android/server/connectivity/TcpKeepaliveController.java",
- ],
-}
diff --git a/services/core/java/android/os/BatteryStatsInternal.java b/services/core/java/android/os/BatteryStatsInternal.java
index 679f18e1e860..5c5edb2bcd49 100644
--- a/services/core/java/android/os/BatteryStatsInternal.java
+++ b/services/core/java/android/os/BatteryStatsInternal.java
@@ -16,6 +16,10 @@
package android.os;
+import com.android.internal.os.BinderCallsStats;
+
+import java.util.Collection;
+
/**
* Battery stats local system service interface. This is used to pass internal data out of
* BatteryStatsImpl, as well as make unchecked calls into BatteryStatsImpl.
@@ -41,4 +45,10 @@ public abstract class BatteryStatsInternal {
* @param sinceLast how long in millis has it been since a job was run
*/
public abstract void noteJobsDeferred(int uid, int numDeferred, long sinceLast);
+
+ /**
+ * Informs battery stats of binder stats for the given work source UID.
+ */
+ public abstract void noteBinderCallStats(int workSourceUid,
+ Collection<BinderCallsStats.CallStat> callStats);
}
diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java
index f4a8f372bc36..339ca84c93cf 100644
--- a/services/core/java/com/android/server/BinderCallsStatsService.java
+++ b/services/core/java/com/android/server/BinderCallsStatsService.java
@@ -26,6 +26,7 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.database.ContentObserver;
import android.net.Uri;
+import android.os.BatteryStatsInternal;
import android.os.Binder;
import android.os.Process;
import android.os.SystemProperties;
@@ -173,10 +174,10 @@ public class BinderCallsStatsService extends Binder {
}
try {
- mParser.setString(Settings.Global.getString(mContext.getContentResolver(),
- Settings.Global.BINDER_CALLS_STATS));
+ mParser.setString(Settings.Global.getString(mContext.getContentResolver(),
+ Settings.Global.BINDER_CALLS_STATS));
} catch (IllegalArgumentException e) {
- Slog.e(TAG, "Bad binder call stats settings", e);
+ Slog.e(TAG, "Bad binder call stats settings", e);
}
mBinderCallsStats.setDetailedTracking(mParser.getBoolean(
SETTINGS_DETAILED_TRACKING_KEY, BinderCallsStats.DETAILED_TRACKING_DEFAULT));
@@ -298,6 +299,11 @@ public class BinderCallsStatsService extends Binder {
CachedDeviceState.Readonly deviceState = getLocalService(
CachedDeviceState.Readonly.class);
mBinderCallsStats.setDeviceState(deviceState);
+
+ BatteryStatsInternal batteryStatsInternal = getLocalService(
+ BatteryStatsInternal.class);
+ mBinderCallsStats.setCallStatsObserver(batteryStatsInternal::noteBinderCallStats);
+
// It needs to be called before mService.systemReady to make sure the observer is
// initialized before installing it.
mWorkSourceProvider.systemReady(getContext());
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 2744f11f1c4e..5122be2b10c4 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -10272,11 +10272,13 @@ public class ActivityManagerService extends IActivityManager.Stub
if (lines > 0) {
sb.append("\n");
- // Merge several logcat streams, and take the last N lines
InputStreamReader input = null;
try {
java.lang.Process logcat = new ProcessBuilder(
- "/system/bin/timeout", "-k", "15s", "10s",
+ // Time out after 10s, but kill logcat with SEGV
+ // so we can investigate why it didn't finish.
+ "/system/bin/timeout", "-s", "SEGV", "10s",
+ // Merge several logcat streams, and take the last N lines.
"/system/bin/logcat", "-v", "threadtime", "-b", "events", "-b", "system",
"-b", "main", "-b", "crash", "-t", String.valueOf(lines))
.redirectErrorStream(true).start();
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 226802c74f25..0260bebbbeac 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -66,6 +66,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IBatteryStats;
import com.android.internal.os.BatteryStatsHelper;
import com.android.internal.os.BatteryStatsImpl;
+import com.android.internal.os.BinderCallsStats;
import com.android.internal.os.PowerProfile;
import com.android.internal.os.RailStats;
import com.android.internal.os.RpmStats;
@@ -87,6 +88,7 @@ import java.nio.charset.CharsetDecoder;
import java.nio.charset.CodingErrorAction;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
+import java.util.Collection;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@@ -304,6 +306,12 @@ public final class BatteryStatsService extends IBatteryStats.Stub
if (DBG) Slog.d(TAG, "Jobs deferred " + uid + ": " + numDeferred + " " + sinceLast);
BatteryStatsService.this.noteJobsDeferred(uid, numDeferred, sinceLast);
}
+
+ @Override
+ public void noteBinderCallStats(int workSourceUid,
+ Collection<BinderCallsStats.CallStat> callStats) {
+ mStats.noteBinderCallStats(workSourceUid, callStats);
+ }
}
private static void awaitUninterruptibly(Future<?> future) {
@@ -1771,5 +1779,4 @@ public final class BatteryStatsService extends IBatteryStats.Stub
Binder.restoreCallingIdentity(ident);
}
}
-
}
diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS
index 90d940939be8..0c8114cdf2e2 100644
--- a/services/core/java/com/android/server/am/OWNERS
+++ b/services/core/java/com/android/server/am/OWNERS
@@ -20,6 +20,7 @@ ogunwale@google.com
# Permissions & Packages
svetoslavganov@google.com
toddke@google.com
+patb@google.com
# Battery Stats
joeo@google.com
diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java
index e7c0a50163da..431b00914f02 100644
--- a/services/core/java/com/android/server/net/NetworkStatsFactory.java
+++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java
@@ -382,8 +382,8 @@ public class NetworkStatsFactory {
// Migrate data usage over a VPN to the TUN network.
for (UnderlyingNetworkInfo info : vpnArray) {
- delta.migrateTun(info.getOwnerUid(), info.getIface(),
- info.getUnderlyingIfaces());
+ delta.migrateTun(info.getOwnerUid(), info.getInterface(),
+ info.getUnderlyingInterfaces());
// Filter out debug entries as that may lead to over counting.
delta.filterDebugEntries();
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 3c14440c6467..4ee867b7d051 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -181,7 +181,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private static final int MSG_PERFORM_POLL = 1;
// Perform polling, persist network, and register the global alert again.
private static final int MSG_PERFORM_POLL_REGISTER_ALERT = 2;
- private static final int MSG_UPDATE_IFACES = 3;
+ private static final int MSG_NOTIFY_NETWORK_STATUS = 3;
// A message for broadcasting ACTION_NETWORK_STATS_UPDATED in handler thread to prevent
// deadlock.
private static final int MSG_BROADCAST_NETWORK_STATS_UPDATED = 4;
@@ -379,11 +379,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
performPoll(FLAG_PERSIST_ALL);
break;
}
- case MSG_UPDATE_IFACES: {
+ case MSG_NOTIFY_NETWORK_STATUS: {
// If no cached states, ignore.
if (mLastNetworkStateSnapshots == null) break;
// TODO (b/181642673): Protect mDefaultNetworks from concurrent accessing.
- updateIfaces(mDefaultNetworks, mLastNetworkStateSnapshots, mActiveIface);
+ handleNotifyNetworkStatus(
+ mDefaultNetworks, mLastNetworkStateSnapshots, mActiveIface);
break;
}
case MSG_PERFORM_POLL_REGISTER_ALERT: {
@@ -474,7 +475,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
@NonNull Looper looper, @NonNull Executor executor,
@NonNull NetworkStatsService service) {
// TODO: Update RatType passively in NSS, instead of querying into the monitor
- // when forceUpdateIface.
+ // when notifyNetworkStatus.
return new NetworkStatsSubscriptionsMonitor(context, looper, executor,
(subscriberId, type) -> service.handleOnCollapsedRatTypeChanged());
}
@@ -971,16 +972,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
}
- public void forceUpdateIfaces(
- Network[] defaultNetworks,
- NetworkStateSnapshot[] networkStates,
- String activeIface,
- UnderlyingNetworkInfo[] underlyingNetworkInfos) {
+ /**
+ * Notify {@code NetworkStatsService} about network status changed.
+ */
+ public void notifyNetworkStatus(
+ @NonNull Network[] defaultNetworks,
+ @NonNull NetworkStateSnapshot[] networkStates,
+ @Nullable String activeIface,
+ @NonNull UnderlyingNetworkInfo[] underlyingNetworkInfos) {
checkNetworkStackPermission(mContext);
final long token = Binder.clearCallingIdentity();
try {
- updateIfaces(defaultNetworks, networkStates, activeIface);
+ handleNotifyNetworkStatus(defaultNetworks, networkStates, activeIface);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -1244,12 +1248,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
@VisibleForTesting
public void handleOnCollapsedRatTypeChanged() {
// Protect service from frequently updating. Remove pending messages if any.
- mHandler.removeMessages(MSG_UPDATE_IFACES);
+ mHandler.removeMessages(MSG_NOTIFY_NETWORK_STATUS);
mHandler.sendMessageDelayed(
- mHandler.obtainMessage(MSG_UPDATE_IFACES), mSettings.getPollDelay());
+ mHandler.obtainMessage(MSG_NOTIFY_NETWORK_STATUS), mSettings.getPollDelay());
}
- private void updateIfaces(
+ private void handleNotifyNetworkStatus(
Network[] defaultNetworks,
NetworkStateSnapshot[] snapshots,
String activeIface) {
@@ -1257,7 +1261,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
mWakeLock.acquire();
try {
mActiveIface = activeIface;
- updateIfacesLocked(defaultNetworks, snapshots);
+ handleNotifyNetworkStatusLocked(defaultNetworks, snapshots);
} finally {
mWakeLock.release();
}
@@ -1270,10 +1274,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
* they are combined under a single {@link NetworkIdentitySet}.
*/
@GuardedBy("mStatsLock")
- private void updateIfacesLocked(@NonNull Network[] defaultNetworks,
+ private void handleNotifyNetworkStatusLocked(@NonNull Network[] defaultNetworks,
@NonNull NetworkStateSnapshot[] snapshots) {
if (!mSystemReady) return;
- if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
+ if (LOGV) Slog.v(TAG, "handleNotifyNetworkStatusLocked()");
// take one last stats snapshot before updating iface mapping. this
// isn't perfect, since the kernel may already be counting traffic from
diff --git a/services/core/java/com/android/server/os/OWNERS b/services/core/java/com/android/server/os/OWNERS
new file mode 100644
index 000000000000..19573323e5ad
--- /dev/null
+++ b/services/core/java/com/android/server/os/OWNERS
@@ -0,0 +1,2 @@
+# Bugreporting
+per-file Bugreport* = file:/platform/frameworks/native:/cmds/dumpstate/OWNERS
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 77c1c1db2257..49a0a8827699 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -31,6 +31,9 @@ import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.os.BatteryManagerInternal;
import android.os.Environment;
+import android.os.IThermalService;
+import android.os.PowerManager;
+import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.UserHandle;
@@ -82,10 +85,15 @@ public class BackgroundDexOptService extends JobService {
private static final int OPTIMIZE_ABORT_BY_JOB_SCHEDULER = 2;
// Optimizations should be aborted. No space left on device.
private static final int OPTIMIZE_ABORT_NO_SPACE_LEFT = 3;
+ // Optimizations should be aborted. Thermal throttling level too high.
+ private static final int OPTIMIZE_ABORT_THERMAL = 4;
// Used for calculating space threshold for downgrading unused apps.
private static final int LOW_THRESHOLD_MULTIPLIER_FOR_DOWNGRADE = 2;
+ // Thermal cutoff value used if one isn't defined by a system property.
+ private static final int THERMAL_CUTOFF_DEFAULT = PowerManager.THERMAL_STATUS_MODERATE;
+
/**
* Set of failed packages remembered across job runs.
*/
@@ -107,8 +115,14 @@ public class BackgroundDexOptService extends JobService {
private static final long mDowngradeUnusedAppsThresholdInMillis =
getDowngradeUnusedAppsThresholdInMillis();
+ private final IThermalService mThermalService =
+ IThermalService.Stub.asInterface(
+ ServiceManager.getService(Context.THERMAL_SERVICE));
+
private static List<PackagesUpdatedListener> sPackagesUpdatedListeners = new ArrayList<>();
+ private int mThermalStatusCutoff = THERMAL_CUTOFF_DEFAULT;
+
public static void schedule(Context context) {
if (isBackgroundDexoptDisabled()) {
return;
@@ -251,12 +265,18 @@ public class BackgroundDexOptService extends JobService {
Slog.w(TAG, "Idle optimizations aborted because of space constraints.");
} else if (result == OPTIMIZE_ABORT_BY_JOB_SCHEDULER) {
Slog.w(TAG, "Idle optimizations aborted by job scheduler.");
+ } else if (result == OPTIMIZE_ABORT_THERMAL) {
+ Slog.w(TAG, "Idle optimizations aborted by thermal throttling.");
} else {
Slog.w(TAG, "Idle optimizations ended with unexpected code: " + result);
}
- if (result != OPTIMIZE_ABORT_BY_JOB_SCHEDULER) {
+
+ if (result == OPTIMIZE_ABORT_THERMAL) {
+ // Abandon our timeslice and reschedule
+ jobFinished(jobParams, /* wantsReschedule */ true);
+ } else if (result != OPTIMIZE_ABORT_BY_JOB_SCHEDULER) {
// Abandon our timeslice and do not reschedule.
- jobFinished(jobParams, /* reschedule */ false);
+ jobFinished(jobParams, /* wantsReschedule */ false);
}
}
}.start();
@@ -542,6 +562,24 @@ public class BackgroundDexOptService extends JobService {
// JobScheduler requested an early abort.
return OPTIMIZE_ABORT_BY_JOB_SCHEDULER;
}
+
+ // Abort background dexopt if the device is in a moderate or stronger thermal throttling
+ // state.
+ try {
+ final int thermalStatus = mThermalService.getCurrentThermalStatus();
+
+ if (DEBUG) {
+ Log.i(TAG, "Thermal throttling status during bgdexopt: " + thermalStatus);
+ }
+
+ if (thermalStatus >= mThermalStatusCutoff) {
+ return OPTIMIZE_ABORT_THERMAL;
+ }
+ } catch (RemoteException ex) {
+ // Because this is a intra-process Binder call it is impossible for a RemoteException
+ // to be raised.
+ }
+
long usableSpace = mDataDir.getUsableSpace();
if (usableSpace < lowStorageThreshold) {
// Rather bail than completely fill up the disk.
@@ -603,6 +641,9 @@ public class BackgroundDexOptService extends JobService {
return false;
}
+ mThermalStatusCutoff =
+ SystemProperties.getInt("dalvik.vm.dexopt.thermal-cutoff", THERMAL_CUTOFF_DEFAULT);
+
boolean result;
if (params.getJobId() == JOB_POST_BOOT_UPDATE) {
result = runPostBootUpdate(params, pm, pkgs);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index fa64df5b1670..836e6150414c 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -5257,6 +5257,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
long[] pattern;
switch (effectId) {
case HapticFeedbackConstants.CONTEXT_CLICK:
+ case HapticFeedbackConstants.GESTURE_END:
return VibrationEffect.get(VibrationEffect.EFFECT_TICK);
case HapticFeedbackConstants.TEXT_HANDLE_MOVE:
if (!mHapticTextHandleEnabled) {
@@ -5269,7 +5270,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case HapticFeedbackConstants.VIRTUAL_KEY_RELEASE:
case HapticFeedbackConstants.ENTRY_BUMP:
case HapticFeedbackConstants.DRAG_CROSSING:
- case HapticFeedbackConstants.GESTURE_END:
return VibrationEffect.get(VibrationEffect.EFFECT_TICK, false);
case HapticFeedbackConstants.KEYBOARD_TAP: // == KEYBOARD_PRESS
case HapticFeedbackConstants.VIRTUAL_KEY:
diff --git a/services/core/java/com/android/server/vcn/OWNERS b/services/core/java/com/android/server/vcn/OWNERS
index 33b9f0f75f81..2441e772468c 100644
--- a/services/core/java/com/android/server/vcn/OWNERS
+++ b/services/core/java/com/android/server/vcn/OWNERS
@@ -3,5 +3,5 @@ set noparent
benedictwong@google.com
ckesting@google.com
evitayan@google.com
+junyin@google.com
nharold@google.com
-jchalard@google.com \ No newline at end of file
diff --git a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
index 19fbdbd86099..5565ccb6cf7c 100644
--- a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
+++ b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
@@ -145,7 +145,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver {
*/
public void handleSubscriptionsChanged() {
final Map<ParcelUuid, Set<String>> privilegedPackages = new HashMap<>();
- final Map<Integer, ParcelUuid> newSubIdToGroupMap = new HashMap<>();
+ final Map<Integer, SubscriptionInfo> newSubIdToInfoMap = new HashMap<>();
final List<SubscriptionInfo> allSubs = mSubscriptionManager.getAllSubscriptionInfoList();
if (allSubs == null) {
@@ -160,7 +160,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver {
}
// Build subId -> subGrp cache
- newSubIdToGroupMap.put(subInfo.getSubscriptionId(), subInfo.getGroupUuid());
+ newSubIdToInfoMap.put(subInfo.getSubscriptionId(), subInfo);
// Update subscription groups that are both ready, and active. For a group to be
// considered active, both of the following must be true:
@@ -186,7 +186,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver {
}
final TelephonySubscriptionSnapshot newSnapshot =
- new TelephonySubscriptionSnapshot(newSubIdToGroupMap, privilegedPackages);
+ new TelephonySubscriptionSnapshot(newSubIdToInfoMap, privilegedPackages);
// If snapshot was meaningfully updated, fire the callback
if (!newSnapshot.equals(mCurrentSnapshot)) {
@@ -245,7 +245,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver {
/** TelephonySubscriptionSnapshot is a class containing info about active subscriptions */
public static class TelephonySubscriptionSnapshot {
- private final Map<Integer, ParcelUuid> mSubIdToGroupMap;
+ private final Map<Integer, SubscriptionInfo> mSubIdToInfoMap;
private final Map<ParcelUuid, Set<String>> mPrivilegedPackages;
public static final TelephonySubscriptionSnapshot EMPTY_SNAPSHOT =
@@ -253,12 +253,12 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver {
@VisibleForTesting(visibility = Visibility.PRIVATE)
TelephonySubscriptionSnapshot(
- @NonNull Map<Integer, ParcelUuid> subIdToGroupMap,
+ @NonNull Map<Integer, SubscriptionInfo> subIdToInfoMap,
@NonNull Map<ParcelUuid, Set<String>> privilegedPackages) {
- Objects.requireNonNull(subIdToGroupMap, "subIdToGroupMap was null");
+ Objects.requireNonNull(subIdToInfoMap, "subIdToInfoMap was null");
Objects.requireNonNull(privilegedPackages, "privilegedPackages was null");
- mSubIdToGroupMap = Collections.unmodifiableMap(subIdToGroupMap);
+ mSubIdToInfoMap = Collections.unmodifiableMap(subIdToInfoMap);
final Map<ParcelUuid, Set<String>> unmodifiableInnerSets = new ArrayMap<>();
for (Entry<ParcelUuid, Set<String>> entry : privilegedPackages.entrySet()) {
@@ -285,7 +285,9 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver {
/** Returns the Subscription Group for a given subId. */
@Nullable
public ParcelUuid getGroupForSubId(int subId) {
- return mSubIdToGroupMap.get(subId);
+ return mSubIdToInfoMap.containsKey(subId)
+ ? mSubIdToInfoMap.get(subId).getGroupUuid()
+ : null;
}
/**
@@ -295,8 +297,8 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver {
public Set<Integer> getAllSubIdsInGroup(ParcelUuid subGrp) {
final Set<Integer> subIds = new ArraySet<>();
- for (Entry<Integer, ParcelUuid> entry : mSubIdToGroupMap.entrySet()) {
- if (subGrp.equals(entry.getValue())) {
+ for (Entry<Integer, SubscriptionInfo> entry : mSubIdToInfoMap.entrySet()) {
+ if (subGrp.equals(entry.getValue().getGroupUuid())) {
subIds.add(entry.getKey());
}
}
@@ -304,9 +306,17 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver {
return subIds;
}
+ /** Checks if the requested subscription is opportunistic */
+ @NonNull
+ public boolean isOpportunistic(int subId) {
+ return mSubIdToInfoMap.containsKey(subId)
+ ? mSubIdToInfoMap.get(subId).isOpportunistic()
+ : false;
+ }
+
@Override
public int hashCode() {
- return Objects.hash(mSubIdToGroupMap, mPrivilegedPackages);
+ return Objects.hash(mSubIdToInfoMap, mPrivilegedPackages);
}
@Override
@@ -317,7 +327,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver {
final TelephonySubscriptionSnapshot other = (TelephonySubscriptionSnapshot) obj;
- return mSubIdToGroupMap.equals(other.mSubIdToGroupMap)
+ return mSubIdToInfoMap.equals(other.mSubIdToInfoMap)
&& mPrivilegedPackages.equals(other.mPrivilegedPackages);
}
@@ -326,7 +336,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver {
pw.println("TelephonySubscriptionSnapshot:");
pw.increaseIndent();
- pw.println("mSubIdToGroupMap: " + mSubIdToGroupMap);
+ pw.println("mSubIdToInfoMap: " + mSubIdToInfoMap);
pw.println("mPrivilegedPackages: " + mPrivilegedPackages);
pw.decreaseIndent();
@@ -335,7 +345,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver {
@Override
public String toString() {
return "TelephonySubscriptionSnapshot{ "
- + "mSubIdToGroupMap=" + mSubIdToGroupMap
+ + "mSubIdToInfoMap=" + mSubIdToInfoMap
+ ", mPrivilegedPackages=" + mPrivilegedPackages
+ " }";
}
diff --git a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java
index 3bdeec0c1d8e..b05662e1678e 100644
--- a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java
+++ b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java
@@ -16,6 +16,10 @@
package com.android.server.vcn;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.net.ConnectivityManager;
@@ -25,8 +29,16 @@ import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.TelephonyNetworkSpecifier;
+import android.net.vcn.VcnManager;
import android.os.Handler;
+import android.os.HandlerExecutor;
import android.os.ParcelUuid;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyCallback;
+import android.telephony.TelephonyManager;
+import android.util.ArrayMap;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
@@ -35,9 +47,13 @@ import com.android.internal.util.IndentingPrintWriter;
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.TreeSet;
/**
* Tracks a set of Networks underpinning a VcnGatewayConnection.
@@ -51,19 +67,62 @@ import java.util.Set;
public class UnderlyingNetworkTracker {
@NonNull private static final String TAG = UnderlyingNetworkTracker.class.getSimpleName();
+ /**
+ * Minimum signal strength for a WiFi network to be eligible for switching to
+ *
+ * <p>A network that satisfies this is eligible to become the selected underlying network with
+ * no additional conditions
+ */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final int WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT = -70;
+
+ /**
+ * Minimum signal strength to continue using a WiFi network
+ *
+ * <p>A network that satisfies the conditions may ONLY continue to be used if it is already
+ * selected as the underlying network. A WiFi network satisfying this condition, but NOT the
+ * prospective-network RSSI threshold CANNOT be switched to.
+ */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final int WIFI_EXIT_RSSI_THRESHOLD_DEFAULT = -74;
+
+ /** Priority for any cellular network for which the subscription is listed as opportunistic */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final int PRIORITY_OPPORTUNISTIC_CELLULAR = 0;
+
+ /** Priority for any WiFi network which is in use, and satisfies the in-use RSSI threshold */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final int PRIORITY_WIFI_IN_USE = 1;
+
+ /** Priority for any WiFi network which satisfies the prospective-network RSSI threshold */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final int PRIORITY_WIFI_PROSPECTIVE = 2;
+
+ /** Priority for any standard macro cellular network */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final int PRIORITY_MACRO_CELLULAR = 3;
+
+ /** Priority for any other networks (including unvalidated, etc) */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final int PRIORITY_ANY = Integer.MAX_VALUE;
+
@NonNull private final VcnContext mVcnContext;
@NonNull private final ParcelUuid mSubscriptionGroup;
- @NonNull private final Set<Integer> mRequiredUnderlyingNetworkCapabilities;
@NonNull private final UnderlyingNetworkTrackerCallback mCb;
@NonNull private final Dependencies mDeps;
@NonNull private final Handler mHandler;
@NonNull private final ConnectivityManager mConnectivityManager;
+ @NonNull private final TelephonyCallback mActiveDataSubIdListener =
+ new VcnActiveDataSubscriptionIdListener();
@NonNull private final List<NetworkCallback> mCellBringupCallbacks = new ArrayList<>();
@Nullable private NetworkCallback mWifiBringupCallback;
- @Nullable private NetworkCallback mRouteSelectionCallback;
+ @Nullable private NetworkCallback mWifiEntryRssiThresholdCallback;
+ @Nullable private NetworkCallback mWifiExitRssiThresholdCallback;
+ @Nullable private UnderlyingNetworkListener mRouteSelectionCallback;
@NonNull private TelephonySubscriptionSnapshot mLastSnapshot;
+ @Nullable private PersistableBundle mCarrierConfig;
private boolean mIsQuitting = false;
@Nullable private UnderlyingNetworkRecord mCurrentRecord;
@@ -73,13 +132,11 @@ public class UnderlyingNetworkTracker {
@NonNull VcnContext vcnContext,
@NonNull ParcelUuid subscriptionGroup,
@NonNull TelephonySubscriptionSnapshot snapshot,
- @NonNull Set<Integer> requiredUnderlyingNetworkCapabilities,
@NonNull UnderlyingNetworkTrackerCallback cb) {
this(
vcnContext,
subscriptionGroup,
snapshot,
- requiredUnderlyingNetworkCapabilities,
cb,
new Dependencies());
}
@@ -88,22 +145,41 @@ public class UnderlyingNetworkTracker {
@NonNull VcnContext vcnContext,
@NonNull ParcelUuid subscriptionGroup,
@NonNull TelephonySubscriptionSnapshot snapshot,
- @NonNull Set<Integer> requiredUnderlyingNetworkCapabilities,
@NonNull UnderlyingNetworkTrackerCallback cb,
@NonNull Dependencies deps) {
mVcnContext = Objects.requireNonNull(vcnContext, "Missing vcnContext");
mSubscriptionGroup = Objects.requireNonNull(subscriptionGroup, "Missing subscriptionGroup");
mLastSnapshot = Objects.requireNonNull(snapshot, "Missing snapshot");
- mRequiredUnderlyingNetworkCapabilities =
- Objects.requireNonNull(
- requiredUnderlyingNetworkCapabilities,
- "Missing requiredUnderlyingNetworkCapabilities");
mCb = Objects.requireNonNull(cb, "Missing cb");
mDeps = Objects.requireNonNull(deps, "Missing deps");
mHandler = new Handler(mVcnContext.getLooper());
mConnectivityManager = mVcnContext.getContext().getSystemService(ConnectivityManager.class);
+ mVcnContext
+ .getContext()
+ .getSystemService(TelephonyManager.class)
+ .registerTelephonyCallback(new HandlerExecutor(mHandler), mActiveDataSubIdListener);
+
+ // TODO: Listen for changes in carrier config that affect this.
+ for (int subId : mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup)) {
+ PersistableBundle config =
+ mVcnContext
+ .getContext()
+ .getSystemService(CarrierConfigManager.class)
+ .getConfigForSubId(subId);
+
+ if (config != null) {
+ mCarrierConfig = config;
+
+ // Attempt to use (any) non-opportunistic subscription. If this subscription is
+ // opportunistic, continue and try to find a non-opportunistic subscription, using
+ // the opportunistic ones as a last resort.
+ if (!isOpportunistic(mLastSnapshot, Collections.singleton(subId))) {
+ break;
+ }
+ }
+ }
registerOrUpdateNetworkRequests();
}
@@ -111,16 +187,30 @@ public class UnderlyingNetworkTracker {
private void registerOrUpdateNetworkRequests() {
NetworkCallback oldRouteSelectionCallback = mRouteSelectionCallback;
NetworkCallback oldWifiCallback = mWifiBringupCallback;
+ NetworkCallback oldWifiEntryRssiThresholdCallback = mWifiEntryRssiThresholdCallback;
+ NetworkCallback oldWifiExitRssiThresholdCallback = mWifiExitRssiThresholdCallback;
List<NetworkCallback> oldCellCallbacks = new ArrayList<>(mCellBringupCallbacks);
mCellBringupCallbacks.clear();
// Register new callbacks. Make-before-break; always register new callbacks before removal
// of old callbacks
if (!mIsQuitting) {
- mRouteSelectionCallback = new RouteSelectionCallback();
- mConnectivityManager.requestBackgroundNetwork(
+ mRouteSelectionCallback = new UnderlyingNetworkListener();
+ mConnectivityManager.registerNetworkCallback(
getRouteSelectionRequest(), mRouteSelectionCallback, mHandler);
+ mWifiEntryRssiThresholdCallback = new NetworkBringupCallback();
+ mConnectivityManager.registerNetworkCallback(
+ getWifiEntryRssiThresholdNetworkRequest(),
+ mWifiEntryRssiThresholdCallback,
+ mHandler);
+
+ mWifiExitRssiThresholdCallback = new NetworkBringupCallback();
+ mConnectivityManager.registerNetworkCallback(
+ getWifiExitRssiThresholdNetworkRequest(),
+ mWifiExitRssiThresholdCallback,
+ mHandler);
+
mWifiBringupCallback = new NetworkBringupCallback();
mConnectivityManager.requestBackgroundNetwork(
getWifiNetworkRequest(), mWifiBringupCallback, mHandler);
@@ -135,6 +225,8 @@ public class UnderlyingNetworkTracker {
} else {
mRouteSelectionCallback = null;
mWifiBringupCallback = null;
+ mWifiEntryRssiThresholdCallback = null;
+ mWifiExitRssiThresholdCallback = null;
// mCellBringupCallbacks already cleared above.
}
@@ -145,6 +237,12 @@ public class UnderlyingNetworkTracker {
if (oldWifiCallback != null) {
mConnectivityManager.unregisterNetworkCallback(oldWifiCallback);
}
+ if (oldWifiEntryRssiThresholdCallback != null) {
+ mConnectivityManager.unregisterNetworkCallback(oldWifiEntryRssiThresholdCallback);
+ }
+ if (oldWifiExitRssiThresholdCallback != null) {
+ mConnectivityManager.unregisterNetworkCallback(oldWifiExitRssiThresholdCallback);
+ }
for (NetworkCallback cellBringupCallback : oldCellCallbacks) {
mConnectivityManager.unregisterNetworkCallback(cellBringupCallback);
}
@@ -168,6 +266,8 @@ public class UnderlyingNetworkTracker {
}
return getBaseNetworkRequestBuilder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)
.setSubscriptionIds(mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup))
.build();
}
@@ -189,6 +289,38 @@ public class UnderlyingNetworkTracker {
}
/**
+ * Builds the WiFi entry threshold signal strength request
+ *
+ * <p>This request ensures that WiFi reports the crossing of the wifi entry RSSI threshold.
+ * Without this request, WiFi rate-limits, and reports signal strength changes at too slow a
+ * pace to effectively select a short-lived WiFi offload network.
+ */
+ private NetworkRequest getWifiEntryRssiThresholdNetworkRequest() {
+ return getBaseNetworkRequestBuilder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .setSubscriptionIds(mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup))
+ // Ensure wifi updates signal strengths when crossing this threshold.
+ .setSignalStrength(getWifiEntryRssiThreshold(mCarrierConfig))
+ .build();
+ }
+
+ /**
+ * Builds the WiFi exit threshold signal strength request
+ *
+ * <p>This request ensures that WiFi reports the crossing of the wifi exit RSSI threshold.
+ * Without this request, WiFi rate-limits, and reports signal strength changes at too slow a
+ * pace to effectively select away from a failing WiFi network.
+ */
+ private NetworkRequest getWifiExitRssiThresholdNetworkRequest() {
+ return getBaseNetworkRequestBuilder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .setSubscriptionIds(mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup))
+ // Ensure wifi updates signal strengths when crossing this threshold.
+ .setSignalStrength(getWifiExitRssiThreshold(mCarrierConfig))
+ .build();
+ }
+
+ /**
* Builds a Cellular bringup request for a given subId
*
* <p>This request is filed in order to ensure that the Telephony stack always has a
@@ -233,10 +365,18 @@ public class UnderlyingNetworkTracker {
* reevaluate its NetworkBringupCallbacks. This may result in NetworkRequests being registered
* or unregistered if the subIds mapped to the this Tracker's SubscriptionGroup change.
*/
- public void updateSubscriptionSnapshot(@NonNull TelephonySubscriptionSnapshot snapshot) {
- Objects.requireNonNull(snapshot, "Missing snapshot");
+ public void updateSubscriptionSnapshot(@NonNull TelephonySubscriptionSnapshot newSnapshot) {
+ Objects.requireNonNull(newSnapshot, "Missing newSnapshot");
+
+ final TelephonySubscriptionSnapshot oldSnapshot = mLastSnapshot;
+ mLastSnapshot = newSnapshot;
- mLastSnapshot = snapshot;
+ // Only trigger re-registration if subIds in this group have changed
+ if (oldSnapshot
+ .getAllSubIdsInGroup(mSubscriptionGroup)
+ .equals(newSnapshot.getAllSubIdsInGroup(mSubscriptionGroup))) {
+ return;
+ }
registerOrUpdateNetworkRequests();
}
@@ -247,88 +387,43 @@ public class UnderlyingNetworkTracker {
// Will unregister all existing callbacks, but not register new ones due to quitting flag.
registerOrUpdateNetworkRequests();
- }
- /** Returns whether the currently selected Network matches the given network. */
- private static boolean isSameNetwork(
- @Nullable UnderlyingNetworkRecord.Builder recordInProgress, @NonNull Network network) {
- return recordInProgress != null && recordInProgress.getNetwork().equals(network);
+ mVcnContext
+ .getContext()
+ .getSystemService(TelephonyManager.class)
+ .unregisterTelephonyCallback(mActiveDataSubIdListener);
}
- /** Notify the Callback if a full UnderlyingNetworkRecord exists. */
- private void maybeNotifyCallback() {
- // Only forward this update if a complete record has been received
- if (!mRecordInProgress.isValid()) {
- return;
- }
+ private void reevaluateNetworks() {
+ TreeSet<UnderlyingNetworkRecord> sorted =
+ new TreeSet<>(
+ UnderlyingNetworkRecord.getComparator(
+ mSubscriptionGroup, mLastSnapshot, mCurrentRecord, mCarrierConfig));
+ sorted.addAll(mRouteSelectionCallback.getUnderlyingNetworks());
- // Only forward this update if the updated record differs form the current record
- UnderlyingNetworkRecord updatedRecord = mRecordInProgress.build();
- if (!updatedRecord.equals(mCurrentRecord)) {
- mCurrentRecord = updatedRecord;
-
- mCb.onSelectedUnderlyingNetworkChanged(mCurrentRecord);
- }
- }
-
- private void handleNetworkAvailable(@NonNull Network network) {
- mVcnContext.ensureRunningOnLooperThread();
-
- mRecordInProgress = new UnderlyingNetworkRecord.Builder(network);
- }
-
- private void handleNetworkLost(@NonNull Network network) {
- mVcnContext.ensureRunningOnLooperThread();
-
- if (!isSameNetwork(mRecordInProgress, network)) {
- Slog.wtf(TAG, "Non-underlying Network lost");
+ UnderlyingNetworkRecord candidate = sorted.isEmpty() ? null : sorted.first();
+ if (Objects.equals(mCurrentRecord, candidate)) {
return;
}
- mRecordInProgress = null;
- mCurrentRecord = null;
- mCb.onSelectedUnderlyingNetworkChanged(null /* underlyingNetworkRecord */);
+ mCurrentRecord = candidate;
+ mCb.onSelectedUnderlyingNetworkChanged(mCurrentRecord);
}
- private void handleCapabilitiesChanged(
- @NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) {
- mVcnContext.ensureRunningOnLooperThread();
-
- if (!isSameNetwork(mRecordInProgress, network)) {
- Slog.wtf(TAG, "Invalid update to NetworkCapabilities");
- return;
+ private static boolean isOpportunistic(
+ @NonNull TelephonySubscriptionSnapshot snapshot, Set<Integer> subIds) {
+ if (snapshot == null) {
+ Slog.wtf(TAG, "Got null snapshot");
+ return false;
}
- mRecordInProgress.setNetworkCapabilities(networkCapabilities);
-
- maybeNotifyCallback();
- }
-
- private void handlePropertiesChanged(
- @NonNull Network network, @NonNull LinkProperties linkProperties) {
- mVcnContext.ensureRunningOnLooperThread();
-
- if (!isSameNetwork(mRecordInProgress, network)) {
- Slog.wtf(TAG, "Invalid update to LinkProperties");
- return;
- }
-
- mRecordInProgress.setLinkProperties(linkProperties);
-
- maybeNotifyCallback();
- }
-
- private void handleNetworkBlocked(@NonNull Network network, boolean isBlocked) {
- mVcnContext.ensureRunningOnLooperThread();
-
- if (!isSameNetwork(mRecordInProgress, network)) {
- Slog.wtf(TAG, "Invalid update to isBlocked");
- return;
+ for (int subId : subIds) {
+ if (snapshot.isOpportunistic(subId)) {
+ return true;
+ }
}
- mRecordInProgress.setIsBlocked(isBlocked);
-
- maybeNotifyCallback();
+ return false;
}
/**
@@ -347,36 +442,104 @@ public class UnderlyingNetworkTracker {
* truth.
*/
@VisibleForTesting
- class RouteSelectionCallback extends NetworkCallback {
+ class UnderlyingNetworkListener extends NetworkCallback {
+ private final Map<Network, UnderlyingNetworkRecord.Builder>
+ mUnderlyingNetworkRecordBuilders = new ArrayMap<>();
+
+ private List<UnderlyingNetworkRecord> getUnderlyingNetworks() {
+ final List<UnderlyingNetworkRecord> records = new ArrayList<>();
+
+ for (UnderlyingNetworkRecord.Builder builder :
+ mUnderlyingNetworkRecordBuilders.values()) {
+ if (builder.isValid()) {
+ records.add(builder.build());
+ }
+ }
+
+ return records;
+ }
+
@Override
public void onAvailable(@NonNull Network network) {
- handleNetworkAvailable(network);
+ mUnderlyingNetworkRecordBuilders.put(
+ network, new UnderlyingNetworkRecord.Builder(network));
}
@Override
public void onLost(@NonNull Network network) {
- handleNetworkLost(network);
+ mUnderlyingNetworkRecordBuilders.remove(network);
+
+ reevaluateNetworks();
}
@Override
public void onCapabilitiesChanged(
@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) {
- if (networkCapabilities.equals(mRecordInProgress.getNetworkCapabilities())) return;
- handleCapabilitiesChanged(network, networkCapabilities);
+ final UnderlyingNetworkRecord.Builder builder =
+ mUnderlyingNetworkRecordBuilders.get(network);
+ if (builder == null) {
+ Slog.wtf(TAG, "Got capabilities change for unknown key: " + network);
+ return;
+ }
+
+ builder.setNetworkCapabilities(networkCapabilities);
+ if (builder.isValid()) {
+ reevaluateNetworks();
+ }
}
@Override
public void onLinkPropertiesChanged(
@NonNull Network network, @NonNull LinkProperties linkProperties) {
- handlePropertiesChanged(network, linkProperties);
+ final UnderlyingNetworkRecord.Builder builder =
+ mUnderlyingNetworkRecordBuilders.get(network);
+ if (builder == null) {
+ Slog.wtf(TAG, "Got link properties change for unknown key: " + network);
+ return;
+ }
+
+ builder.setLinkProperties(linkProperties);
+ if (builder.isValid()) {
+ reevaluateNetworks();
+ }
}
@Override
public void onBlockedStatusChanged(@NonNull Network network, boolean isBlocked) {
- handleNetworkBlocked(network, isBlocked);
+ final UnderlyingNetworkRecord.Builder builder =
+ mUnderlyingNetworkRecordBuilders.get(network);
+ if (builder == null) {
+ Slog.wtf(TAG, "Got blocked status change for unknown key: " + network);
+ return;
+ }
+
+ builder.setIsBlocked(isBlocked);
+ if (builder.isValid()) {
+ reevaluateNetworks();
+ }
}
}
+ private static int getWifiEntryRssiThreshold(@Nullable PersistableBundle carrierConfig) {
+ if (carrierConfig != null) {
+ return carrierConfig.getInt(
+ VcnManager.VCN_NETWORK_SELECTION_WIFI_ENTRY_RSSI_THRESHOLD_KEY,
+ WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT);
+ }
+
+ return WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT;
+ }
+
+ private static int getWifiExitRssiThreshold(@Nullable PersistableBundle carrierConfig) {
+ if (carrierConfig != null) {
+ return carrierConfig.getInt(
+ VcnManager.VCN_NETWORK_SELECTION_WIFI_EXIT_RSSI_THRESHOLD_KEY,
+ WIFI_EXIT_RSSI_THRESHOLD_DEFAULT);
+ }
+
+ return WIFI_EXIT_RSSI_THRESHOLD_DEFAULT;
+ }
+
/** A record of a single underlying network, caching relevant fields. */
public static class UnderlyingNetworkRecord {
@NonNull public final Network network;
@@ -413,6 +576,89 @@ public class UnderlyingNetworkTracker {
return Objects.hash(network, networkCapabilities, linkProperties, isBlocked);
}
+ /**
+ * Gives networks a priority class, based on the following priorities:
+ *
+ * <ol>
+ * <li>Opportunistic cellular
+ * <li>Carrier WiFi, signal strength >= WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT
+ * <li>Carrier WiFi, active network + signal strength >= WIFI_EXIT_RSSI_THRESHOLD_DEFAULT
+ * <li>Macro cellular
+ * <li>Any others
+ * </ol>
+ */
+ private int calculatePriorityClass(
+ ParcelUuid subscriptionGroup,
+ TelephonySubscriptionSnapshot snapshot,
+ UnderlyingNetworkRecord currentlySelected,
+ PersistableBundle carrierConfig) {
+ final NetworkCapabilities caps = networkCapabilities;
+
+ // mRouteSelectionNetworkRequest requires a network be both VALIDATED and NOT_SUSPENDED
+
+ if (isBlocked) {
+ Slog.wtf(TAG, "Network blocked for System Server: " + network);
+ return PRIORITY_ANY;
+ }
+
+ if (caps.hasTransport(TRANSPORT_CELLULAR)
+ && isOpportunistic(snapshot, caps.getSubscriptionIds())) {
+ // If this carrier is the active data provider, ensure that opportunistic is only
+ // ever prioritized if it is also the active data subscription. This ensures that
+ // if an opportunistic subscription is still in the process of being switched to,
+ // or switched away from, the VCN does not attempt to continue using it against the
+ // decision made at the telephony layer. Failure to do so may result in the modem
+ // switching back and forth.
+ //
+ // Allow the following two cases:
+ // 1. Active subId is NOT in the group that this VCN is supporting
+ // 2. This opportunistic subscription is for the active subId
+ if (!snapshot.getAllSubIdsInGroup(subscriptionGroup)
+ .contains(SubscriptionManager.getActiveDataSubscriptionId())
+ || caps.getSubscriptionIds()
+ .contains(SubscriptionManager.getActiveDataSubscriptionId())) {
+ return PRIORITY_OPPORTUNISTIC_CELLULAR;
+ }
+ }
+
+ if (caps.hasTransport(TRANSPORT_WIFI)) {
+ if (caps.getSignalStrength() >= getWifiExitRssiThreshold(carrierConfig)
+ && currentlySelected != null
+ && network.equals(currentlySelected.network)) {
+ return PRIORITY_WIFI_IN_USE;
+ }
+
+ if (caps.getSignalStrength() >= getWifiEntryRssiThreshold(carrierConfig)) {
+ return PRIORITY_WIFI_PROSPECTIVE;
+ }
+ }
+
+ // Disallow opportunistic subscriptions from matching PRIORITY_MACRO_CELLULAR, as might
+ // be the case when Default Data SubId (CBRS) != Active Data SubId (MACRO), as might be
+ // the case if the Default Data SubId does not support certain services (eg voice
+ // calling)
+ if (caps.hasTransport(TRANSPORT_CELLULAR)
+ && !isOpportunistic(snapshot, caps.getSubscriptionIds())) {
+ return PRIORITY_MACRO_CELLULAR;
+ }
+
+ return PRIORITY_ANY;
+ }
+
+ private static Comparator<UnderlyingNetworkRecord> getComparator(
+ ParcelUuid subscriptionGroup,
+ TelephonySubscriptionSnapshot snapshot,
+ UnderlyingNetworkRecord currentlySelected,
+ PersistableBundle carrierConfig) {
+ return (left, right) -> {
+ return Integer.compare(
+ left.calculatePriorityClass(
+ subscriptionGroup, snapshot, currentlySelected, carrierConfig),
+ right.calculatePriorityClass(
+ subscriptionGroup, snapshot, currentlySelected, carrierConfig));
+ };
+ }
+
/** Dumps the state of this record for logging and debugging purposes. */
public void dump(IndentingPrintWriter pw) {
pw.println("UnderlyingNetworkRecord:");
@@ -434,6 +680,8 @@ public class UnderlyingNetworkTracker {
boolean mIsBlocked;
boolean mWasIsBlockedSet;
+ @Nullable private UnderlyingNetworkRecord mCached;
+
private Builder(@NonNull Network network) {
mNetwork = network;
}
@@ -445,6 +693,7 @@ public class UnderlyingNetworkTracker {
private void setNetworkCapabilities(@NonNull NetworkCapabilities networkCapabilities) {
mNetworkCapabilities = networkCapabilities;
+ mCached = null;
}
@Nullable
@@ -454,11 +703,13 @@ public class UnderlyingNetworkTracker {
private void setLinkProperties(@NonNull LinkProperties linkProperties) {
mLinkProperties = linkProperties;
+ mCached = null;
}
private void setIsBlocked(boolean isBlocked) {
mIsBlocked = isBlocked;
mWasIsBlockedSet = true;
+ mCached = null;
}
private boolean isValid() {
@@ -466,12 +717,30 @@ public class UnderlyingNetworkTracker {
}
private UnderlyingNetworkRecord build() {
- return new UnderlyingNetworkRecord(
- mNetwork, mNetworkCapabilities, mLinkProperties, mIsBlocked);
+ if (!isValid()) {
+ throw new IllegalArgumentException(
+ "Called build before UnderlyingNetworkRecord was valid");
+ }
+
+ if (mCached == null) {
+ mCached =
+ new UnderlyingNetworkRecord(
+ mNetwork, mNetworkCapabilities, mLinkProperties, mIsBlocked);
+ }
+
+ return mCached;
}
}
}
+ private class VcnActiveDataSubscriptionIdListener extends TelephonyCallback
+ implements ActiveDataSubscriptionIdListener {
+ @Override
+ public void onActiveDataSubscriptionIdChanged(int subId) {
+ reevaluateNetworks();
+ }
+ }
+
/** Callbacks for being notified of the changes in, or to the selected underlying network. */
public interface UnderlyingNetworkTrackerCallback {
/**
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index 5cecff6f93c1..dff04bfc6d7c 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -673,7 +673,6 @@ public class VcnGatewayConnection extends StateMachine {
mVcnContext,
subscriptionGroup,
mLastSnapshot,
- mConnectionConfig.getAllUnderlyingCapabilities(),
mUnderlyingNetworkTrackerCallback);
mIpSecManager = mVcnContext.getContext().getSystemService(IpSecManager.class);
@@ -2274,13 +2273,11 @@ public class VcnGatewayConnection extends StateMachine {
VcnContext vcnContext,
ParcelUuid subscriptionGroup,
TelephonySubscriptionSnapshot snapshot,
- Set<Integer> requiredUnderlyingNetworkCapabilities,
UnderlyingNetworkTrackerCallback callback) {
return new UnderlyingNetworkTracker(
vcnContext,
subscriptionGroup,
snapshot,
- requiredUnderlyingNetworkCapabilities,
callback);
}
diff --git a/services/incremental/OWNERS b/services/incremental/OWNERS
index ad5eca7f6daf..7ebb962c8feb 100644
--- a/services/incremental/OWNERS
+++ b/services/incremental/OWNERS
@@ -5,3 +5,4 @@ alexbuy@google.com
schfan@google.com
toddke@google.com
zyy@google.com
+patb@google.com
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index a02a039c3beb..d041eecab17b 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -159,13 +159,13 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.internal.util.test.BroadcastInterceptingContext.FutureIntent;
+import com.android.internal.util.test.FsUtil;
import com.android.server.DeviceIdleInternal;
import com.android.server.LocalServices;
import com.android.server.usage.AppStandbyInternal;
import com.google.common.util.concurrent.AbstractFuture;
-import libcore.io.IoUtils;
import libcore.io.Streams;
import org.junit.After;
@@ -2347,7 +2347,7 @@ public class NetworkPolicyManagerServiceTest {
private void setNetpolicyXml(Context context) throws Exception {
mPolicyDir = context.getFilesDir();
if (mPolicyDir.exists()) {
- IoUtils.deleteContents(mPolicyDir);
+ FsUtil.deleteContents(mPolicyDir);
}
if (!TextUtils.isEmpty(mNetpolicyXml)) {
final String assetPath = NETPOLICY_DIR + "/" + mNetpolicyXml;
diff --git a/tests/BackgroundDexOptServiceIntegrationTests/OWNERS b/tests/BackgroundDexOptServiceIntegrationTests/OWNERS
new file mode 100644
index 000000000000..3414a7469ac2
--- /dev/null
+++ b/tests/BackgroundDexOptServiceIntegrationTests/OWNERS
@@ -0,0 +1 @@
+include platform/art:/OWNERS
diff --git a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
index e05816eb391f..90ddb6ffb34a 100644
--- a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
+++ b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
@@ -20,6 +20,7 @@ import android.app.AlarmManager;
import android.content.Context;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
+import android.os.PowerManager;
import android.os.SystemProperties;
import android.os.storage.StorageManager;
import android.util.Log;
@@ -201,11 +202,16 @@ public final class BackgroundDexOptServiceIntegrationTests {
fillUpStorage((long) (getStorageLowBytes() * LOW_STORAGE_MULTIPLIER));
}
- // TODO(aeubanks): figure out how to get scheduled bg-dexopt to run
private static void runBackgroundDexOpt() throws IOException {
+ runBackgroundDexOpt("Success");
+ }
+
+ // TODO(aeubanks): figure out how to get scheduled bg-dexopt to run
+ private static void runBackgroundDexOpt(String expectedStatus) throws IOException {
String result = runShellCommand("cmd package bg-dexopt-job " + PACKAGE_NAME);
- if (!result.trim().equals("Success")) {
- throw new IllegalStateException("Expected command success, received >" + result + "<");
+ if (!result.trim().equals(expectedStatus)) {
+ throw new IllegalStateException("Expected status: " + expectedStatus
+ + "; Received: " + result.trim());
}
}
@@ -242,6 +248,16 @@ public final class BackgroundDexOptServiceIntegrationTests {
runShellCommand(String.format("cmd package compile -f -m %s %s", filter, pkg));
}
+ // Override the thermal status of the device
+ public static void overrideThermalStatus(int status) throws IOException {
+ runShellCommand("cmd thermalservice override-status " + status);
+ }
+
+ // Reset the thermal status of the device
+ public static void resetThermalStatus() throws IOException {
+ runShellCommand("cmd thermalservice reset");
+ }
+
// Test that background dexopt under normal conditions succeeds.
@Test
public void testBackgroundDexOpt() throws IOException {
@@ -307,4 +323,17 @@ public final class BackgroundDexOptServiceIntegrationTests {
}
}
+ // Test that background dexopt job doesn't trigger if the device is under thermal throttling.
+ @Test
+ public void testBackgroundDexOptThermalThrottling() throws IOException {
+ try {
+ compilePackageWithFilter(PACKAGE_NAME, "verify");
+ overrideThermalStatus(PowerManager.THERMAL_STATUS_MODERATE);
+ // The bgdexopt task should fail when onStartJob is run
+ runBackgroundDexOpt("Failure");
+ Assert.assertEquals("verify", getCompilerFilter(PACKAGE_NAME));
+ } finally {
+ resetThermalStatus();
+ }
+ }
}
diff --git a/tests/utils/testutils/java/com/android/internal/util/test/FsUtil.java b/tests/utils/testutils/java/com/android/internal/util/test/FsUtil.java
new file mode 100644
index 000000000000..e65661298b7c
--- /dev/null
+++ b/tests/utils/testutils/java/com/android/internal/util/test/FsUtil.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util.test;
+
+import java.io.File;
+
+public class FsUtil {
+
+ /**
+ * Deletes all files under a given directory. Deliberately ignores errors, on the assumption
+ * that test cleanup is only supposed to be best-effort.
+ *
+ * @param dir directory to clear its contents
+ */
+ public static void deleteContents(File dir) {
+ File[] files = dir.listFiles();
+ if (files != null) {
+ for (File file : files) {
+ if (file.isDirectory()) {
+ deleteContents(file);
+ }
+ file.delete();
+ }
+ }
+ }
+}
diff --git a/tests/vcn/OWNERS b/tests/vcn/OWNERS
index 33b9f0f75f81..2441e772468c 100644
--- a/tests/vcn/OWNERS
+++ b/tests/vcn/OWNERS
@@ -3,5 +3,5 @@ set noparent
benedictwong@google.com
ckesting@google.com
evitayan@google.com
+junyin@google.com
nharold@google.com
-jchalard@google.com \ No newline at end of file
diff --git a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
index c59dcf879b1c..4ce78aa4d8c1 100644
--- a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
@@ -92,10 +92,6 @@ public class VcnGatewayConnectionConfigTest {
builder.addExposedCapability(caps);
}
- for (int caps : UNDERLYING_CAPS) {
- builder.addRequiredUnderlyingCapability(caps);
- }
-
return builder.build();
}
@@ -141,9 +137,7 @@ public class VcnGatewayConnectionConfigTest {
@Test
public void testBuilderRequiresNonEmptyExposedCaps() {
try {
- newBuilder()
- .addRequiredUnderlyingCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .build();
+ newBuilder().build();
fail("Expected exception due to invalid exposed capabilities");
} catch (IllegalArgumentException e) {
@@ -187,10 +181,6 @@ public class VcnGatewayConnectionConfigTest {
Arrays.sort(exposedCaps);
assertArrayEquals(EXPOSED_CAPS, exposedCaps);
- int[] underlyingCaps = config.getRequiredUnderlyingCapabilities();
- Arrays.sort(underlyingCaps);
- assertArrayEquals(UNDERLYING_CAPS, underlyingCaps);
-
assertEquals(TUNNEL_CONNECTION_PARAMS, config.getTunnelConnectionParams());
assertArrayEquals(RETRY_INTERVALS_MS, config.getRetryIntervalsMillis());
diff --git a/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java b/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java
index 582275d0547d..abae81cf1742 100644
--- a/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java
@@ -16,15 +16,17 @@
package android.net.vcn;
-import static android.net.NetworkCapabilities.REDACT_ALL;
-import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS;
+import static android.net.NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION;
+import static android.net.NetworkCapabilities.REDACT_NONE;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
+import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
+import android.os.Build;
import android.os.Parcel;
import org.junit.Test;
@@ -39,12 +41,6 @@ public class VcnTransportInfoTest {
private static final VcnTransportInfo WIFI_UNDERLYING_INFO = new VcnTransportInfo(WIFI_INFO);
@Test
- public void testRedactionDefaults() {
- assertEquals(REDACT_ALL, CELL_UNDERLYING_INFO.getRedaction());
- assertEquals(REDACT_ALL, WIFI_UNDERLYING_INFO.getRedaction());
- }
-
- @Test
public void testGetWifiInfo() {
assertEquals(WIFI_INFO, WIFI_UNDERLYING_INFO.getWifiInfo());
@@ -59,15 +55,19 @@ public class VcnTransportInfoTest {
}
@Test
- public void testMakeCopySetsRedactions() {
- assertEquals(
- REDACT_FOR_NETWORK_SETTINGS,
- ((VcnTransportInfo) CELL_UNDERLYING_INFO.makeCopy(REDACT_FOR_NETWORK_SETTINGS))
- .getRedaction());
+ public void testMakeCopyRedactForAccessFineLocation() {
assertEquals(
- REDACT_FOR_NETWORK_SETTINGS,
- ((VcnTransportInfo) WIFI_UNDERLYING_INFO.makeCopy(REDACT_FOR_NETWORK_SETTINGS))
- .getRedaction());
+ SUB_ID,
+ ((VcnTransportInfo) CELL_UNDERLYING_INFO.makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION))
+ .getSubId());
+
+ // TODO: remove the if statement when S pushes to AOSP.
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ assertEquals(
+ WifiConfiguration.INVALID_NETWORK_ID,
+ ((VcnTransportInfo) WIFI_UNDERLYING_INFO.makeCopy(
+ REDACT_FOR_ACCESS_FINE_LOCATION)).getWifiInfo().getNetworkId());
+ }
}
@Test
@@ -78,35 +78,31 @@ public class VcnTransportInfoTest {
}
@Test
- public void testParcelUnparcel() {
- verifyParcelingIsNull(CELL_UNDERLYING_INFO);
- verifyParcelingIsNull(WIFI_UNDERLYING_INFO);
- }
-
- private void verifyParcelingIsNull(VcnTransportInfo vcnTransportInfo) {
- // Verify redacted by default
- Parcel parcel = Parcel.obtain();
- vcnTransportInfo.writeToParcel(parcel, 0 /* flags */);
- parcel.setDataPosition(0);
+ public void testApplicableRedactions() {
+ assertEquals(REDACT_NONE, CELL_UNDERLYING_INFO.getApplicableRedactions());
- assertNull(VcnTransportInfo.CREATOR.createFromParcel(parcel));
+ final long wifiRedactions = WIFI_INFO.getApplicableRedactions();
+ assertEquals(wifiRedactions, WIFI_UNDERLYING_INFO.getApplicableRedactions());
}
@Test
- public void testParcelUnparcelNotRedactedForSysUi() {
- verifyParcelingForSysUi(CELL_UNDERLYING_INFO);
- verifyParcelingForSysUi(WIFI_UNDERLYING_INFO);
+ public void testParcelNotRedactedForSysUi() {
+ VcnTransportInfo cellRedacted = parcelForSysUi(CELL_UNDERLYING_INFO);
+ assertEquals(SUB_ID, cellRedacted.getSubId());
+ VcnTransportInfo wifiRedacted = parcelForSysUi(WIFI_UNDERLYING_INFO);
+ assertEquals(NETWORK_ID, wifiRedacted.getWifiInfo().getNetworkId());
}
- private void verifyParcelingForSysUi(VcnTransportInfo vcnTransportInfo) {
+ private VcnTransportInfo parcelForSysUi(VcnTransportInfo vcnTransportInfo) {
// Allow fully unredacted; SysUI will have all the relevant permissions.
- final VcnTransportInfo unRedacted = (VcnTransportInfo) vcnTransportInfo.makeCopy(0);
+ final VcnTransportInfo unRedacted = (VcnTransportInfo) vcnTransportInfo.makeCopy(
+ REDACT_NONE);
final Parcel parcel = Parcel.obtain();
unRedacted.writeToParcel(parcel, 0 /* flags */);
parcel.setDataPosition(0);
final VcnTransportInfo unparceled = VcnTransportInfo.CREATOR.createFromParcel(parcel);
assertEquals(vcnTransportInfo, unparceled);
- assertEquals(REDACT_ALL, unparceled.getRedaction());
+ return unparceled;
}
}
diff --git a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
index 528f240b9912..ca7463884d3a 100644
--- a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
+++ b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
@@ -88,13 +88,13 @@ public class TelephonySubscriptionTrackerTest {
private static final SubscriptionInfo TEST_SUBINFO_2 = mock(SubscriptionInfo.class);
private static final Map<ParcelUuid, Set<String>> TEST_PRIVILEGED_PACKAGES =
Collections.singletonMap(TEST_PARCEL_UUID, Collections.singleton(PACKAGE_NAME));
- private static final Map<Integer, ParcelUuid> TEST_SUBID_TO_GROUP_MAP;
+ private static final Map<Integer, SubscriptionInfo> TEST_SUBID_TO_INFO_MAP;
static {
- final Map<Integer, ParcelUuid> subIdToGroupMap = new HashMap<>();
- subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_1, TEST_PARCEL_UUID);
- subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_2, TEST_PARCEL_UUID);
- TEST_SUBID_TO_GROUP_MAP = Collections.unmodifiableMap(subIdToGroupMap);
+ final Map<Integer, SubscriptionInfo> subIdToGroupMap = new HashMap<>();
+ subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_1, TEST_SUBINFO_1);
+ subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_2, TEST_SUBINFO_2);
+ TEST_SUBID_TO_INFO_MAP = Collections.unmodifiableMap(subIdToGroupMap);
}
@NonNull private final Context mContext;
@@ -190,13 +190,13 @@ public class TelephonySubscriptionTrackerTest {
private TelephonySubscriptionSnapshot buildExpectedSnapshot(
Map<ParcelUuid, Set<String>> privilegedPackages) {
- return buildExpectedSnapshot(TEST_SUBID_TO_GROUP_MAP, privilegedPackages);
+ return buildExpectedSnapshot(TEST_SUBID_TO_INFO_MAP, privilegedPackages);
}
private TelephonySubscriptionSnapshot buildExpectedSnapshot(
- Map<Integer, ParcelUuid> subIdToGroupMap,
+ Map<Integer, SubscriptionInfo> subIdToInfoMap,
Map<ParcelUuid, Set<String>> privilegedPackages) {
- return new TelephonySubscriptionSnapshot(subIdToGroupMap, privilegedPackages);
+ return new TelephonySubscriptionSnapshot(subIdToInfoMap, privilegedPackages);
}
private void verifyNoActiveSubscriptions() {
@@ -371,7 +371,7 @@ public class TelephonySubscriptionTrackerTest {
@Test
public void testTelephonySubscriptionSnapshotGetGroupForSubId() throws Exception {
final TelephonySubscriptionSnapshot snapshot =
- new TelephonySubscriptionSnapshot(TEST_SUBID_TO_GROUP_MAP, emptyMap());
+ new TelephonySubscriptionSnapshot(TEST_SUBID_TO_INFO_MAP, emptyMap());
assertEquals(TEST_PARCEL_UUID, snapshot.getGroupForSubId(TEST_SUBSCRIPTION_ID_1));
assertEquals(TEST_PARCEL_UUID, snapshot.getGroupForSubId(TEST_SUBSCRIPTION_ID_2));
@@ -380,7 +380,7 @@ public class TelephonySubscriptionTrackerTest {
@Test
public void testTelephonySubscriptionSnapshotGetAllSubIdsInGroup() throws Exception {
final TelephonySubscriptionSnapshot snapshot =
- new TelephonySubscriptionSnapshot(TEST_SUBID_TO_GROUP_MAP, emptyMap());
+ new TelephonySubscriptionSnapshot(TEST_SUBID_TO_INFO_MAP, emptyMap());
assertEquals(
new ArraySet<>(Arrays.asList(TEST_SUBSCRIPTION_ID_1, TEST_SUBSCRIPTION_ID_2)),
diff --git a/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java b/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java
index 0b72cd93e8b0..f91575b670d3 100644
--- a/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java
+++ b/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java
@@ -42,12 +42,14 @@ import android.net.NetworkRequest;
import android.net.TelephonyNetworkSpecifier;
import android.os.ParcelUuid;
import android.os.test.TestLooper;
+import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionInfo;
+import android.telephony.TelephonyManager;
import android.util.ArraySet;
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
import com.android.server.vcn.UnderlyingNetworkTracker.NetworkBringupCallback;
-import com.android.server.vcn.UnderlyingNetworkTracker.RouteSelectionCallback;
+import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkListener;
import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkRecord;
import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkTrackerCallback;
@@ -59,7 +61,6 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.Arrays;
-import java.util.Collections;
import java.util.Set;
import java.util.UUID;
@@ -98,11 +99,13 @@ public class UnderlyingNetworkTrackerTest {
@Mock private Context mContext;
@Mock private VcnNetworkProvider mVcnNetworkProvider;
@Mock private ConnectivityManager mConnectivityManager;
+ @Mock private TelephonyManager mTelephonyManager;
+ @Mock private CarrierConfigManager mCarrierConfigManager;
@Mock private TelephonySubscriptionSnapshot mSubscriptionSnapshot;
@Mock private UnderlyingNetworkTrackerCallback mNetworkTrackerCb;
@Mock private Network mNetwork;
- @Captor private ArgumentCaptor<RouteSelectionCallback> mRouteSelectionCallbackCaptor;
+ @Captor private ArgumentCaptor<UnderlyingNetworkListener> mUnderlyingNetworkListenerCaptor;
private TestLooper mTestLooper;
private VcnContext mVcnContext;
@@ -127,6 +130,13 @@ public class UnderlyingNetworkTrackerTest {
mConnectivityManager,
Context.CONNECTIVITY_SERVICE,
ConnectivityManager.class);
+ setupSystemService(
+ mContext, mTelephonyManager, Context.TELEPHONY_SERVICE, TelephonyManager.class);
+ setupSystemService(
+ mContext,
+ mCarrierConfigManager,
+ Context.CARRIER_CONFIG_SERVICE,
+ CarrierConfigManager.class);
when(mSubscriptionSnapshot.getAllSubIdsInGroup(eq(SUB_GROUP))).thenReturn(INITIAL_SUB_IDS);
@@ -135,7 +145,6 @@ public class UnderlyingNetworkTrackerTest {
mVcnContext,
SUB_GROUP,
mSubscriptionSnapshot,
- Collections.singleton(NetworkCapabilities.NET_CAPABILITY_INTERNET),
mNetworkTrackerCb);
}
@@ -163,26 +172,25 @@ public class UnderlyingNetworkTrackerTest {
@Test
public void testNetworkCallbacksRegisteredOnStartupForTestMode() {
+ final ConnectivityManager cm = mock(ConnectivityManager.class);
+ setupSystemService(mContext, cm, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class);
final VcnContext vcnContext =
- spy(
- new VcnContext(
- mContext,
- mTestLooper.getLooper(),
- mVcnNetworkProvider,
- true /* isInTestMode */));
-
- mUnderlyingNetworkTracker =
- new UnderlyingNetworkTracker(
- vcnContext,
- SUB_GROUP,
- mSubscriptionSnapshot,
- Collections.singleton(NetworkCapabilities.NET_CAPABILITY_INTERNET),
- mNetworkTrackerCb);
-
- verify(mConnectivityManager)
- .requestBackgroundNetwork(
+ new VcnContext(
+ mContext,
+ mTestLooper.getLooper(),
+ mVcnNetworkProvider,
+ true /* isInTestMode */);
+
+ new UnderlyingNetworkTracker(
+ vcnContext,
+ SUB_GROUP,
+ mSubscriptionSnapshot,
+ mNetworkTrackerCb);
+
+ verify(cm)
+ .registerNetworkCallback(
eq(getTestNetworkRequest(INITIAL_SUB_IDS)),
- any(RouteSelectionCallback.class),
+ any(UnderlyingNetworkListener.class),
any());
}
@@ -200,9 +208,19 @@ public class UnderlyingNetworkTrackerTest {
}
verify(mConnectivityManager)
- .requestBackgroundNetwork(
+ .registerNetworkCallback(
eq(getRouteSelectionRequest(expectedSubIds)),
- any(RouteSelectionCallback.class),
+ any(UnderlyingNetworkListener.class),
+ any());
+ verify(mConnectivityManager)
+ .registerNetworkCallback(
+ eq(getWifiEntryRssiThresholdRequest(expectedSubIds)),
+ any(NetworkBringupCallback.class),
+ any());
+ verify(mConnectivityManager)
+ .registerNetworkCallback(
+ eq(getWifiExitRssiThresholdRequest(expectedSubIds)),
+ any(NetworkBringupCallback.class),
any());
}
@@ -218,9 +236,10 @@ public class UnderlyingNetworkTrackerTest {
mUnderlyingNetworkTracker.updateSubscriptionSnapshot(subscriptionUpdate);
// verify that initially-filed bringup requests are unregistered (cell + wifi)
- verify(mConnectivityManager, times(INITIAL_SUB_IDS.size() + 1))
+ verify(mConnectivityManager, times(INITIAL_SUB_IDS.size() + 3))
.unregisterNetworkCallback(any(NetworkBringupCallback.class));
- verify(mConnectivityManager).unregisterNetworkCallback(any(RouteSelectionCallback.class));
+ verify(mConnectivityManager)
+ .unregisterNetworkCallback(any(UnderlyingNetworkListener.class));
verifyNetworkRequestsRegistered(UPDATED_SUB_IDS);
}
@@ -231,6 +250,24 @@ public class UnderlyingNetworkTrackerTest {
.build();
}
+ private NetworkRequest getWifiEntryRssiThresholdRequest(Set<Integer> netCapsSubIds) {
+ // TODO (b/187991063): Add tests for carrier-config based thresholds
+ return getExpectedRequestBase()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .setSubscriptionIds(netCapsSubIds)
+ .setSignalStrength(UnderlyingNetworkTracker.WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT)
+ .build();
+ }
+
+ private NetworkRequest getWifiExitRssiThresholdRequest(Set<Integer> netCapsSubIds) {
+ // TODO (b/187991063): Add tests for carrier-config based thresholds
+ return getExpectedRequestBase()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .setSubscriptionIds(netCapsSubIds)
+ .setSignalStrength(UnderlyingNetworkTracker.WIFI_EXIT_RSSI_THRESHOLD_DEFAULT)
+ .build();
+ }
+
private NetworkRequest getCellRequestForSubId(int subId) {
return getExpectedRequestBase()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
@@ -239,7 +276,11 @@ public class UnderlyingNetworkTrackerTest {
}
private NetworkRequest getRouteSelectionRequest(Set<Integer> netCapsSubIds) {
- return getExpectedRequestBase().setSubscriptionIds(netCapsSubIds).build();
+ return getExpectedRequestBase()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)
+ .setSubscriptionIds(netCapsSubIds)
+ .build();
}
private NetworkRequest getTestNetworkRequest(Set<Integer> netCapsSubIds) {
@@ -265,11 +306,12 @@ public class UnderlyingNetworkTrackerTest {
public void testTeardown() {
mUnderlyingNetworkTracker.teardown();
- // Expect 3 NetworkBringupCallbacks to be unregistered: 1 for WiFi and 2 for Cellular (1x
- // for each subId)
- verify(mConnectivityManager, times(3))
+ // Expect 5 NetworkBringupCallbacks to be unregistered: 1 for WiFi, 2 for Cellular (1x for
+ // each subId), and 1 for each of the Wifi signal strength thresholds
+ verify(mConnectivityManager, times(5))
.unregisterNetworkCallback(any(NetworkBringupCallback.class));
- verify(mConnectivityManager).unregisterNetworkCallback(any(RouteSelectionCallback.class));
+ verify(mConnectivityManager)
+ .unregisterNetworkCallback(any(UnderlyingNetworkListener.class));
}
@Test
@@ -302,19 +344,19 @@ public class UnderlyingNetworkTrackerTest {
verifyRegistrationOnAvailableAndGetCallback();
}
- private RouteSelectionCallback verifyRegistrationOnAvailableAndGetCallback() {
+ private UnderlyingNetworkListener verifyRegistrationOnAvailableAndGetCallback() {
return verifyRegistrationOnAvailableAndGetCallback(INITIAL_NETWORK_CAPABILITIES);
}
- private RouteSelectionCallback verifyRegistrationOnAvailableAndGetCallback(
+ private UnderlyingNetworkListener verifyRegistrationOnAvailableAndGetCallback(
NetworkCapabilities networkCapabilities) {
verify(mConnectivityManager)
- .requestBackgroundNetwork(
+ .registerNetworkCallback(
eq(getRouteSelectionRequest(INITIAL_SUB_IDS)),
- mRouteSelectionCallbackCaptor.capture(),
+ mUnderlyingNetworkListenerCaptor.capture(),
any());
- RouteSelectionCallback cb = mRouteSelectionCallbackCaptor.getValue();
+ UnderlyingNetworkListener cb = mUnderlyingNetworkListenerCaptor.getValue();
cb.onAvailable(mNetwork);
cb.onCapabilitiesChanged(mNetwork, networkCapabilities);
cb.onLinkPropertiesChanged(mNetwork, INITIAL_LINK_PROPERTIES);
@@ -332,7 +374,7 @@ public class UnderlyingNetworkTrackerTest {
@Test
public void testRecordTrackerCallbackNotifiedForNetworkCapabilitiesChange() {
- RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback();
+ UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
cb.onCapabilitiesChanged(mNetwork, UPDATED_NETWORK_CAPABILITIES);
@@ -347,7 +389,7 @@ public class UnderlyingNetworkTrackerTest {
@Test
public void testRecordTrackerCallbackNotifiedForLinkPropertiesChange() {
- RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback();
+ UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
cb.onLinkPropertiesChanged(mNetwork, UPDATED_LINK_PROPERTIES);
@@ -362,7 +404,7 @@ public class UnderlyingNetworkTrackerTest {
@Test
public void testRecordTrackerCallbackNotifiedForNetworkSuspended() {
- RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback();
+ UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
cb.onCapabilitiesChanged(mNetwork, SUSPENDED_NETWORK_CAPABILITIES);
@@ -381,7 +423,7 @@ public class UnderlyingNetworkTrackerTest {
@Test
public void testRecordTrackerCallbackNotifiedForNetworkResumed() {
- RouteSelectionCallback cb =
+ UnderlyingNetworkListener cb =
verifyRegistrationOnAvailableAndGetCallback(SUSPENDED_NETWORK_CAPABILITIES);
cb.onCapabilitiesChanged(mNetwork, INITIAL_NETWORK_CAPABILITIES);
@@ -401,7 +443,7 @@ public class UnderlyingNetworkTrackerTest {
@Test
public void testRecordTrackerCallbackNotifiedForBlocked() {
- RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback();
+ UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
cb.onBlockedStatusChanged(mNetwork, true /* isBlocked */);
@@ -416,7 +458,7 @@ public class UnderlyingNetworkTrackerTest {
@Test
public void testRecordTrackerCallbackNotifiedForNetworkLoss() {
- RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback();
+ UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
cb.onLost(mNetwork);
@@ -425,7 +467,7 @@ public class UnderlyingNetworkTrackerTest {
@Test
public void testRecordTrackerCallbackIgnoresDuplicateRecord() {
- RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback();
+ UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
cb.onCapabilitiesChanged(mNetwork, INITIAL_NETWORK_CAPABILITIES);
@@ -433,4 +475,6 @@ public class UnderlyingNetworkTrackerTest {
// UnderlyingNetworkRecord does not actually change
verifyNoMoreInteractions(mNetworkTrackerCb);
}
+
+ // TODO (b/187991063): Add tests for network prioritization
}
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
index 1ecb4c9ee298..860a919aa9b3 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
@@ -54,6 +54,7 @@ import android.net.vcn.VcnGatewayConnectionConfigTest;
import android.os.ParcelUuid;
import android.os.PowerManager;
import android.os.test.TestLooper;
+import android.telephony.SubscriptionInfo;
import com.android.internal.util.State;
import com.android.internal.util.WakeupMessage;
@@ -73,6 +74,12 @@ import java.util.concurrent.TimeUnit;
public class VcnGatewayConnectionTestBase {
protected static final ParcelUuid TEST_SUB_GRP = new ParcelUuid(UUID.randomUUID());
+ protected static final SubscriptionInfo TEST_SUB_INFO = mock(SubscriptionInfo.class);
+
+ static {
+ doReturn(TEST_SUB_GRP).when(TEST_SUB_INFO).getGroupUuid();
+ }
+
protected static final InetAddress TEST_DNS_ADDR =
InetAddresses.parseNumericAddress("2001:DB8:0:1::");
protected static final InetAddress TEST_DNS_ADDR_2 =
@@ -116,7 +123,7 @@ public class VcnGatewayConnectionTestBase {
protected static final TelephonySubscriptionSnapshot TEST_SUBSCRIPTION_SNAPSHOT =
new TelephonySubscriptionSnapshot(
- Collections.singletonMap(TEST_SUB_ID, TEST_SUB_GRP), Collections.EMPTY_MAP);
+ Collections.singletonMap(TEST_SUB_ID, TEST_SUB_INFO), Collections.EMPTY_MAP);
@NonNull protected final Context mContext;
@NonNull protected final TestLooper mTestLooper;
@@ -166,7 +173,7 @@ public class VcnGatewayConnectionTestBase {
doReturn(mUnderlyingNetworkTracker)
.when(mDeps)
- .newUnderlyingNetworkTracker(any(), any(), any(), any(), any());
+ .newUnderlyingNetworkTracker(any(), any(), any(), any());
doReturn(mWakeLock)
.when(mDeps)
.newWakeLock(eq(mContext), eq(PowerManager.PARTIAL_WAKE_LOCK), any());
diff --git a/tools/aapt/pseudolocalize.cpp b/tools/aapt/pseudolocalize.cpp
index 5c47e0fa8a16..4e8dcb1bc6ee 100644
--- a/tools/aapt/pseudolocalize.cpp
+++ b/tools/aapt/pseudolocalize.cpp
@@ -194,7 +194,8 @@ static String16 pseudo_generate_expansion(const unsigned int length) {
break;
}
}
- result.remove(length + ext, 0);
+ // Just keep the first length + ext characters
+ result = String16(result, length + ext);
}
return result;
}
diff --git a/tools/aapt2/OWNERS b/tools/aapt2/OWNERS
index f1903a5a54a7..69dfcc98340d 100644
--- a/tools/aapt2/OWNERS
+++ b/tools/aapt2/OWNERS
@@ -1,3 +1,4 @@
set noparent
toddke@google.com
-rtmitchell@google.com \ No newline at end of file
+rtmitchell@google.com
+patb@google.com \ No newline at end of file
diff --git a/tools/aosp/aosp_sha.sh b/tools/aosp/aosp_sha.sh
index f25fcdcb7479..514f17a042bc 100755
--- a/tools/aosp/aosp_sha.sh
+++ b/tools/aosp/aosp_sha.sh
@@ -5,7 +5,21 @@ if git branch -vv | grep -q -P "^\*[^\[]+\[aosp/"; then
# Change appears to be in AOSP
exit 0
else
- # Change appears to be non-AOSP; search for files
+ # Change appears to be non-AOSP.
+
+ # If this is a cherry-pick, then allow it.
+ cherrypick=0
+ while read -r line ; do
+ if [[ $line =~ cherry\ picked\ from ]] ; then
+ (( cherrypick++ ))
+ fi
+ done < <(git show $1)
+ if (( cherrypick != 0 )); then
+ # This is a cherry-pick, so allow it.
+ exit 0
+ fi
+
+ # See if any files are affected.
count=0
while read -r file ; do
if (( count == 0 )); then
diff --git a/tools/codegen/src/com/android/codegen/Utils.kt b/tools/codegen/src/com/android/codegen/Utils.kt
index c19ae3b0b11f..a117aa09ab62 100644
--- a/tools/codegen/src/com/android/codegen/Utils.kt
+++ b/tools/codegen/src/com/android/codegen/Utils.kt
@@ -43,8 +43,8 @@ inline infix fun Int.times(action: () -> Unit) {
* cccc dd
*/
fun Iterable<Pair<String, String>>.columnize(separator: String = " | "): String {
- val col1w = map { (a, _) -> a.length }.max()!!
- val col2w = map { (_, b) -> b.length }.max()!!
+ val col1w = map { (a, _) -> a.length }.maxOrNull()!!
+ val col2w = map { (_, b) -> b.length }.maxOrNull()!!
return map { it.first.padEnd(col1w) + separator + it.second.padEnd(col2w) }.joinToString("\n")
}