summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/test-current.txt1
-rw-r--r--core/java/android/net/EthernetManager.java15
-rw-r--r--core/java/android/net/IEthernetManager.aidl1
-rw-r--r--core/java/android/net/NetworkIdentity.java24
-rw-r--r--core/java/android/net/NetworkTemplate.java100
-rw-r--r--core/java/android/net/TestNetworkManager.java12
-rw-r--r--core/java/android/provider/Settings.java2
-rw-r--r--core/tests/coretests/src/android/provider/SettingsBackupTest.java1
-rw-r--r--packages/Tethering/res/values-mcc310-mnc120/strings.xml22
-rw-r--r--packages/Tethering/res/values-mcc311-mnc490/strings.xml22
-rw-r--r--packages/Tethering/res/values-mcc312-mnc530/strings.xml22
-rw-r--r--packages/Tethering/res/values/strings.xml5
-rw-r--r--services/core/java/com/android/server/OWNERS2
-rw-r--r--services/core/java/com/android/server/TestNetworkService.java5
-rw-r--r--services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java3
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java5
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsService.java134
-rw-r--r--services/core/java/com/android/server/pm/StagingManager.java175
-rw-r--r--services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java13
-rw-r--r--services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java82
-rw-r--r--tests/net/java/android/net/NetworkTemplateTest.kt155
-rw-r--r--tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java90
-rw-r--r--tests/net/java/com/android/server/net/NetworkStatsServiceTest.java110
23 files changed, 782 insertions, 219 deletions
diff --git a/api/test-current.txt b/api/test-current.txt
index c9725710daf8..353cf3aea82d 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1442,6 +1442,7 @@ package android.net {
public class EthernetManager {
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public android.net.EthernetManager.TetheredInterfaceRequest requestTetheredInterface(@NonNull java.util.concurrent.Executor, @NonNull android.net.EthernetManager.TetheredInterfaceCallback);
+ method public void setIncludeTestInterfaces(boolean);
}
public static interface EthernetManager.TetheredInterfaceCallback {
diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java
index 83b5f63576f2..d975017f9c8e 100644
--- a/core/java/android/net/EthernetManager.java
+++ b/core/java/android/net/EthernetManager.java
@@ -200,6 +200,21 @@ public class EthernetManager {
}
/**
+ * Whether to treat interfaces created by {@link TestNetworkManager#createTapInterface}
+ * as Ethernet interfaces. The effects of this method apply to any test interfaces that are
+ * already present on the system.
+ * @hide
+ */
+ @TestApi
+ public void setIncludeTestInterfaces(boolean include) {
+ try {
+ mService.setIncludeTestInterfaces(include);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* A request for a tethered interface.
*/
public static class TetheredInterfaceRequest {
diff --git a/core/java/android/net/IEthernetManager.aidl b/core/java/android/net/IEthernetManager.aidl
index ccc6e352098f..e058e5a70c71 100644
--- a/core/java/android/net/IEthernetManager.aidl
+++ b/core/java/android/net/IEthernetManager.aidl
@@ -33,6 +33,7 @@ interface IEthernetManager
boolean isAvailable(String iface);
void addListener(in IEthernetServiceListener listener);
void removeListener(in IEthernetServiceListener listener);
+ void setIncludeTestInterfaces(boolean include);
void requestTetheredInterface(in ITetheredInterfaceCallback callback);
void releaseTetheredInterface(in ITetheredInterfaceCallback callback);
}
diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java
index febc730480e4..4edbcd0ac8b8 100644
--- a/core/java/android/net/NetworkIdentity.java
+++ b/core/java/android/net/NetworkIdentity.java
@@ -25,6 +25,7 @@ import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.service.NetworkIdentityProto;
+import android.telephony.Annotation.NetworkType;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
@@ -39,16 +40,6 @@ import java.util.Objects;
public class NetworkIdentity implements Comparable<NetworkIdentity> {
private static final String TAG = "NetworkIdentity";
- /**
- * When enabled, combine all {@link #mSubType} together under
- * {@link #SUBTYPE_COMBINED}.
- *
- * @deprecated we no longer offer to collect statistics on a per-subtype
- * basis; this is always disabled.
- */
- @Deprecated
- public static final boolean COMBINE_SUBTYPE_ENABLED = true;
-
public static final int SUBTYPE_COMBINED = -1;
final int mType;
@@ -63,7 +54,7 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> {
int type, int subType, String subscriberId, String networkId, boolean roaming,
boolean metered, boolean defaultNetwork) {
mType = type;
- mSubType = COMBINE_SUBTYPE_ENABLED ? SUBTYPE_COMBINED : subType;
+ mSubType = subType;
mSubscriberId = subscriberId;
mNetworkId = networkId;
mRoaming = roaming;
@@ -95,7 +86,7 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> {
final StringBuilder builder = new StringBuilder("{");
builder.append("type=").append(getNetworkTypeName(mType));
builder.append(", subType=");
- if (COMBINE_SUBTYPE_ENABLED) {
+ if (mSubType == SUBTYPE_COMBINED) {
builder.append("COMBINED");
} else {
builder.append(mSubType);
@@ -187,13 +178,14 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> {
}
/**
- * Build a {@link NetworkIdentity} from the given {@link NetworkState},
- * assuming that any mobile networks are using the current IMSI.
+ * Build a {@link NetworkIdentity} from the given {@link NetworkState} and {@code subType},
+ * assuming that any mobile networks are using the current IMSI. The subType if applicable,
+ * should be set as one of the TelephonyManager.NETWORK_TYPE_* constants, or
+ * {@link android.telephony.TelephonyManager#NETWORK_TYPE_UNKNOWN} if not.
*/
public static NetworkIdentity buildNetworkIdentity(Context context, NetworkState state,
- boolean defaultNetwork) {
+ boolean defaultNetwork, @NetworkType int subType) {
final int type = state.networkInfo.getType();
- final int subType = state.networkInfo.getSubtype();
String subscriberId = null;
String networkId = null;
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index 5498f74ba2cc..cb9463a59d34 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -34,9 +34,13 @@ import static android.net.NetworkStats.ROAMING_NO;
import static android.net.NetworkStats.ROAMING_YES;
import static android.net.wifi.WifiInfo.sanitizeSsid;
+import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
+import android.telephony.Annotation.NetworkType;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
import android.util.BackupUtils;
import android.util.Log;
@@ -73,6 +77,14 @@ public class NetworkTemplate implements Parcelable {
public static final int MATCH_BLUETOOTH = 8;
public static final int MATCH_PROXY = 9;
+ /**
+ * Include all network types when filtering. This is meant to merge in with the
+ * {@code TelephonyManager.NETWORK_TYPE_*} constants, and thus needs to stay in sync.
+ *
+ * @hide
+ */
+ public static final int NETWORK_TYPE_ALL = -1;
+
private static boolean isKnownMatchRule(final int rule) {
switch (rule) {
case MATCH_MOBILE:
@@ -117,7 +129,22 @@ public class NetworkTemplate implements Parcelable {
}
/**
- * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks,
+ * Template to match cellular networks with the given IMSI and {@code ratType}.
+ * Use {@link #NETWORK_TYPE_ALL} to include all network types when filtering.
+ * See {@code TelephonyManager.NETWORK_TYPE_*}.
+ */
+ public static NetworkTemplate buildTemplateMobileWithRatType(@Nullable String subscriberId,
+ @NetworkType int ratType) {
+ if (TextUtils.isEmpty(subscriberId)) {
+ return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null, null,
+ METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType);
+ }
+ return new NetworkTemplate(MATCH_MOBILE, subscriberId, new String[]{subscriberId}, null,
+ METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType);
+ }
+
+ /**
+ * Template to match metered {@link ConnectivityManager#TYPE_MOBILE} networks,
* regardless of IMSI.
*/
@UnsupportedAppUsage
@@ -126,7 +153,7 @@ public class NetworkTemplate implements Parcelable {
}
/**
- * Template to match all {@link ConnectivityManager#TYPE_WIFI} networks,
+ * Template to match all metered {@link ConnectivityManager#TYPE_WIFI} networks,
* regardless of SSID.
*/
@UnsupportedAppUsage
@@ -192,6 +219,7 @@ public class NetworkTemplate implements Parcelable {
private final int mMetered;
private final int mRoaming;
private final int mDefaultNetwork;
+ private final int mSubType;
@UnsupportedAppUsage
public NetworkTemplate(int matchRule, String subscriberId, String networkId) {
@@ -201,11 +229,11 @@ public class NetworkTemplate implements Parcelable {
public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
String networkId) {
this(matchRule, subscriberId, matchSubscriberIds, networkId, METERED_ALL, ROAMING_ALL,
- DEFAULT_NETWORK_ALL);
+ DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL);
}
public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
- String networkId, int metered, int roaming, int defaultNetwork) {
+ String networkId, int metered, int roaming, int defaultNetwork, int subType) {
mMatchRule = matchRule;
mSubscriberId = subscriberId;
mMatchSubscriberIds = matchSubscriberIds;
@@ -213,6 +241,7 @@ public class NetworkTemplate implements Parcelable {
mMetered = metered;
mRoaming = roaming;
mDefaultNetwork = defaultNetwork;
+ mSubType = subType;
if (!isKnownMatchRule(matchRule)) {
Log.e(TAG, "Unknown network template rule " + matchRule
@@ -228,6 +257,7 @@ public class NetworkTemplate implements Parcelable {
mMetered = in.readInt();
mRoaming = in.readInt();
mDefaultNetwork = in.readInt();
+ mSubType = in.readInt();
}
@Override
@@ -239,6 +269,7 @@ public class NetworkTemplate implements Parcelable {
dest.writeInt(mMetered);
dest.writeInt(mRoaming);
dest.writeInt(mDefaultNetwork);
+ dest.writeInt(mSubType);
}
@Override
@@ -271,13 +302,16 @@ public class NetworkTemplate implements Parcelable {
builder.append(", defaultNetwork=").append(NetworkStats.defaultNetworkToString(
mDefaultNetwork));
}
+ if (mSubType != NETWORK_TYPE_ALL) {
+ builder.append(", subType=").append(mSubType);
+ }
return builder.toString();
}
@Override
public int hashCode() {
return Objects.hash(mMatchRule, mSubscriberId, mNetworkId, mMetered, mRoaming,
- mDefaultNetwork);
+ mDefaultNetwork, mSubType);
}
@Override
@@ -289,7 +323,8 @@ public class NetworkTemplate implements Parcelable {
&& Objects.equals(mNetworkId, other.mNetworkId)
&& mMetered == other.mMetered
&& mRoaming == other.mRoaming
- && mDefaultNetwork == other.mDefaultNetwork;
+ && mDefaultNetwork == other.mDefaultNetwork
+ && mSubType == other.mSubType;
}
return false;
}
@@ -376,6 +411,11 @@ public class NetworkTemplate implements Parcelable {
|| (mDefaultNetwork == DEFAULT_NETWORK_NO && !ident.mDefaultNetwork);
}
+ private boolean matchesCollapsedRatType(NetworkIdentity ident) {
+ return mSubType == NETWORK_TYPE_ALL
+ || getCollapsedRatType(mSubType) == getCollapsedRatType(ident.mSubType);
+ }
+
public boolean matchesSubscriberId(String subscriberId) {
return ArrayUtils.contains(mMatchSubscriberIds, subscriberId);
}
@@ -388,9 +428,52 @@ public class NetworkTemplate implements Parcelable {
// TODO: consider matching against WiMAX subscriber identity
return true;
} else {
+ // Only metered mobile network would be matched regardless of metered filter.
+ // This is used to exclude non-metered APNs, e.g. IMS. See ag/908650.
+ // TODO: Respect metered filter and remove mMetered condition.
return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered))
&& !ArrayUtils.isEmpty(mMatchSubscriberIds)
- && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId);
+ && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId)
+ && matchesCollapsedRatType(ident);
+ }
+ }
+
+ /**
+ * Get a Radio Access Technology(RAT) type that is representative of a group of RAT types.
+ * The mapping is corresponding to {@code TelephonyManager#NETWORK_CLASS_BIT_MASK_*}.
+ *
+ * @param ratType An integer defined in {@code TelephonyManager#NETWORK_TYPE_*}.
+ */
+ // TODO: 1. Consider move this to TelephonyManager if used by other modules.
+ // 2. Consider make this configurable.
+ // 3. Use TelephonyManager APIs when available.
+ public static int getCollapsedRatType(int ratType) {
+ switch (ratType) {
+ case TelephonyManager.NETWORK_TYPE_GPRS:
+ case TelephonyManager.NETWORK_TYPE_GSM:
+ case TelephonyManager.NETWORK_TYPE_EDGE:
+ case TelephonyManager.NETWORK_TYPE_IDEN:
+ case TelephonyManager.NETWORK_TYPE_CDMA:
+ case TelephonyManager.NETWORK_TYPE_1xRTT:
+ return TelephonyManager.NETWORK_TYPE_GSM;
+ case TelephonyManager.NETWORK_TYPE_EVDO_0:
+ case TelephonyManager.NETWORK_TYPE_EVDO_A:
+ case TelephonyManager.NETWORK_TYPE_EVDO_B:
+ case TelephonyManager.NETWORK_TYPE_EHRPD:
+ case TelephonyManager.NETWORK_TYPE_UMTS:
+ case TelephonyManager.NETWORK_TYPE_HSDPA:
+ case TelephonyManager.NETWORK_TYPE_HSUPA:
+ case TelephonyManager.NETWORK_TYPE_HSPA:
+ case TelephonyManager.NETWORK_TYPE_HSPAP:
+ case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
+ return TelephonyManager.NETWORK_TYPE_UMTS;
+ case TelephonyManager.NETWORK_TYPE_LTE:
+ case TelephonyManager.NETWORK_TYPE_IWLAN:
+ return TelephonyManager.NETWORK_TYPE_LTE;
+ case TelephonyManager.NETWORK_TYPE_NR:
+ return TelephonyManager.NETWORK_TYPE_NR;
+ default:
+ return TelephonyManager.NETWORK_TYPE_UNKNOWN;
}
}
@@ -421,7 +504,8 @@ public class NetworkTemplate implements Parcelable {
if (ident.mType == TYPE_WIMAX) {
return true;
} else {
- return sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered);
+ return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered))
+ && matchesCollapsedRatType(ident);
}
}
diff --git a/core/java/android/net/TestNetworkManager.java b/core/java/android/net/TestNetworkManager.java
index c3284df39713..a0a563b37025 100644
--- a/core/java/android/net/TestNetworkManager.java
+++ b/core/java/android/net/TestNetworkManager.java
@@ -30,6 +30,18 @@ import com.android.internal.util.Preconditions;
*/
@TestApi
public class TestNetworkManager {
+ /**
+ * Prefix for tun interfaces created by this class.
+ * @hide
+ */
+ public static final String TEST_TUN_PREFIX = "testtun";
+
+ /**
+ * Prefix for tap interfaces created by this class.
+ * @hide
+ */
+ public static final String TEST_TAP_PREFIX = "testtap";
+
@NonNull private static final String TAG = TestNetworkManager.class.getSimpleName();
@NonNull private final ITestNetworkManager mService;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index d6869c549dcf..1701a349da0f 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10197,6 +10197,8 @@ public final class Settings {
public static final String NETSTATS_SAMPLE_ENABLED = "netstats_sample_enabled";
/** {@hide} */
public static final String NETSTATS_AUGMENT_ENABLED = "netstats_augment_enabled";
+ /** {@hide} */
+ public static final String NETSTATS_COMBINE_SUBTYPE_ENABLED = "netstats_combine_subtype_enabled";
/** {@hide} */
public static final String NETSTATS_DEV_BUCKET_DURATION = "netstats_dev_bucket_duration";
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 7d752cdcd2d8..802b106a107c 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -346,6 +346,7 @@ public class SettingsBackupTest {
Settings.Global.NETSTATS_POLL_INTERVAL,
Settings.Global.NETSTATS_SAMPLE_ENABLED,
Settings.Global.NETSTATS_AUGMENT_ENABLED,
+ Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED,
Settings.Global.NETSTATS_TIME_CACHE_MAX_AGE,
Settings.Global.NETSTATS_UID_BUCKET_DURATION,
Settings.Global.NETSTATS_UID_DELETE_AGE,
diff --git a/packages/Tethering/res/values-mcc310-mnc120/strings.xml b/packages/Tethering/res/values-mcc310-mnc120/strings.xml
new file mode 100644
index 000000000000..618df90c7105
--- /dev/null
+++ b/packages/Tethering/res/values-mcc310-mnc120/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- String for tethered notification title with client number info. -->
+ <plurals name="tethered_notification_title_with_client_number">
+ <item quantity="one"><xliff:g>%1$d</xliff:g> device connected.</item>
+ <item quantity="other"><xliff:g>%1$d</xliff:g> devices connected.</item>
+ </plurals>
+</resources> \ No newline at end of file
diff --git a/packages/Tethering/res/values-mcc311-mnc490/strings.xml b/packages/Tethering/res/values-mcc311-mnc490/strings.xml
new file mode 100644
index 000000000000..618df90c7105
--- /dev/null
+++ b/packages/Tethering/res/values-mcc311-mnc490/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- String for tethered notification title with client number info. -->
+ <plurals name="tethered_notification_title_with_client_number">
+ <item quantity="one"><xliff:g>%1$d</xliff:g> device connected.</item>
+ <item quantity="other"><xliff:g>%1$d</xliff:g> devices connected.</item>
+ </plurals>
+</resources> \ No newline at end of file
diff --git a/packages/Tethering/res/values-mcc312-mnc530/strings.xml b/packages/Tethering/res/values-mcc312-mnc530/strings.xml
new file mode 100644
index 000000000000..618df90c7105
--- /dev/null
+++ b/packages/Tethering/res/values-mcc312-mnc530/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- String for tethered notification title with client number info. -->
+ <plurals name="tethered_notification_title_with_client_number">
+ <item quantity="one"><xliff:g>%1$d</xliff:g> device connected.</item>
+ <item quantity="other"><xliff:g>%1$d</xliff:g> devices connected.</item>
+ </plurals>
+</resources> \ No newline at end of file
diff --git a/packages/Tethering/res/values/strings.xml b/packages/Tethering/res/values/strings.xml
index d50884b2a7b0..981524e4daea 100644
--- a/packages/Tethering/res/values/strings.xml
+++ b/packages/Tethering/res/values/strings.xml
@@ -13,12 +13,15 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<resources>
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Shown when the device is tethered -->
<!-- String for tethered notification title [CHAR LIMIT=200] -->
<string name="tethered_notification_title">Tethering or hotspot active</string>
<!-- String for tethered notification message [CHAR LIMIT=200] -->
<string name="tethered_notification_message">Tap to set up.</string>
+ <!-- String for tethered notification title with client number info. -->
+ <plurals name="tethered_notification_title_with_client_number">
+ </plurals>
<!-- This notification is shown when tethering has been disabled on a user's device.
The device is managed by the user's employer. Tethering can't be turned on unless the
diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS
index 76e0c137d2f5..8099f8f37bc7 100644
--- a/services/core/java/com/android/server/OWNERS
+++ b/services/core/java/com/android/server/OWNERS
@@ -1,5 +1,5 @@
# Connectivity / Networking
-per-file ConnectivityService.java,NetworkManagementService.java,NsdService.java = codewiz@google.com, ek@google.com, jchalard@google.com, lorenzo@google.com, reminv@google.com, satk@google.com
+per-file ConnectivityService.java,NetworkManagementService.java,NsdService.java = codewiz@google.com, ek@google.com, jchalard@google.com, junyulai@google.com, lorenzo@google.com, reminv@google.com, satk@google.com
# Vibrator / Threads
per-file VibratorService.java, DisplayThread.java = michaelwr@google.com
diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java
index f772a4a5a300..5045361ee0c5 100644
--- a/services/core/java/com/android/server/TestNetworkService.java
+++ b/services/core/java/com/android/server/TestNetworkService.java
@@ -16,6 +16,9 @@
package com.android.server;
+import static android.net.TestNetworkManager.TEST_TAP_PREFIX;
+import static android.net.TestNetworkManager.TEST_TUN_PREFIX;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -61,8 +64,6 @@ import java.util.concurrent.atomic.AtomicInteger;
class TestNetworkService extends ITestNetworkManager.Stub {
@NonNull private static final String TAG = TestNetworkService.class.getSimpleName();
@NonNull private static final String TEST_NETWORK_TYPE = "TEST_NETWORK";
- @NonNull private static final String TEST_TUN_PREFIX = "testtun";
- @NonNull private static final String TEST_TAP_PREFIX = "testtap";
@NonNull private static final AtomicInteger sTestTunIndex = new AtomicInteger();
@NonNull private final Context mContext;
diff --git a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
index 04c792ae482b..d5488712aa34 100644
--- a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
+++ b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
@@ -25,6 +25,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicy.WARNING_DISABLED;
+import static android.net.NetworkTemplate.NETWORK_TYPE_ALL;
import static android.provider.Settings.Global.NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -220,7 +221,7 @@ public class MultipathPolicyTracker {
mNetworkTemplate = new NetworkTemplate(
NetworkTemplate.MATCH_MOBILE, subscriberId, new String[] { subscriberId },
null, NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL,
- NetworkStats.DEFAULT_NETWORK_NO);
+ NetworkStats.DEFAULT_NETWORK_NO, NETWORK_TYPE_ALL);
mUsageCallback = new UsageCallback() {
@Override
public void onThresholdReached(int networkType, String subscriberId) {
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index a2a4e91aa9fe..0392807bcb37 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -1869,8 +1869,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mNetIdToSubId.put(state.network.netId, parseSubId(state));
}
if (state.networkInfo != null && state.networkInfo.isConnected()) {
+ // Policies matched by NPMS only match by subscriber ID or by ssid. Thus subtype
+ // in the object created here is never used and its value doesn't matter, so use
+ // NETWORK_TYPE_UNKNOWN.
final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state,
- true);
+ true, TelephonyManager.NETWORK_TYPE_UNKNOWN /* subType */);
identified.put(state, ident);
}
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 88fc0a6b11f7..26808587437c 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -27,6 +27,7 @@ import static android.content.Intent.EXTRA_UID;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
import static android.net.ConnectivityManager.isNetworkTypeMobile;
+import static android.net.NetworkIdentity.SUBTYPE_COMBINED;
import static android.net.NetworkStack.checkNetworkStackPermission;
import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
import static android.net.NetworkStats.IFACE_ALL;
@@ -45,10 +46,12 @@ import static android.net.NetworkStats.UID_ALL;
import static android.net.NetworkStatsHistory.FIELD_ALL;
import static android.net.NetworkTemplate.buildTemplateMobileWildcard;
import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
+import static android.net.NetworkTemplate.getCollapsedRatType;
import static android.net.TrafficStats.KB_IN_BYTES;
import static android.net.TrafficStats.MB_IN_BYTES;
import static android.os.Trace.TRACE_TAG_NETWORK;
import static android.provider.Settings.Global.NETSTATS_AUGMENT_ENABLED;
+import static android.provider.Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED;
import static android.provider.Settings.Global.NETSTATS_DEV_BUCKET_DURATION;
import static android.provider.Settings.Global.NETSTATS_DEV_DELETE_AGE;
import static android.provider.Settings.Global.NETSTATS_DEV_PERSIST_BYTES;
@@ -64,6 +67,9 @@ import static android.provider.Settings.Global.NETSTATS_UID_TAG_BUCKET_DURATION;
import static android.provider.Settings.Global.NETSTATS_UID_TAG_DELETE_AGE;
import static android.provider.Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES;
import static android.provider.Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE;
+import static android.telephony.PhoneStateListener.LISTEN_NONE;
+import static android.telephony.PhoneStateListener.LISTEN_SERVICE_STATE;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
@@ -109,6 +115,7 @@ import android.os.Binder;
import android.os.DropBoxManager;
import android.os.Environment;
import android.os.Handler;
+import android.os.HandlerExecutor;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.INetworkManagementService;
@@ -125,6 +132,8 @@ import android.provider.Settings;
import android.provider.Settings.Global;
import android.service.NetworkInterfaceProto;
import android.service.NetworkStatsServiceDumpProto;
+import android.telephony.PhoneStateListener;
+import android.telephony.ServiceState;
import android.telephony.SubscriptionPlan;
import android.telephony.TelephonyManager;
import android.text.format.DateUtils;
@@ -157,6 +166,7 @@ import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
+import java.util.concurrent.Executor;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
@@ -173,6 +183,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;
/** Flags to control detail level of poll event. */
private static final int FLAG_PERSIST_NETWORK = 0x1;
@@ -229,12 +240,20 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
* Settings that can be changed externally.
*/
public interface NetworkStatsSettings {
- public long getPollInterval();
- public long getPollDelay();
- public boolean getSampleEnabled();
- public boolean getAugmentEnabled();
+ long getPollInterval();
+ long getPollDelay();
+ boolean getSampleEnabled();
+ boolean getAugmentEnabled();
+ /**
+ * When enabled, all mobile data is reported under {@link NetworkIdentity#SUBTYPE_COMBINED}.
+ * When disabled, mobile data is broken down by a granular subtype representative of the
+ * actual subtype. {@see NetworkTemplate#getCollapsedRatType}.
+ * Enabling this decreases the level of detail but saves performance, disk space and
+ * amount of data logged.
+ */
+ boolean getCombineSubtypeEnabled();
- public static class Config {
+ class Config {
public final long bucketDuration;
public final long rotateAgeMillis;
public final long deleteAgeMillis;
@@ -246,16 +265,16 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
}
- public Config getDevConfig();
- public Config getXtConfig();
- public Config getUidConfig();
- public Config getUidTagConfig();
+ Config getDevConfig();
+ Config getXtConfig();
+ Config getUidConfig();
+ Config getUidTagConfig();
- public long getGlobalAlertBytes(long def);
- public long getDevPersistBytes(long def);
- public long getXtPersistBytes(long def);
- public long getUidPersistBytes(long def);
- public long getUidTagPersistBytes(long def);
+ long getGlobalAlertBytes(long def);
+ long getDevPersistBytes(long def);
+ long getXtPersistBytes(long def);
+ long getUidPersistBytes(long def);
+ long getUidTagPersistBytes(long def);
}
private final Object mStatsLock = new Object();
@@ -280,6 +299,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
@GuardedBy("mStatsLock")
private Network[] mDefaultNetworks = new Network[0];
+ /** Last states of all networks sent from ConnectivityService. */
+ @GuardedBy("mStatsLock")
+ @Nullable
+ private NetworkState[] mLastNetworkStates = null;
+
private final DropBoxNonMonotonicObserver mNonMonotonicObserver =
new DropBoxNonMonotonicObserver();
@@ -355,6 +379,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
performPoll(FLAG_PERSIST_ALL);
break;
}
+ case MSG_UPDATE_IFACES: {
+ // If no cached states, ignore.
+ if (mLastNetworkStates == null) break;
+ updateIfaces(mDefaultNetworks, mLastNetworkStates, mActiveIface);
+ break;
+ }
case MSG_PERFORM_POLL_REGISTER_ALERT: {
performPoll(FLAG_PERSIST_NETWORK);
registerGlobalAlert();
@@ -407,6 +437,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
final HandlerThread handlerThread = mDeps.makeHandlerThread();
handlerThread.start();
mHandler = new NetworkStatsHandler(handlerThread.getLooper());
+ mPhoneListener = new NetworkTypeListener(new HandlerExecutor(mHandler));
}
/**
@@ -486,6 +517,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime,
mSettings.getPollInterval(), pollIntent);
+ // TODO: 1. listen to changes from all subscriptions.
+ // 2. listen to settings changed to support dynamically enable/disable.
+ // watch for networkType changes
+ if (!mSettings.getCombineSubtypeEnabled()) {
+ mTeleManager.listen(mPhoneListener, LISTEN_SERVICE_STATE);
+ }
+
registerGlobalAlert();
}
@@ -506,6 +544,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
mContext.unregisterReceiver(mUserReceiver);
mContext.unregisterReceiver(mShutdownReceiver);
+ mTeleManager.listen(mPhoneListener, LISTEN_NONE);
+
final long currentTime = mClock.millis();
// persist any pending stats
@@ -1156,6 +1196,38 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
};
+ /**
+ * Receiver that watches for {@link TelephonyManager} changes, such as
+ * transitioning between Radio Access Technology(RAT) types.
+ */
+ @NonNull
+ private final NetworkTypeListener mPhoneListener;
+
+ class NetworkTypeListener extends PhoneStateListener {
+ private volatile int mLastCollapsedRatType = NETWORK_TYPE_UNKNOWN;
+
+ NetworkTypeListener(@NonNull Executor executor) {
+ super(executor);
+ }
+
+ @Override
+ public void onServiceStateChanged(@NonNull ServiceState ss) {
+ final int networkType = ss.getDataNetworkType();
+ final int collapsedRatType = getCollapsedRatType(networkType);
+ if (collapsedRatType == mLastCollapsedRatType) return;
+
+ if (LOGD) {
+ Log.d(TAG, "subtype changed for mobile: "
+ + mLastCollapsedRatType + " -> " + collapsedRatType);
+ }
+ // Protect service from frequently updating. Remove pending messages if any.
+ mHandler.removeMessages(MSG_UPDATE_IFACES);
+ mLastCollapsedRatType = collapsedRatType;
+ mHandler.sendMessageDelayed(
+ mHandler.obtainMessage(MSG_UPDATE_IFACES), mSettings.getPollDelay());
+ }
+ }
+
private void updateIfaces(
Network[] defaultNetworks,
NetworkState[] networkStates,
@@ -1177,7 +1249,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
* they are combined under a single {@link NetworkIdentitySet}.
*/
@GuardedBy("mStatsLock")
- private void updateIfacesLocked(Network[] defaultNetworks, NetworkState[] states) {
+ private void updateIfacesLocked(@Nullable Network[] defaultNetworks,
+ @NonNull NetworkState[] states) {
if (!mSystemReady) return;
if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
@@ -1197,13 +1270,18 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
mDefaultNetworks = defaultNetworks;
}
+ mLastNetworkStates = states;
+
+ final boolean combineSubtypeEnabled = mSettings.getCombineSubtypeEnabled();
final ArraySet<String> mobileIfaces = new ArraySet<>();
for (NetworkState state : states) {
if (state.networkInfo.isConnected()) {
final boolean isMobile = isNetworkTypeMobile(state.networkInfo.getType());
final boolean isDefault = ArrayUtils.contains(mDefaultNetworks, state.network);
+ final int subType = combineSubtypeEnabled ? SUBTYPE_COMBINED
+ : getSubTypeForState(state);
final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state,
- isDefault);
+ isDefault, subType);
// Traffic occurring on the base interface is always counted for
// both total usage and UID details.
@@ -1264,6 +1342,20 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
mMobileIfaces = mobileIfaces.toArray(new String[mobileIfaces.size()]);
}
+ /**
+ * For networks with {@code TRANSPORT_CELLULAR}, get subType that was obtained through
+ * {@link PhoneStateListener}. Otherwise, return 0 given that other networks with different
+ * transport types do not actually fill this value.
+ */
+ private int getSubTypeForState(@NonNull NetworkState state) {
+ if (!state.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
+ return 0;
+ }
+
+ // TODO: return different subType for different subscriptions.
+ return mPhoneListener.mLastCollapsedRatType;
+ }
+
private static <K> NetworkIdentitySet findOrCreateNetworkIdentitySet(
ArrayMap<K, NetworkIdentitySet> map, K key) {
NetworkIdentitySet ident = map.get(key);
@@ -1617,6 +1709,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
return;
}
+ pw.println("Configs:");
+ pw.increaseIndent();
+ pw.printPair(NETSTATS_COMBINE_SUBTYPE_ENABLED, mSettings.getCombineSubtypeEnabled());
+ pw.println();
+ pw.decreaseIndent();
+
pw.println("Active interfaces:");
pw.increaseIndent();
for (int i = 0; i < mActiveIfaces.size(); i++) {
@@ -2045,6 +2143,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
return getGlobalBoolean(NETSTATS_AUGMENT_ENABLED, true);
}
@Override
+ public boolean getCombineSubtypeEnabled() {
+ return getGlobalBoolean(NETSTATS_COMBINE_SUBTYPE_ENABLED, false);
+ }
+ @Override
public Config getDevConfig() {
return new Config(getGlobalLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS),
getGlobalLong(NETSTATS_DEV_ROTATE_AGE, 15 * DAY_IN_MILLIS),
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 1a55521cfa8b..15e2fd579cc4 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -114,18 +114,17 @@ public class StagingManager {
* Validates the signature used to sign the container of the new apex package
*
* @param newApexPkg The new apex package that is being installed
- * @param installFlags flags related to the session
* @throws PackageManagerException
*/
- private void validateApexSignature(PackageInfo newApexPkg, int installFlags)
+ private void validateApexSignature(PackageInfo newApexPkg)
throws PackageManagerException {
// Get signing details of the new package
final String apexPath = newApexPkg.applicationInfo.sourceDir;
final String packageName = newApexPkg.packageName;
- final SigningDetails signingDetails;
+ final SigningDetails newSigningDetails;
try {
- signingDetails = ApkSignatureVerifier.verify(apexPath, SignatureSchemeVersion.JAR);
+ newSigningDetails = ApkSignatureVerifier.verify(apexPath, SignatureSchemeVersion.JAR);
} catch (PackageParserException e) {
throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
"Failed to parse APEX package " + apexPath, e);
@@ -150,16 +149,10 @@ public class StagingManager {
}
// Verify signing details for upgrade
- if (signingDetails.checkCapability(existingSigningDetails,
- PackageParser.SigningDetails.CertCapabilities.INSTALLED_DATA)) {
- return;
- }
-
- // Verify signing details for downgrade
- // Allow downgrading from B to A iff it is possible to upgrade from A to B
- if (existingApexPkg.getLongVersionCode() > newApexPkg.getLongVersionCode()
- && existingSigningDetails.checkCapability(signingDetails,
- PackageParser.SigningDetails.CertCapabilities.INSTALLED_DATA)) {
+ if (newSigningDetails.checkCapability(existingSigningDetails,
+ SigningDetails.CertCapabilities.INSTALLED_DATA)
+ || existingSigningDetails.checkCapability(newSigningDetails,
+ SigningDetails.CertCapabilities.ROLLBACK)) {
return;
}
@@ -319,7 +312,7 @@ public class StagingManager {
// The APEX part of the session is activated, proceed with the installation of APKs.
try {
Slog.d(TAG, "Installing APK packages in session " + session.sessionId);
- installApksInSession(session, /* preReboot */ false);
+ installApksInSession(session);
} catch (PackageManagerException e) {
session.setStagedSessionFailed(e.error, e.getMessage());
@@ -410,72 +403,23 @@ public class StagingManager {
}
}
- private void commitApkSession(@NonNull PackageInstallerSession apkSession,
- PackageInstallerSession originalSession, boolean preReboot)
- throws PackageManagerException {
- final int errorCode = preReboot ? SessionInfo.STAGED_SESSION_VERIFICATION_FAILED
- : SessionInfo.STAGED_SESSION_ACTIVATION_FAILED;
- if (preReboot) {
- final LocalIntentReceiverAsync receiver = new LocalIntentReceiverAsync(
- (Intent result) -> {
- int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
- PackageInstaller.STATUS_FAILURE);
- if (status != PackageInstaller.STATUS_SUCCESS) {
- final String errorMessage = result.getStringExtra(
- PackageInstaller.EXTRA_STATUS_MESSAGE);
- Slog.e(TAG, "Failure to install APK staged session "
- + originalSession.sessionId + " [" + errorMessage + "]");
- originalSession.setStagedSessionFailed(errorCode, errorMessage);
- return;
- }
- mPreRebootVerificationHandler.notifyPreRebootVerification_Apk_Complete(
- originalSession.sessionId);
- });
- apkSession.commit(receiver.getIntentSender(), false);
- return;
- }
-
- if ((apkSession.params.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) {
- // If rollback is available for this session, notify the rollback
- // manager of the apk session so it can properly enable rollback.
- final IRollbackManager rm = IRollbackManager.Stub.asInterface(
- ServiceManager.getService(Context.ROLLBACK_SERVICE));
- try {
- rm.notifyStagedApkSession(originalSession.sessionId, apkSession.sessionId);
- } catch (RemoteException re) {
- Slog.e(TAG, "Failed to notifyStagedApkSession for session: "
- + originalSession.sessionId, re);
- }
- }
-
- final LocalIntentReceiverSync receiver = new LocalIntentReceiverSync();
- apkSession.commit(receiver.getIntentSender(), false);
- final Intent result = receiver.getResult();
- final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
- PackageInstaller.STATUS_FAILURE);
- if (status != PackageInstaller.STATUS_SUCCESS) {
- final String errorMessage = result.getStringExtra(
- PackageInstaller.EXTRA_STATUS_MESSAGE);
- Slog.e(TAG, "Failure to install APK staged session "
- + originalSession.sessionId + " [" + errorMessage + "]");
- throw new PackageManagerException(errorCode, errorMessage);
- }
- }
-
- private void installApksInSession(@NonNull PackageInstallerSession session,
- boolean preReboot) throws PackageManagerException {
+ /**
+ * Extract apks in the given session into a new session. Returns {@code null} if there is no
+ * apks in the given session. Only parent session is returned for multi-package session.
+ */
+ @Nullable
+ private PackageInstallerSession extractApksInSession(PackageInstallerSession session,
+ boolean preReboot) throws PackageManagerException {
final int errorCode = preReboot ? SessionInfo.STAGED_SESSION_VERIFICATION_FAILED
: SessionInfo.STAGED_SESSION_ACTIVATION_FAILED;
if (!session.isMultiPackage() && !isApexSession(session)) {
- // APK single-packaged staged session. Do a regular install.
- PackageInstallerSession apkSession = createAndWriteApkSession(session, preReboot);
- commitApkSession(apkSession, session, preReboot);
+ return createAndWriteApkSession(session, preReboot);
} else if (session.isMultiPackage()) {
// For multi-package staged sessions containing APKs, we identify which child sessions
// contain an APK, and with those then create a new multi-package group of sessions,
// carrying over all the session parameters and unmarking them as staged. On commit the
// sessions will be installed atomically.
- List<PackageInstallerSession> childSessions;
+ final List<PackageInstallerSession> childSessions;
synchronized (mStagedSessions) {
childSessions =
Arrays.stream(session.getChildSessionIds())
@@ -487,18 +431,18 @@ public class StagingManager {
}
if (childSessions.isEmpty()) {
// APEX-only multi-package staged session, nothing to do.
- return;
+ return null;
}
- PackageInstaller.SessionParams params = session.params.copy();
+ final PackageInstaller.SessionParams params = session.params.copy();
params.isStaged = false;
if (preReboot) {
params.installFlags &= ~PackageManager.INSTALL_ENABLE_ROLLBACK;
}
// TODO(b/129744602): use the userid from the original session.
- int apkParentSessionId = mPi.createSession(
+ final int apkParentSessionId = mPi.createSession(
params, session.getInstallerPackageName(),
0 /* UserHandle.SYSTEM */);
- PackageInstallerSession apkParentSession = mPi.getSession(apkParentSessionId);
+ final PackageInstallerSession apkParentSession = mPi.getSession(apkParentSessionId);
try {
apkParentSession.open();
} catch (IOException e) {
@@ -519,9 +463,75 @@ public class StagingManager {
"Failed to add a child session " + apkChildSession.sessionId);
}
}
- commitApkSession(apkParentSession, session, preReboot);
+ return apkParentSession;
+ }
+ return null;
+ }
+
+ private void verifyApksInSession(PackageInstallerSession session)
+ throws PackageManagerException {
+
+ final PackageInstallerSession apksToVerify = extractApksInSession(
+ session, /* preReboot */ true);
+ if (apksToVerify == null) {
+ return;
+ }
+
+ final LocalIntentReceiverAsync receiver = new LocalIntentReceiverAsync(
+ (Intent result) -> {
+ int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
+ PackageInstaller.STATUS_FAILURE);
+ if (status != PackageInstaller.STATUS_SUCCESS) {
+ final String errorMessage = result.getStringExtra(
+ PackageInstaller.EXTRA_STATUS_MESSAGE);
+ Slog.e(TAG, "Failure to verify APK staged session "
+ + session.sessionId + " [" + errorMessage + "]");
+ session.setStagedSessionFailed(
+ SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, errorMessage);
+ return;
+ }
+ mPreRebootVerificationHandler.notifyPreRebootVerification_Apk_Complete(
+ session.sessionId);
+ });
+
+ apksToVerify.commit(receiver.getIntentSender(), false);
+ }
+
+ private void installApksInSession(@NonNull PackageInstallerSession session)
+ throws PackageManagerException {
+
+ final PackageInstallerSession apksToInstall = extractApksInSession(
+ session, /* preReboot */ false);
+ if (apksToInstall == null) {
+ return;
+ }
+
+ if ((apksToInstall.params.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) {
+ // If rollback is available for this session, notify the rollback
+ // manager of the apk session so it can properly enable rollback.
+ final IRollbackManager rm = IRollbackManager.Stub.asInterface(
+ ServiceManager.getService(Context.ROLLBACK_SERVICE));
+ try {
+ rm.notifyStagedApkSession(session.sessionId, apksToInstall.sessionId);
+ } catch (RemoteException re) {
+ Slog.e(TAG, "Failed to notifyStagedApkSession for session: "
+ + session.sessionId, re);
+ }
+ }
+
+ final LocalIntentReceiverSync receiver = new LocalIntentReceiverSync();
+ apksToInstall.commit(receiver.getIntentSender(), false);
+ final Intent result = receiver.getResult();
+ final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
+ PackageInstaller.STATUS_FAILURE);
+ if (status != PackageInstaller.STATUS_SUCCESS) {
+ final String errorMessage = result.getStringExtra(
+ PackageInstaller.EXTRA_STATUS_MESSAGE);
+ Slog.e(TAG, "Failure to install APK staged session "
+ + session.sessionId + " [" + errorMessage + "]");
+ throw new PackageManagerException(
+ SessionInfo.STAGED_SESSION_ACTIVATION_FAILED, errorMessage);
}
- // APEX single-package staged session, nothing to do.
}
void commitSession(@NonNull PackageInstallerSession session) {
@@ -808,8 +818,7 @@ public class StagingManager {
final List<PackageInfo> apexPackages =
submitSessionToApexService(session);
for (PackageInfo apexPackage : apexPackages) {
- validateApexSignature(
- apexPackage, session.params.installFlags);
+ validateApexSignature(apexPackage);
}
} catch (PackageManagerException e) {
session.setStagedSessionFailed(e.error, e.getMessage());
@@ -836,8 +845,8 @@ public class StagingManager {
Slog.d(TAG, "Running a pre-reboot verification for APKs in session "
+ session.sessionId + " by performing a dry-run install");
- // installApksInSession will notify the handler when APK verification is complete
- installApksInSession(session, /* preReboot */ true);
+ // verifyApksInSession will notify the handler when APK verification is complete
+ verifyApksInSession(session);
// TODO(b/118865310): abort the session on apexd.
} catch (PackageManagerException e) {
session.setStagedSessionFailed(e.error, e.getMessage());
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
index cc33fb0f5008..d318b1a4732c 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
@@ -276,18 +276,6 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
return;
}
- // Special case handling for uninitialized devices. This should only happen once.
- String newZoneId = bestTelephonySuggestion.suggestion.getZoneId();
- if (newZoneId != null && !mCallback.isDeviceTimeZoneInitialized()) {
- String cause = "Device has no time zone set. Attempting to set the device to the best"
- + " available suggestion."
- + " bestTelephonySuggestion=" + bestTelephonySuggestion
- + ", detectionReason=" + detectionReason;
- Slog.i(LOG_TAG, cause);
- setDeviceTimeZoneIfRequired(ORIGIN_TELEPHONY, newZoneId, cause);
- return;
- }
-
boolean suggestionGoodEnough =
bestTelephonySuggestion.score >= TELEPHONY_SCORE_USAGE_THRESHOLD;
if (!suggestionGoodEnough) {
@@ -301,6 +289,7 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
// Paranoia: Every suggestion above the SCORE_USAGE_THRESHOLD should have a non-null time
// zone ID.
+ String newZoneId = bestTelephonySuggestion.suggestion.getZoneId();
if (newZoneId == null) {
Slog.w(LOG_TAG, "Empty zone suggestion scored higher than expected. This is an error:"
+ " bestTelephonySuggestion=" + bestTelephonySuggestion
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
index ba309679e47a..30bb12e3e616 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
@@ -128,43 +128,69 @@ public class TimeZoneDetectorStrategyImplTest {
}
@Test
- public void testFirstPlausibleTelephonySuggestionAcceptedWhenTimeZoneUninitialized() {
+ public void testTelephonySuggestionsWhenTimeZoneUninitialized() {
+ assertTrue(TELEPHONY_SCORE_LOW < TELEPHONY_SCORE_USAGE_THRESHOLD);
+ assertTrue(TELEPHONY_SCORE_HIGH >= TELEPHONY_SCORE_USAGE_THRESHOLD);
SuggestionTestCase testCase = newTestCase(MATCH_TYPE_NETWORK_COUNTRY_ONLY,
QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS, TELEPHONY_SCORE_LOW);
- TelephonyTimeZoneSuggestion lowQualitySuggestion =
- testCase.createSuggestion(SLOT_INDEX1, "America/New_York");
+ SuggestionTestCase testCase2 = newTestCase(MATCH_TYPE_NETWORK_COUNTRY_ONLY,
+ QUALITY_SINGLE_ZONE, TELEPHONY_SCORE_HIGH);
- // The device time zone setting is left uninitialized.
Script script = new Script()
.initializeAutoTimeZoneDetection(true);
- // The very first suggestion will be taken.
- script.suggestTelephonyTimeZone(lowQualitySuggestion)
- .verifyTimeZoneSetAndReset(lowQualitySuggestion);
+ // A low quality suggestions will not be taken: The device time zone setting is left
+ // uninitialized.
+ {
+ TelephonyTimeZoneSuggestion lowQualitySuggestion =
+ testCase.createSuggestion(SLOT_INDEX1, "America/New_York");
- // Assert internal service state.
- QualifiedTelephonyTimeZoneSuggestion expectedScoredSuggestion =
- new QualifiedTelephonyTimeZoneSuggestion(
- lowQualitySuggestion, testCase.expectedScore);
- assertEquals(expectedScoredSuggestion,
- mTimeZoneDetectorStrategy.getLatestTelephonySuggestion(SLOT_INDEX1));
- assertEquals(expectedScoredSuggestion,
- mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests());
+ script.suggestTelephonyTimeZone(lowQualitySuggestion)
+ .verifyTimeZoneNotSet();
- // Another low quality suggestion will be ignored now that the setting is initialized.
- TelephonyTimeZoneSuggestion lowQualitySuggestion2 =
- testCase.createSuggestion(SLOT_INDEX1, "America/Los_Angeles");
- script.suggestTelephonyTimeZone(lowQualitySuggestion2)
- .verifyTimeZoneNotSet();
+ // Assert internal service state.
+ QualifiedTelephonyTimeZoneSuggestion expectedScoredSuggestion =
+ new QualifiedTelephonyTimeZoneSuggestion(
+ lowQualitySuggestion, testCase.expectedScore);
+ assertEquals(expectedScoredSuggestion,
+ mTimeZoneDetectorStrategy.getLatestTelephonySuggestion(SLOT_INDEX1));
+ assertEquals(expectedScoredSuggestion,
+ mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests());
+ }
- // Assert internal service state.
- QualifiedTelephonyTimeZoneSuggestion expectedScoredSuggestion2 =
- new QualifiedTelephonyTimeZoneSuggestion(
- lowQualitySuggestion2, testCase.expectedScore);
- assertEquals(expectedScoredSuggestion2,
- mTimeZoneDetectorStrategy.getLatestTelephonySuggestion(SLOT_INDEX1));
- assertEquals(expectedScoredSuggestion2,
- mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests());
+ // A good quality suggestion will be used.
+ {
+ TelephonyTimeZoneSuggestion goodQualitySuggestion =
+ testCase2.createSuggestion(SLOT_INDEX1, "Europe/London");
+ script.suggestTelephonyTimeZone(goodQualitySuggestion)
+ .verifyTimeZoneSetAndReset(goodQualitySuggestion);
+
+ // Assert internal service state.
+ QualifiedTelephonyTimeZoneSuggestion expectedScoredSuggestion =
+ new QualifiedTelephonyTimeZoneSuggestion(
+ goodQualitySuggestion, testCase2.expectedScore);
+ assertEquals(expectedScoredSuggestion,
+ mTimeZoneDetectorStrategy.getLatestTelephonySuggestion(SLOT_INDEX1));
+ assertEquals(expectedScoredSuggestion,
+ mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests());
+ }
+
+ // A low quality suggestion will be accepted, but not used to set the device time zone.
+ {
+ TelephonyTimeZoneSuggestion lowQualitySuggestion2 =
+ testCase.createSuggestion(SLOT_INDEX1, "America/Los_Angeles");
+ script.suggestTelephonyTimeZone(lowQualitySuggestion2)
+ .verifyTimeZoneNotSet();
+
+ // Assert internal service state.
+ QualifiedTelephonyTimeZoneSuggestion expectedScoredSuggestion =
+ new QualifiedTelephonyTimeZoneSuggestion(
+ lowQualitySuggestion2, testCase.expectedScore);
+ assertEquals(expectedScoredSuggestion,
+ mTimeZoneDetectorStrategy.getLatestTelephonySuggestion(SLOT_INDEX1));
+ assertEquals(expectedScoredSuggestion,
+ mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests());
+ }
}
/**
diff --git a/tests/net/java/android/net/NetworkTemplateTest.kt b/tests/net/java/android/net/NetworkTemplateTest.kt
new file mode 100644
index 000000000000..5dd0fda4da28
--- /dev/null
+++ b/tests/net/java/android/net/NetworkTemplateTest.kt
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net
+
+import android.content.Context
+import android.net.ConnectivityManager.TYPE_MOBILE
+import android.net.ConnectivityManager.TYPE_WIFI
+import android.net.NetworkIdentity.SUBTYPE_COMBINED
+import android.net.NetworkIdentity.buildNetworkIdentity
+import android.net.NetworkStats.DEFAULT_NETWORK_ALL
+import android.net.NetworkStats.METERED_ALL
+import android.net.NetworkStats.ROAMING_ALL
+import android.net.NetworkTemplate.MATCH_MOBILE
+import android.net.NetworkTemplate.MATCH_WIFI
+import android.net.NetworkTemplate.NETWORK_TYPE_ALL
+import android.net.NetworkTemplate.buildTemplateMobileWithRatType
+import android.telephony.TelephonyManager
+import com.android.testutils.assertParcelSane
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.mock
+import org.mockito.MockitoAnnotations
+import kotlin.test.assertFalse
+import kotlin.test.assertNotEquals
+import kotlin.test.assertTrue
+
+private const val TEST_IMSI1 = "imsi1"
+private const val TEST_IMSI2 = "imsi2"
+private const val TEST_SSID1 = "ssid1"
+
+@RunWith(JUnit4::class)
+class NetworkTemplateTest {
+ private val mockContext = mock(Context::class.java)
+
+ private fun buildMobileNetworkState(subscriberId: String): NetworkState =
+ buildNetworkState(TYPE_MOBILE, subscriberId = subscriberId)
+ private fun buildWifiNetworkState(ssid: String): NetworkState =
+ buildNetworkState(TYPE_WIFI, ssid = ssid)
+
+ private fun buildNetworkState(
+ type: Int,
+ subscriberId: String? = null,
+ ssid: String? = null
+ ): NetworkState {
+ val info = mock(NetworkInfo::class.java)
+ doReturn(type).`when`(info).type
+ doReturn(NetworkInfo.State.CONNECTED).`when`(info).state
+ val lp = LinkProperties()
+ val caps = NetworkCapabilities().apply {
+ setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, false)
+ setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true)
+ }
+ return NetworkState(info, lp, caps, mock(Network::class.java), subscriberId, ssid)
+ }
+
+ private fun NetworkTemplate.assertMatches(ident: NetworkIdentity) =
+ assertTrue(matches(ident), "$this does not match $ident")
+
+ private fun NetworkTemplate.assertDoesNotMatch(ident: NetworkIdentity) =
+ assertFalse(matches(ident), "$this should match $ident")
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ }
+
+ @Test
+ fun testRatTypeGroupMatches() {
+ val stateMobile = buildMobileNetworkState(TEST_IMSI1)
+ // Build UMTS template that matches mobile identities with RAT in the same
+ // group with any IMSI. See {@link NetworkTemplate#getCollapsedRatType}.
+ val templateUmts = buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_UMTS)
+ // Build normal template that matches mobile identities with any RAT and IMSI.
+ val templateAll = buildTemplateMobileWithRatType(null, NETWORK_TYPE_ALL)
+ // Build template with UNKNOWN RAT that matches mobile identities with RAT that
+ // cannot be determined.
+ val templateUnknown =
+ buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_UNKNOWN)
+
+ val identUmts = buildNetworkIdentity(
+ mockContext, stateMobile, false, TelephonyManager.NETWORK_TYPE_UMTS)
+ val identHsdpa = buildNetworkIdentity(
+ mockContext, stateMobile, false, TelephonyManager.NETWORK_TYPE_HSDPA)
+ val identLte = buildNetworkIdentity(
+ mockContext, stateMobile, false, TelephonyManager.NETWORK_TYPE_LTE)
+ val identCombined = buildNetworkIdentity(
+ mockContext, stateMobile, false, SUBTYPE_COMBINED)
+ val identImsi2 = buildNetworkIdentity(mockContext, buildMobileNetworkState(TEST_IMSI2),
+ false, TelephonyManager.NETWORK_TYPE_UMTS)
+ val identWifi = buildNetworkIdentity(
+ mockContext, buildWifiNetworkState(TEST_SSID1), true, 0)
+
+ // Assert that identity with the same RAT matches.
+ templateUmts.assertMatches(identUmts)
+ templateAll.assertMatches(identUmts)
+ templateUnknown.assertDoesNotMatch(identUmts)
+ // Assert that identity with the RAT within the same group matches.
+ templateUmts.assertMatches(identHsdpa)
+ templateAll.assertMatches(identHsdpa)
+ templateUnknown.assertDoesNotMatch(identHsdpa)
+ // Assert that identity with the RAT out of the same group only matches template with
+ // NETWORK_TYPE_ALL.
+ templateUmts.assertDoesNotMatch(identLte)
+ templateAll.assertMatches(identLte)
+ templateUnknown.assertDoesNotMatch(identLte)
+ // Assert that identity with combined RAT only matches with template with NETWORK_TYPE_ALL
+ // and NETWORK_TYPE_UNKNOWN.
+ templateUmts.assertDoesNotMatch(identCombined)
+ templateAll.assertMatches(identCombined)
+ templateUnknown.assertMatches(identCombined)
+ // Assert that identity with different IMSI matches.
+ templateUmts.assertMatches(identImsi2)
+ templateAll.assertMatches(identImsi2)
+ templateUnknown.assertDoesNotMatch(identImsi2)
+ // Assert that wifi identity does not match.
+ templateUmts.assertDoesNotMatch(identWifi)
+ templateAll.assertDoesNotMatch(identWifi)
+ templateUnknown.assertDoesNotMatch(identWifi)
+ }
+
+ @Test
+ fun testParcelUnparcel() {
+ val templateMobile = NetworkTemplate(MATCH_MOBILE, TEST_IMSI1, null, null, METERED_ALL,
+ ROAMING_ALL, DEFAULT_NETWORK_ALL, TelephonyManager.NETWORK_TYPE_LTE)
+ val templateWifi = NetworkTemplate(MATCH_WIFI, null, null, TEST_SSID1, METERED_ALL,
+ ROAMING_ALL, DEFAULT_NETWORK_ALL, 0)
+ assertParcelSane(templateMobile, 8)
+ assertParcelSane(templateWifi, 8)
+ }
+
+ // Verify NETWORK_TYPE_ALL does not conflict with TelephonyManager#NETWORK_TYPE_* constants.
+ @Test
+ fun testNetworkTypeAll() {
+ for (ratType in TelephonyManager.getAllNetworkTypes()) {
+ assertNotEquals(NETWORK_TYPE_ALL, ratType)
+ }
+ }
+}
diff --git a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java b/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
index 8f90f13ce7ef..551498f2c0cc 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
@@ -319,33 +319,33 @@ public class NetworkStatsCollectionTest {
assertEntry(18322, 75, 15031, 75, history.getValues(i++, null));
assertEntry(527798, 761, 78570, 652, history.getValues(i++, null));
assertEntry(527797, 760, 78570, 651, history.getValues(i++, null));
- assertEntry(10747, 50, 16838, 55, history.getValues(i++, null));
- assertEntry(10747, 49, 16838, 54, history.getValues(i++, null));
+ assertEntry(10747, 50, 16839, 55, history.getValues(i++, null));
+ assertEntry(10747, 49, 16837, 54, history.getValues(i++, null));
assertEntry(89191, 151, 18021, 140, history.getValues(i++, null));
assertEntry(89190, 150, 18020, 139, history.getValues(i++, null));
- assertEntry(3821, 22, 4525, 26, history.getValues(i++, null));
- assertEntry(3820, 22, 4524, 26, history.getValues(i++, null));
- assertEntry(91686, 159, 18575, 146, history.getValues(i++, null));
- assertEntry(91685, 159, 18575, 146, history.getValues(i++, null));
- assertEntry(8289, 35, 6863, 38, history.getValues(i++, null));
- assertEntry(8289, 35, 6863, 38, history.getValues(i++, null));
+ assertEntry(3821, 23, 4525, 26, history.getValues(i++, null));
+ assertEntry(3820, 21, 4524, 26, history.getValues(i++, null));
+ assertEntry(91686, 159, 18576, 146, history.getValues(i++, null));
+ assertEntry(91685, 159, 18574, 146, history.getValues(i++, null));
+ assertEntry(8289, 36, 6864, 39, history.getValues(i++, null));
+ assertEntry(8289, 34, 6862, 37, history.getValues(i++, null));
assertEntry(113914, 174, 18364, 157, history.getValues(i++, null));
assertEntry(113913, 173, 18364, 157, history.getValues(i++, null));
- assertEntry(11378, 49, 9261, 49, history.getValues(i++, null));
- assertEntry(11377, 48, 9261, 49, history.getValues(i++, null));
- assertEntry(201765, 328, 41808, 291, history.getValues(i++, null));
- assertEntry(201765, 328, 41807, 290, history.getValues(i++, null));
- assertEntry(106106, 218, 39917, 201, history.getValues(i++, null));
- assertEntry(106105, 217, 39917, 201, history.getValues(i++, null));
+ assertEntry(11378, 49, 9261, 50, history.getValues(i++, null));
+ assertEntry(11377, 48, 9261, 48, history.getValues(i++, null));
+ assertEntry(201766, 328, 41808, 291, history.getValues(i++, null));
+ assertEntry(201764, 328, 41807, 290, history.getValues(i++, null));
+ assertEntry(106106, 219, 39918, 202, history.getValues(i++, null));
+ assertEntry(106105, 216, 39916, 200, history.getValues(i++, null));
assertEquals(history.size(), i);
// Slice from middle should be untouched
history = getHistory(collection, plan, TIME_B - HOUR_IN_MILLIS,
TIME_B + HOUR_IN_MILLIS); i = 0;
- assertEntry(3821, 22, 4525, 26, history.getValues(i++, null));
- assertEntry(3820, 22, 4524, 26, history.getValues(i++, null));
- assertEntry(91686, 159, 18575, 146, history.getValues(i++, null));
- assertEntry(91685, 159, 18575, 146, history.getValues(i++, null));
+ assertEntry(3821, 23, 4525, 26, history.getValues(i++, null));
+ assertEntry(3820, 21, 4524, 26, history.getValues(i++, null));
+ assertEntry(91686, 159, 18576, 146, history.getValues(i++, null));
+ assertEntry(91685, 159, 18574, 146, history.getValues(i++, null));
assertEquals(history.size(), i);
}
@@ -373,25 +373,25 @@ public class NetworkStatsCollectionTest {
assertEntry(527797, 760, 78570, 651, history.getValues(i++, null));
// Cycle point; start data normalization
assertEntry(7507, 0, 11763, 0, history.getValues(i++, null));
- assertEntry(7507, 0, 11763, 0, history.getValues(i++, null));
+ assertEntry(7507, 0, 11762, 0, history.getValues(i++, null));
assertEntry(62309, 0, 12589, 0, history.getValues(i++, null));
assertEntry(62309, 0, 12588, 0, history.getValues(i++, null));
assertEntry(2669, 0, 3161, 0, history.getValues(i++, null));
assertEntry(2668, 0, 3160, 0, history.getValues(i++, null));
// Anchor point; end data normalization
- assertEntry(91686, 159, 18575, 146, history.getValues(i++, null));
- assertEntry(91685, 159, 18575, 146, history.getValues(i++, null));
- assertEntry(8289, 35, 6863, 38, history.getValues(i++, null));
- assertEntry(8289, 35, 6863, 38, history.getValues(i++, null));
+ assertEntry(91686, 159, 18576, 146, history.getValues(i++, null));
+ assertEntry(91685, 159, 18574, 146, history.getValues(i++, null));
+ assertEntry(8289, 36, 6864, 39, history.getValues(i++, null));
+ assertEntry(8289, 34, 6862, 37, history.getValues(i++, null));
assertEntry(113914, 174, 18364, 157, history.getValues(i++, null));
assertEntry(113913, 173, 18364, 157, history.getValues(i++, null));
// Cycle point
- assertEntry(11378, 49, 9261, 49, history.getValues(i++, null));
- assertEntry(11377, 48, 9261, 49, history.getValues(i++, null));
- assertEntry(201765, 328, 41808, 291, history.getValues(i++, null));
- assertEntry(201765, 328, 41807, 290, history.getValues(i++, null));
- assertEntry(106106, 218, 39917, 201, history.getValues(i++, null));
- assertEntry(106105, 217, 39917, 201, history.getValues(i++, null));
+ assertEntry(11378, 49, 9261, 50, history.getValues(i++, null));
+ assertEntry(11377, 48, 9261, 48, history.getValues(i++, null));
+ assertEntry(201766, 328, 41808, 291, history.getValues(i++, null));
+ assertEntry(201764, 328, 41807, 290, history.getValues(i++, null));
+ assertEntry(106106, 219, 39918, 202, history.getValues(i++, null));
+ assertEntry(106105, 216, 39916, 200, history.getValues(i++, null));
assertEquals(history.size(), i);
// Slice from middle should be augmented
@@ -399,8 +399,8 @@ public class NetworkStatsCollectionTest {
TIME_B + HOUR_IN_MILLIS); i = 0;
assertEntry(2669, 0, 3161, 0, history.getValues(i++, null));
assertEntry(2668, 0, 3160, 0, history.getValues(i++, null));
- assertEntry(91686, 159, 18575, 146, history.getValues(i++, null));
- assertEntry(91685, 159, 18575, 146, history.getValues(i++, null));
+ assertEntry(91686, 159, 18576, 146, history.getValues(i++, null));
+ assertEntry(91685, 159, 18574, 146, history.getValues(i++, null));
assertEquals(history.size(), i);
}
@@ -427,34 +427,34 @@ public class NetworkStatsCollectionTest {
assertEntry(527798, 761, 78570, 652, history.getValues(i++, null));
assertEntry(527797, 760, 78570, 651, history.getValues(i++, null));
// Cycle point; start data normalization
- assertEntry(15015, 0, 23526, 0, history.getValues(i++, null));
- assertEntry(15015, 0, 23526, 0, history.getValues(i++, null));
+ assertEntry(15015, 0, 23527, 0, history.getValues(i++, null));
+ assertEntry(15015, 0, 23524, 0, history.getValues(i++, null));
assertEntry(124619, 0, 25179, 0, history.getValues(i++, null));
assertEntry(124618, 0, 25177, 0, history.getValues(i++, null));
assertEntry(5338, 0, 6322, 0, history.getValues(i++, null));
assertEntry(5337, 0, 6320, 0, history.getValues(i++, null));
// Anchor point; end data normalization
- assertEntry(91686, 159, 18575, 146, history.getValues(i++, null));
- assertEntry(91685, 159, 18575, 146, history.getValues(i++, null));
- assertEntry(8289, 35, 6863, 38, history.getValues(i++, null));
- assertEntry(8289, 35, 6863, 38, history.getValues(i++, null));
+ assertEntry(91686, 159, 18576, 146, history.getValues(i++, null));
+ assertEntry(91685, 159, 18574, 146, history.getValues(i++, null));
+ assertEntry(8289, 36, 6864, 39, history.getValues(i++, null));
+ assertEntry(8289, 34, 6862, 37, history.getValues(i++, null));
assertEntry(113914, 174, 18364, 157, history.getValues(i++, null));
assertEntry(113913, 173, 18364, 157, history.getValues(i++, null));
// Cycle point
- assertEntry(11378, 49, 9261, 49, history.getValues(i++, null));
- assertEntry(11377, 48, 9261, 49, history.getValues(i++, null));
- assertEntry(201765, 328, 41808, 291, history.getValues(i++, null));
- assertEntry(201765, 328, 41807, 290, history.getValues(i++, null));
- assertEntry(106106, 218, 39917, 201, history.getValues(i++, null));
- assertEntry(106105, 217, 39917, 201, history.getValues(i++, null));
+ assertEntry(11378, 49, 9261, 50, history.getValues(i++, null));
+ assertEntry(11377, 48, 9261, 48, history.getValues(i++, null));
+ assertEntry(201766, 328, 41808, 291, history.getValues(i++, null));
+ assertEntry(201764, 328, 41807, 290, history.getValues(i++, null));
+ assertEntry(106106, 219, 39918, 202, history.getValues(i++, null));
+ assertEntry(106105, 216, 39916, 200, history.getValues(i++, null));
// Slice from middle should be augmented
history = getHistory(collection, plan, TIME_B - HOUR_IN_MILLIS,
TIME_B + HOUR_IN_MILLIS); i = 0;
assertEntry(5338, 0, 6322, 0, history.getValues(i++, null));
assertEntry(5337, 0, 6320, 0, history.getValues(i++, null));
- assertEntry(91686, 159, 18575, 146, history.getValues(i++, null));
- assertEntry(91685, 159, 18575, 146, history.getValues(i++, null));
+ assertEntry(91686, 159, 18576, 146, history.getValues(i++, null));
+ assertEntry(91685, 159, 18574, 146, history.getValues(i++, null));
assertEquals(history.size(), i);
}
}
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index b346c923914e..6e6331312eac 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -42,6 +42,7 @@ import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
import static android.net.NetworkStatsHistory.FIELD_ALL;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
+import static android.net.NetworkTemplate.buildTemplateMobileWithRatType;
import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
import static android.net.TrafficStats.MB_IN_BYTES;
import static android.net.TrafficStats.UID_REMOVED;
@@ -60,11 +61,13 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.AlarmManager;
import android.app.usage.NetworkStatsManager;
import android.content.Context;
@@ -92,6 +95,8 @@ import android.os.Message;
import android.os.Messenger;
import android.os.PowerManager;
import android.os.SimpleClock;
+import android.telephony.PhoneStateListener;
+import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import androidx.test.InstrumentationRegistry;
@@ -163,11 +168,14 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
private @Mock NetworkStatsSettings mSettings;
private @Mock IBinder mBinder;
private @Mock AlarmManager mAlarmManager;
+ private @Mock TelephonyManager mTelephonyManager;
private HandlerThread mHandlerThread;
private NetworkStatsService mService;
private INetworkStatsSession mSession;
private INetworkManagementEventObserver mNetworkObserver;
+ @Nullable
+ private PhoneStateListener mPhoneStateListener;
private final Clock mClock = new SimpleClock(ZoneOffset.UTC) {
@Override
@@ -195,7 +203,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
mHandlerThread = new HandlerThread("HandlerThread");
final NetworkStatsService.Dependencies deps = makeDependencies();
mService = new NetworkStatsService(mServiceContext, mNetManager, mAlarmManager, wakeLock,
- mClock, mServiceContext.getSystemService(TelephonyManager.class), mSettings,
+ mClock, mTelephonyManager, mSettings,
mStatsFactory, new NetworkStatsObservers(), mStatsDir, getBaseDir(mStatsDir), deps);
mElapsedRealtime = 0L;
@@ -216,6 +224,12 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
ArgumentCaptor.forClass(INetworkManagementEventObserver.class);
verify(mNetManager).registerObserver(networkObserver.capture());
mNetworkObserver = networkObserver.getValue();
+
+ // Capture the phone state listener that created by service.
+ final ArgumentCaptor<PhoneStateListener> phoneStateListenerCaptor =
+ ArgumentCaptor.forClass(PhoneStateListener.class);
+ verify(mTelephonyManager).listen(phoneStateListenerCaptor.capture(), anyInt());
+ mPhoneStateListener = phoneStateListenerCaptor.getValue();
}
@NonNull
@@ -534,7 +548,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
}
@Test
- public void testUid3g4gCombinedByTemplate() throws Exception {
+ public void testUid3gWimaxCombinedByTemplate() throws Exception {
// pretend that network comes online
expectDefaultSettings();
NetworkState[] states = new NetworkState[] {buildMobile3gState(IMSI_1)};
@@ -558,10 +572,10 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
assertUidTotal(sTemplateImsi1, UID_RED, 1024L, 8L, 1024L, 8L, 5);
- // now switch over to 4g network
+ // now switch over to wimax network
incrementCurrentTime(HOUR_IN_MILLIS);
expectDefaultSettings();
- states = new NetworkState[] {buildMobile4gState(TEST_IFACE2)};
+ states = new NetworkState[] {buildWimaxState(TEST_IFACE2)};
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
.insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L)
@@ -589,6 +603,89 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
}
@Test
+ public void testMobileStatsByRatType() throws Exception {
+ final NetworkTemplate template3g =
+ buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_UMTS);
+ final NetworkTemplate template4g =
+ buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_LTE);
+ final NetworkTemplate template5g =
+ buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_NR);
+ final NetworkState[] states = new NetworkState[]{buildMobile3gState(IMSI_1)};
+
+ // 3G network comes online.
+ expectNetworkStatsSummary(buildEmptyStats());
+ expectNetworkStatsUidDetail(buildEmptyStats());
+
+ setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_UMTS);
+ mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ new VpnInfo[0]);
+
+ // Create some traffic.
+ incrementCurrentTime(MINUTE_IN_MILLIS);
+ expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
+ .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE,
+ 12L, 18L, 14L, 1L, 0L)));
+ forcePollAndWaitForIdle();
+
+ // Verify 3g templates gets stats.
+ assertUidTotal(sTemplateImsi1, UID_RED, 12L, 18L, 14L, 1L, 0);
+ assertUidTotal(template3g, UID_RED, 12L, 18L, 14L, 1L, 0);
+ assertUidTotal(template4g, UID_RED, 0L, 0L, 0L, 0L, 0);
+ assertUidTotal(template5g, UID_RED, 0L, 0L, 0L, 0L, 0);
+
+ // 4G network comes online.
+ incrementCurrentTime(MINUTE_IN_MILLIS);
+ setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_LTE);
+ expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
+ // Append more traffic on existing 3g stats entry.
+ .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE,
+ 16L, 22L, 17L, 2L, 0L))
+ // Add entry that is new on 4g.
+ .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE,
+ 33L, 27L, 8L, 10L, 1L)));
+ forcePollAndWaitForIdle();
+
+ // Verify ALL_MOBILE template gets all. 3g template counters do not increase.
+ assertUidTotal(sTemplateImsi1, UID_RED, 49L, 49L, 25L, 12L, 1);
+ assertUidTotal(template3g, UID_RED, 12L, 18L, 14L, 1L, 0);
+ // Verify 4g template counts appended stats on existing entry and newly created entry.
+ assertUidTotal(template4g, UID_RED, 4L + 33L, 4L + 27L, 3L + 8L, 1L + 10L, 1);
+ // Verify 5g template doesn't get anything since no traffic is generated on 5g.
+ assertUidTotal(template5g, UID_RED, 0L, 0L, 0L, 0L, 0);
+
+ // 5g network comes online.
+ incrementCurrentTime(MINUTE_IN_MILLIS);
+ setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_NR);
+ expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
+ // Existing stats remains.
+ .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE,
+ 16L, 22L, 17L, 2L, 0L))
+ .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE,
+ 33L, 27L, 8L, 10L, 1L))
+ // Add some traffic on 5g.
+ .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE,
+ 5L, 13L, 31L, 9L, 2L)));
+ forcePollAndWaitForIdle();
+
+ // Verify ALL_MOBILE template gets all.
+ assertUidTotal(sTemplateImsi1, UID_RED, 54L, 62L, 56L, 21L, 3);
+ // 3g/4g template counters do not increase.
+ assertUidTotal(template3g, UID_RED, 12L, 18L, 14L, 1L, 0);
+ assertUidTotal(template4g, UID_RED, 4L + 33L, 4L + 27L, 3L + 8L, 1L + 10L, 1);
+ // Verify 5g template gets the 5g count.
+ assertUidTotal(template5g, UID_RED, 5L, 13L, 31L, 9L, 2);
+ }
+
+ // TODO: support per IMSI state
+ private void setMobileRatTypeAndWaitForIdle(int ratType) {
+ final ServiceState mockSs = mock(ServiceState.class);
+ when(mockSs.getDataNetworkType()).thenReturn(ratType);
+ mPhoneStateListener.onServiceStateChanged(mockSs);
+
+ HandlerUtilsKt.waitForIdle(mHandlerThread, WAIT_TIMEOUT);
+ }
+
+ @Test
public void testSummaryForAllUid() throws Exception {
// pretend that network comes online
expectDefaultSettings();
@@ -1197,6 +1294,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
when(mSettings.getPollInterval()).thenReturn(HOUR_IN_MILLIS);
when(mSettings.getPollDelay()).thenReturn(0L);
when(mSettings.getSampleEnabled()).thenReturn(true);
+ when(mSettings.getCombineSubtypeEnabled()).thenReturn(false);
final Config config = new Config(bucketDuration, deleteAge, deleteAge);
when(mSettings.getDevConfig()).thenReturn(config);
@@ -1242,6 +1340,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
final NetworkCapabilities capabilities = new NetworkCapabilities();
capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, !isMetered);
capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true);
+ capabilities.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
return new NetworkState(info, prop, capabilities, WIFI_NETWORK, null, TEST_SSID);
}
@@ -1259,10 +1358,11 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
final NetworkCapabilities capabilities = new NetworkCapabilities();
capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, false);
capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, !isRoaming);
+ capabilities.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
return new NetworkState(info, prop, capabilities, MOBILE_NETWORK, subscriberId, null);
}
- private static NetworkState buildMobile4gState(String iface) {
+ private static NetworkState buildWimaxState(@NonNull String iface) {
final NetworkInfo info = new NetworkInfo(TYPE_WIMAX, 0, null, null);
info.setDetailedState(DetailedState.CONNECTED, null, null);
final LinkProperties prop = new LinkProperties();