Merge mainline-release 6664920 to master - DO NOT MERGE
Merged-In: Id04ea331831e8b26ba99478848392b40a92548d5
Change-Id: I888da0c9475f2d00602d917d2f58169f8d7c93a4
diff --git a/core/java/android/net/ITetheredInterfaceCallback.aidl b/core/java/android/net/ITetheredInterfaceCallback.aidl
index e3d0759..14aa023 100644
--- a/core/java/android/net/ITetheredInterfaceCallback.aidl
+++ b/core/java/android/net/ITetheredInterfaceCallback.aidl
@@ -17,7 +17,7 @@
package android.net;
/** @hide */
-interface ITetheredInterfaceCallback {
+oneway interface ITetheredInterfaceCallback {
void onAvailable(in String iface);
void onUnavailable();
}
\ No newline at end of file
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java
index 3c1b86b..51f09a0 100644
--- a/core/java/android/net/NetworkStatsHistory.java
+++ b/core/java/android/net/NetworkStatsHistory.java
@@ -26,6 +26,7 @@
import static android.net.NetworkStatsHistory.Entry.UNKNOWN;
import static android.net.NetworkStatsHistory.ParcelUtils.readLongArray;
import static android.net.NetworkStatsHistory.ParcelUtils.writeLongArray;
+import static android.net.NetworkUtils.multiplySafeByRational;
import static android.text.format.DateUtils.SECOND_IN_MILLIS;
import static com.android.internal.util.ArrayUtils.total;
@@ -364,11 +365,12 @@
if (overlap <= 0) continue;
// integer math each time is faster than floating point
- final long fracRxBytes = rxBytes * overlap / duration;
- final long fracRxPackets = rxPackets * overlap / duration;
- final long fracTxBytes = txBytes * overlap / duration;
- final long fracTxPackets = txPackets * overlap / duration;
- final long fracOperations = operations * overlap / duration;
+ final long fracRxBytes = multiplySafeByRational(rxBytes, overlap, duration);
+ final long fracRxPackets = multiplySafeByRational(rxPackets, overlap, duration);
+ final long fracTxBytes = multiplySafeByRational(txBytes, overlap, duration);
+ final long fracTxPackets = multiplySafeByRational(txPackets, overlap, duration);
+ final long fracOperations = multiplySafeByRational(operations, overlap, duration);
+
addLong(activeTime, i, overlap);
addLong(this.rxBytes, i, fracRxBytes); rxBytes -= fracRxBytes;
@@ -568,12 +570,24 @@
if (overlap <= 0) continue;
// integer math each time is faster than floating point
- if (activeTime != null) entry.activeTime += activeTime[i] * overlap / bucketSpan;
- if (rxBytes != null) entry.rxBytes += rxBytes[i] * overlap / bucketSpan;
- if (rxPackets != null) entry.rxPackets += rxPackets[i] * overlap / bucketSpan;
- if (txBytes != null) entry.txBytes += txBytes[i] * overlap / bucketSpan;
- if (txPackets != null) entry.txPackets += txPackets[i] * overlap / bucketSpan;
- if (operations != null) entry.operations += operations[i] * overlap / bucketSpan;
+ if (activeTime != null) {
+ entry.activeTime += multiplySafeByRational(activeTime[i], overlap, bucketSpan);
+ }
+ if (rxBytes != null) {
+ entry.rxBytes += multiplySafeByRational(rxBytes[i], overlap, bucketSpan);
+ }
+ if (rxPackets != null) {
+ entry.rxPackets += multiplySafeByRational(rxPackets[i], overlap, bucketSpan);
+ }
+ if (txBytes != null) {
+ entry.txBytes += multiplySafeByRational(txBytes[i], overlap, bucketSpan);
+ }
+ if (txPackets != null) {
+ entry.txPackets += multiplySafeByRational(txPackets[i], overlap, bucketSpan);
+ }
+ if (operations != null) {
+ entry.operations += multiplySafeByRational(operations[i], overlap, bucketSpan);
+ }
}
return entry;
}
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index eba7ff3..cd26079 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -87,6 +87,15 @@
* @hide
*/
public static final int NETWORK_TYPE_ALL = -1;
+ /**
+ * Virtual RAT type to represent 5G NSA (Non Stand Alone) mode, where the primary cell is
+ * still LTE and network allocates a secondary 5G cell so telephony reports RAT = LTE along
+ * with NR state as connected. This should not be overlapped with any of the
+ * {@code TelephonyManager.NETWORK_TYPE_*} constants.
+ *
+ * @hide
+ */
+ public static final int NETWORK_TYPE_5G_NSA = -2;
private static boolean isKnownMatchRule(final int rule) {
switch (rule) {
@@ -475,6 +484,9 @@
return TelephonyManager.NETWORK_TYPE_LTE;
case TelephonyManager.NETWORK_TYPE_NR:
return TelephonyManager.NETWORK_TYPE_NR;
+ // Virtual RAT type for 5G NSA mode, see {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}.
+ case NetworkTemplate.NETWORK_TYPE_5G_NSA:
+ return NetworkTemplate.NETWORK_TYPE_5G_NSA;
default:
return TelephonyManager.NETWORK_TYPE_UNKNOWN;
}
@@ -491,6 +503,10 @@
for (final int ratType : ratTypes) {
collapsedRatTypes.add(NetworkTemplate.getCollapsedRatType(ratType));
}
+ // Add NETWORK_TYPE_5G_NSA to the returned list since 5G NSA is a virtual RAT type and
+ // it is not in TelephonyManager#NETWORK_TYPE_* constants.
+ // See {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}.
+ collapsedRatTypes.add(NetworkTemplate.getCollapsedRatType(NETWORK_TYPE_5G_NSA));
// Ensure that unknown type is returned.
collapsedRatTypes.add(TelephonyManager.NETWORK_TYPE_UNKNOWN);
return toIntArray(collapsedRatTypes);
diff --git a/packages/Tethering/src/android/net/util/TetheringMessageBase.java b/packages/Tethering/src/android/net/util/TetheringMessageBase.java
index 1b763ce..29c0a81 100644
--- a/packages/Tethering/src/android/net/util/TetheringMessageBase.java
+++ b/packages/Tethering/src/android/net/util/TetheringMessageBase.java
@@ -19,7 +19,7 @@
* This class defines Message.what base addresses for various state machine.
*/
public class TetheringMessageBase {
- public static final int BASE_MASTER = 0;
+ public static final int BASE_MAIN_SM = 0;
public static final int BASE_IPSERVER = 100;
}
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index 6402e07..b2f0c83 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -1477,7 +1477,7 @@
}
/**
- * Checks an IpSecConfig parcel to ensure that the contents are sane and throws an
+ * Checks an IpSecConfig parcel to ensure that the contents are valid and throws an
* IllegalArgumentException if they are not.
*/
private void checkIpSecConfig(IpSecConfig config) {
diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/services/core/java/com/android/server/net/IpConfigStore.java
index e3e02e3..f0bf5c0 100644
--- a/services/core/java/com/android/server/net/IpConfigStore.java
+++ b/services/core/java/com/android/server/net/IpConfigStore.java
@@ -24,6 +24,7 @@
import android.net.ProxyInfo;
import android.net.RouteInfo;
import android.net.StaticIpConfiguration;
+import android.net.Uri;
import android.util.ArrayMap;
import android.util.Log;
import android.util.SparseArray;
@@ -372,7 +373,7 @@
config.httpProxy = proxyInfo;
break;
case PAC:
- ProxyInfo proxyPacProperties = new ProxyInfo(pacFileUrl);
+ ProxyInfo proxyPacProperties = new ProxyInfo(Uri.parse(pacFileUrl));
config.proxySettings = proxySettings;
config.httpProxy = proxyPacProperties;
break;
diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java
index 05ab2ae..342a11b 100644
--- a/services/core/java/com/android/server/net/NetworkStatsCollection.java
+++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java
@@ -28,6 +28,7 @@
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
import static android.net.TrafficStats.UID_REMOVED;
+import static android.net.NetworkUtils.multiplySafeByRational;
import static android.text.format.DateUtils.WEEK_IN_MILLIS;
import static com.android.server.net.NetworkStatsService.TAG;
@@ -185,35 +186,6 @@
}
}
- /**
- * Safely multiple a value by a rational.
- * <p>
- * Internally it uses integer-based math whenever possible, but switches
- * over to double-based math if values would overflow.
- */
- @VisibleForTesting
- public static long multiplySafe(long value, long num, long den) {
- if (den == 0) den = 1;
- long x = value;
- long y = num;
-
- // Logic shamelessly borrowed from Math.multiplyExact()
- long r = x * y;
- long ax = Math.abs(x);
- long ay = Math.abs(y);
- if (((ax | ay) >>> 31 != 0)) {
- // Some bits greater than 2^31 that might cause overflow
- // Check the result using the divide operator
- // and check for the special case of Long.MIN_VALUE * -1
- if (((y != 0) && (r / y != x)) ||
- (x == Long.MIN_VALUE && y == -1)) {
- // Use double math to avoid overflowing
- return (long) (((double) num / den) * value);
- }
- }
- return r / den;
- }
-
public int[] getRelevantUids(@NetworkStatsAccess.Level int accessLevel) {
return getRelevantUids(accessLevel, Binder.getCallingUid());
}
@@ -311,11 +283,13 @@
}
final long rawBytes = entry.rxBytes + entry.txBytes;
- final long rawRxBytes = entry.rxBytes;
- final long rawTxBytes = entry.txBytes;
+ final long rawRxBytes = entry.rxBytes == 0 ? 1 : entry.rxBytes;
+ final long rawTxBytes = entry.txBytes == 0 ? 1 : entry.txBytes;
final long targetBytes = augmentPlan.getDataUsageBytes();
- final long targetRxBytes = multiplySafe(targetBytes, rawRxBytes, rawBytes);
- final long targetTxBytes = multiplySafe(targetBytes, rawTxBytes, rawBytes);
+
+ final long targetRxBytes = multiplySafeByRational(targetBytes, rawRxBytes, rawBytes);
+ final long targetTxBytes = multiplySafeByRational(targetBytes, rawTxBytes, rawBytes);
+
// Scale all matching buckets to reach anchor target
final long beforeTotal = combined.getTotalBytes();
@@ -323,8 +297,10 @@
combined.getValues(i, entry);
if (entry.bucketStart >= augmentStart
&& entry.bucketStart + entry.bucketDuration <= augmentEnd) {
- entry.rxBytes = multiplySafe(targetRxBytes, entry.rxBytes, rawRxBytes);
- entry.txBytes = multiplySafe(targetTxBytes, entry.txBytes, rawTxBytes);
+ entry.rxBytes = multiplySafeByRational(
+ targetRxBytes, entry.rxBytes, rawRxBytes);
+ entry.txBytes = multiplySafeByRational(
+ targetTxBytes, entry.txBytes, rawTxBytes);
// We purposefully clear out packet counters to indicate
// that this data has been augmented.
entry.rxPackets = 0;
diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java
index 86ad0b3..e9868fd 100644
--- a/services/core/java/com/android/server/net/NetworkStatsFactory.java
+++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java
@@ -59,7 +59,7 @@
private static final String TAG = "NetworkStatsFactory";
private static final boolean USE_NATIVE_PARSING = true;
- private static final boolean SANITY_CHECK_NATIVE = false;
+ private static final boolean VALIDATE_NATIVE_STATS = false;
/** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */
private final File mStatsXtIfaceAll;
@@ -347,7 +347,7 @@
INTERFACES_ALL, TAG_ALL, mUseBpfStats) != 0) {
throw new IOException("Failed to parse network stats");
}
- if (SANITY_CHECK_NATIVE) {
+ if (VALIDATE_NATIVE_STATS) {
final NetworkStats javaStats = javaReadNetworkStatsDetail(mStatsXtUid,
UID_ALL, INTERFACES_ALL, TAG_ALL);
assertEquals(javaStats, stats);
diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
index 9eff5d1..ce74169 100644
--- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java
+++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
@@ -227,7 +227,7 @@
for (int i = 0; i < delta.size(); i++) {
entry = delta.getValues(i, entry);
- // As a last-ditch sanity check, report any negative values and
+ // As a last-ditch check, report any negative values and
// clamp them so recording below doesn't croak.
if (entry.isNegative()) {
if (mObserver != null) {
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index ba9f486..71e7c8a 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -87,6 +87,7 @@
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.database.ContentObserver;
import android.net.DataUsageRequest;
import android.net.INetworkManagementEventObserver;
import android.net.INetworkStatsService;
@@ -103,6 +104,7 @@
import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
import android.net.TrafficStats;
+import android.net.Uri;
import android.net.netstats.provider.INetworkStatsProvider;
import android.net.netstats.provider.INetworkStatsProviderCallback;
import android.net.netstats.provider.NetworkStatsProvider;
@@ -213,6 +215,9 @@
private final boolean mUseBpfTrafficStats;
+ private final ContentObserver mContentObserver;
+ private final ContentResolver mContentResolver;
+
@VisibleForTesting
public static final String ACTION_NETWORK_STATS_POLL =
"com.android.server.action.NETWORK_STATS_POLL";
@@ -437,7 +442,10 @@
handlerThread.start();
mHandler = new NetworkStatsHandler(handlerThread.getLooper());
mNetworkStatsSubscriptionsMonitor = deps.makeSubscriptionsMonitor(mContext,
- new HandlerExecutor(mHandler), this);
+ mHandler.getLooper(), new HandlerExecutor(mHandler), this);
+ mContentResolver = mContext.getContentResolver();
+ mContentObserver = mDeps.makeContentObserver(mHandler, mSettings,
+ mNetworkStatsSubscriptionsMonitor);
}
/**
@@ -460,11 +468,31 @@
*/
@NonNull
public NetworkStatsSubscriptionsMonitor makeSubscriptionsMonitor(@NonNull Context context,
- @NonNull Executor executor, @NonNull NetworkStatsService service) {
+ @NonNull Looper looper, @NonNull Executor executor,
+ @NonNull NetworkStatsService service) {
// TODO: Update RatType passively in NSS, instead of querying into the monitor
// when forceUpdateIface.
- return new NetworkStatsSubscriptionsMonitor(context, executor, (subscriberId, type) ->
- service.handleOnCollapsedRatTypeChanged());
+ return new NetworkStatsSubscriptionsMonitor(context, looper, executor,
+ (subscriberId, type) -> service.handleOnCollapsedRatTypeChanged());
+ }
+
+ /**
+ * Create a ContentObserver instance which is used to observe settings changes,
+ * and dispatch onChange events on handler thread.
+ */
+ public @NonNull ContentObserver makeContentObserver(@NonNull Handler handler,
+ @NonNull NetworkStatsSettings settings,
+ @NonNull NetworkStatsSubscriptionsMonitor monitor) {
+ return new ContentObserver(handler) {
+ @Override
+ public void onChange(boolean selfChange, @NonNull Uri uri) {
+ if (!settings.getCombineSubtypeEnabled()) {
+ monitor.start();
+ } else {
+ monitor.stop();
+ }
+ }
+ };
}
}
@@ -530,11 +558,14 @@
mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime,
mSettings.getPollInterval(), pollIntent);
- // TODO: listen to settings changed to support dynamically enable/disable.
- // watch for networkType changes
- if (!mSettings.getCombineSubtypeEnabled()) {
- mNetworkStatsSubscriptionsMonitor.start();
- }
+ mContentResolver.registerContentObserver(Settings.Global
+ .getUriFor(Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED),
+ false /* notifyForDescendants */, mContentObserver);
+
+ // Post a runnable on handler thread to call onChange(). It's for getting current value of
+ // NETSTATS_COMBINE_SUBTYPE_ENABLED to decide start or stop monitoring RAT type changes.
+ mHandler.post(() -> mContentObserver.onChange(false, Settings.Global
+ .getUriFor(Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED)));
registerGlobalAlert();
}
@@ -560,6 +591,8 @@
mNetworkStatsSubscriptionsMonitor.stop();
}
+ mContentResolver.unregisterContentObserver(mContentObserver);
+
final long currentTime = mClock.millis();
// persist any pending stats
diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
index a0ab5ea..d202a2a 100644
--- a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
+++ b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
@@ -16,11 +16,14 @@
package com.android.server.net;
+import static android.net.NetworkTemplate.NETWORK_TYPE_5G_NSA;
import static android.net.NetworkTemplate.getCollapsedRatType;
import android.annotation.NonNull;
import android.content.Context;
+import android.os.Looper;
import android.telephony.Annotation;
+import android.telephony.NetworkRegistrationInfo;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
@@ -75,9 +78,9 @@
@NonNull
private final Executor mExecutor;
- NetworkStatsSubscriptionsMonitor(@NonNull Context context, @NonNull Executor executor,
- @NonNull Delegate delegate) {
- super();
+ NetworkStatsSubscriptionsMonitor(@NonNull Context context, @NonNull Looper looper,
+ @NonNull Executor executor, @NonNull Delegate delegate) {
+ super(looper);
mSubscriptionManager = (SubscriptionManager) context.getSystemService(
Context.TELEPHONY_SUBSCRIPTION_SERVICE);
mTeleManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
@@ -97,11 +100,16 @@
if (match != null) continue;
// Create listener for every newly added sub. Also store subscriberId into it to
- // prevent binder call to telephony when querying RAT.
+ // prevent binder call to telephony when querying RAT. If the subscriberId is empty
+ // for any reason, such as SIM PIN locked, skip registration.
+ // SubscriberId will be unavailable again if 1. modem crashed 2. reboot
+ // 3. re-insert SIM. If that happens, the listeners will be eventually synchronized
+ // with active sub list once all subscriberIds are ready.
final String subscriberId = mTeleManager.getSubscriberId(subId);
if (TextUtils.isEmpty(subscriberId)) {
- Log.wtf(NetworkStatsService.TAG,
- "Empty subscriberId for newly added sub: " + subId);
+ Log.d(NetworkStatsService.TAG, "Empty subscriberId for newly added sub "
+ + subId + ", skip listener registration");
+ continue;
}
final RatTypeListener listener =
new RatTypeListener(mExecutor, this, subId, subscriberId);
@@ -110,6 +118,7 @@
// Register listener to the telephony manager that associated with specific sub.
mTeleManager.createForSubscriptionId(subId)
.listen(listener, PhoneStateListener.LISTEN_SERVICE_STATE);
+ Log.d(NetworkStatsService.TAG, "RAT type listener registered for sub " + subId);
}
for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) {
@@ -162,6 +171,7 @@
private void handleRemoveRatTypeListener(@NonNull RatTypeListener listener) {
mTeleManager.createForSubscriptionId(listener.mSubId)
.listen(listener, PhoneStateListener.LISTEN_NONE);
+ Log.d(NetworkStatsService.TAG, "RAT type listener unregistered for sub " + listener.mSubId);
mRatListeners.remove(listener);
// Removal of subscriptions doesn't generate RAT changed event, fire it for every
@@ -195,7 +205,18 @@
@Override
public void onServiceStateChanged(@NonNull ServiceState ss) {
- final int networkType = ss.getDataNetworkType();
+ // In 5G SA (Stand Alone) mode, the primary cell itself will be 5G hence telephony
+ // would report RAT = 5G_NR.
+ // However, in 5G NSA (Non Stand Alone) mode, the primary cell is still LTE and
+ // network allocates a secondary 5G cell so telephony reports RAT = LTE along with
+ // NR state as connected. In such case, attributes the data usage to NR.
+ // See b/160727498.
+ final boolean is5GNsa = (ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE
+ || ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE_CA)
+ && ss.getNrState() == NetworkRegistrationInfo.NR_STATE_CONNECTED;
+
+ final int networkType =
+ (is5GNsa ? NETWORK_TYPE_5G_NSA : ss.getDataNetworkType());
final int collapsedRatType = getCollapsedRatType(networkType);
if (collapsedRatType == mLastCollapsedRatType) return;