[SM02] Support record mobile network stats by collapsed rat type am: 825f0828ac am: ad8e8bddfe

Change-Id: I10acd170e902344b1b9063fe2a4da60c5d037e5d
This commit is contained in:
junyulai
2020-03-19 06:53:35 +00:00
committed by Automerger Merge Worker
3 changed files with 134 additions and 10 deletions

View File

@@ -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;
@@ -42,11 +43,8 @@ public class NetworkIdentity implements Comparable<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
// TODO: make this flag configurable through settings. See http://b/146415925
public static final boolean COMBINE_SUBTYPE_ENABLED = true;
public static final int SUBTYPE_COMBINED = -1;
@@ -187,13 +185,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;

View File

@@ -37,6 +37,7 @@ import static android.net.wifi.WifiInfo.sanitizeSsid;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.TelephonyManager;
import android.util.BackupUtils;
import android.util.Log;
@@ -394,6 +395,45 @@ public class NetworkTemplate implements Parcelable {
}
}
/**
* 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;
}
}
/**
* Check if matches Wi-Fi network template.
*/

View File

@@ -27,6 +27,8 @@ 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.COMBINE_SUBTYPE_ENABLED;
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,6 +47,7 @@ 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;
@@ -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;
@@ -280,6 +291,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 +371,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 +429,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 +509,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime,
mSettings.getPollInterval(), pollIntent);
// TODO: listen to changes from all subscriptions.
// watch for networkType changes
if (!COMBINE_SUBTYPE_ENABLED) {
mTeleManager.listen(mPhoneListener, LISTEN_SERVICE_STATE);
}
registerGlobalAlert();
}
@@ -506,6 +535,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
mContext.unregisterReceiver(mUserReceiver);
mContext.unregisterReceiver(mShutdownReceiver);
if (!COMBINE_SUBTYPE_ENABLED) {
mTeleManager.listen(mPhoneListener, LISTEN_NONE);
}
final long currentTime = mClock.millis();
// persist any pending stats
@@ -1156,6 +1189,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 (LOGV) {
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), SECOND_IN_MILLIS);
}
}
private void updateIfaces(
Network[] defaultNetworks,
NetworkState[] networkStates,
@@ -1177,7 +1242,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 +1263,16 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
mDefaultNetworks = defaultNetworks;
}
mLastNetworkStates = states;
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 = 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 +1333,22 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
mMobileIfaces = mobileIfaces.toArray(new String[mobileIfaces.size()]);
}
/**
* If combine subtype is not enabled. For networks with {@code TRANSPORT_CELLULAR}, get
* subType that 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 (COMBINE_SUBTYPE_ENABLED) return SUBTYPE_COMBINED;
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);