Merge "Added video calling data usage per-uid support"
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index 8f2f048..c62593b 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -23,6 +23,7 @@
import android.content.SharedPreferences;
import android.net.LinkProperties;
import android.net.NetworkCapabilities;
+import android.net.NetworkStats;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.AsyncResult;
@@ -3412,9 +3413,16 @@
return this;
}
- public long getVtDataUsage() {
- if (mImsPhone == null) return 0;
- return mImsPhone.getVtDataUsage();
+ /**
+ * Get aggregated video call data usage since boot.
+ * Permissions android.Manifest.permission.READ_NETWORK_USAGE_HISTORY is required.
+ *
+ * @param perUidStats True if requesting data usage per uid, otherwise overall usage.
+ * @return Snapshot of video call data usage
+ */
+ public NetworkStats getVtDataUsage(boolean perUidStats) {
+ if (mImsPhone == null) return null;
+ return mImsPhone.getVtDataUsage(perUidStats);
}
/**
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
index 563252a..4d04d87 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
@@ -16,6 +16,27 @@
package com.android.internal.telephony.imsphone;
+import static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BAIC;
+import static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BAICr;
+import static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BAOC;
+import static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BAOIC;
+import static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BAOICxH;
+import static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BA_ALL;
+import static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BA_MO;
+import static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BA_MT;
+import static com.android.internal.telephony.CommandsInterface.CF_ACTION_DISABLE;
+import static com.android.internal.telephony.CommandsInterface.CF_ACTION_ENABLE;
+import static com.android.internal.telephony.CommandsInterface.CF_ACTION_ERASURE;
+import static com.android.internal.telephony.CommandsInterface.CF_ACTION_REGISTRATION;
+import static com.android.internal.telephony.CommandsInterface.CF_REASON_ALL;
+import static com.android.internal.telephony.CommandsInterface.CF_REASON_ALL_CONDITIONAL;
+import static com.android.internal.telephony.CommandsInterface.CF_REASON_BUSY;
+import static com.android.internal.telephony.CommandsInterface.CF_REASON_NOT_REACHABLE;
+import static com.android.internal.telephony.CommandsInterface.CF_REASON_NO_REPLY;
+import static com.android.internal.telephony.CommandsInterface.CF_REASON_UNCONDITIONAL;
+import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_NONE;
+import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_VOICE;
+
import android.app.Activity;
import android.app.ActivityManagerNative;
import android.app.Notification;
@@ -24,6 +45,7 @@
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.net.NetworkStats;
import android.net.Uri;
import android.os.AsyncResult;
import android.os.Bundle;
@@ -31,14 +53,12 @@
import android.os.Message;
import android.os.PersistableBundle;
import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
import android.os.Registrant;
import android.os.RegistrantList;
import android.os.ResultReceiver;
-import android.os.PowerManager.WakeLock;
import android.os.SystemProperties;
import android.os.UserHandle;
-
-import android.provider.Telephony;
import android.telecom.VideoProfile;
import android.telephony.CarrierConfigManager;
import android.telephony.PhoneNumberUtils;
@@ -55,33 +75,9 @@
import com.android.ims.ImsEcbmStateListener;
import com.android.ims.ImsException;
import com.android.ims.ImsManager;
-import com.android.ims.ImsMultiEndpoint;
import com.android.ims.ImsReasonInfo;
import com.android.ims.ImsSsInfo;
import com.android.ims.ImsUtInterface;
-
-import static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BAOC;
-import static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BAOIC;
-import static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BAOICxH;
-import static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BAIC;
-import static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BAICr;
-import static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BA_ALL;
-import static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BA_MO;
-import static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BA_MT;
-
-import static com.android.internal.telephony.CommandsInterface.CF_ACTION_DISABLE;
-import static com.android.internal.telephony.CommandsInterface.CF_ACTION_ENABLE;
-import static com.android.internal.telephony.CommandsInterface.CF_ACTION_ERASURE;
-import static com.android.internal.telephony.CommandsInterface.CF_ACTION_REGISTRATION;
-import static com.android.internal.telephony.CommandsInterface.CF_REASON_ALL;
-import static com.android.internal.telephony.CommandsInterface.CF_REASON_ALL_CONDITIONAL;
-import static com.android.internal.telephony.CommandsInterface.CF_REASON_NO_REPLY;
-import static com.android.internal.telephony.CommandsInterface.CF_REASON_NOT_REACHABLE;
-import static com.android.internal.telephony.CommandsInterface.CF_REASON_BUSY;
-import static com.android.internal.telephony.CommandsInterface.CF_REASON_UNCONDITIONAL;
-import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_VOICE;
-import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_NONE;
-
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.Call;
import com.android.internal.telephony.CallForwardInfo;
@@ -1642,8 +1638,8 @@
}
@Override
- public long getVtDataUsage() {
- return mCT.getVtDataUsage();
+ public NetworkStats getVtDataUsage(boolean perUidStats) {
+ return mCT.getVtDataUsage(perUidStats);
}
private void updateRoamingState(boolean newRoaming) {
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index f5a95dc..2f30c3e 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -22,8 +22,10 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
+import android.net.NetworkStats;
import android.net.Uri;
import android.os.AsyncResult;
import android.os.Bundle;
@@ -33,15 +35,17 @@
import android.os.Registrant;
import android.os.RegistrantList;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.SystemProperties;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.telecom.ConferenceParticipant;
+import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
import android.telephony.CarrierConfigManager;
import android.telephony.DisconnectCause;
-import android.telephony.PreciseDisconnectCause;
import android.telephony.PhoneNumberUtils;
+import android.telephony.PreciseDisconnectCause;
import android.telephony.Rlog;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
@@ -49,10 +53,10 @@
import android.telephony.ims.ImsServiceProxy;
import android.telephony.ims.feature.ImsFeature;
import android.text.TextUtils;
-import android.util.SparseIntArray;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Pair;
+import android.util.SparseIntArray;
import com.android.ims.ImsCall;
import com.android.ims.ImsCallProfile;
@@ -86,6 +90,7 @@
import com.android.internal.telephony.dataconnection.DataEnabledSettings;
import com.android.internal.telephony.gsm.SuppServiceNotification;
import com.android.internal.telephony.metrics.TelephonyMetrics;
+import com.android.server.net.NetworkStatsService;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -93,6 +98,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Pattern;
/**
@@ -205,6 +211,9 @@
log("onReceive : Updating mAllowEmergencyVideoCalls = " +
mAllowEmergencyVideoCalls);
}
+ } else if (TelecomManager.ACTION_CHANGE_DEFAULT_DIALER.equals(intent.getAction())) {
+ mDefaultDialerUid.set(getPackageUid(context, intent.getStringExtra(
+ TelecomManager.EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME)));
}
}
};
@@ -249,7 +258,11 @@
// Hold aggregated video call data usage for each video call since boot.
// The ImsCall's call id is the key of the map.
private final HashMap<Integer, Long> mVtDataUsageMap = new HashMap<>();
- private volatile long mTotalVtDataUsage = 0;
+
+ private volatile NetworkStats mVtDataUsageSnapshot = null;
+ private volatile NetworkStats mVtDataUsageUidSnapshot = null;
+
+ private final AtomicInteger mDefaultDialerUid = new AtomicInteger(NetworkStats.UID_ALL);
private ImsPhoneConnection mPendingMO;
private int mClirMode = CommandsInterface.CLIR_DEFAULT;
@@ -637,6 +650,7 @@
IntentFilter intentfilter = new IntentFilter();
intentfilter.addAction(ImsManager.ACTION_IMS_INCOMING_CALL);
intentfilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
+ intentfilter.addAction(TelecomManager.ACTION_CHANGE_DEFAULT_DIALER);
mPhone.getContext().registerReceiver(mReceiver, intentfilter);
cacheCarrierConfiguration(mPhone.getSubId());
@@ -644,11 +658,35 @@
this, EVENT_DATA_ENABLED_CHANGED, null);
mImsServiceRetryCount = 0;
+
+ final TelecomManager telecomManager =
+ (TelecomManager) mPhone.getContext().getSystemService(Context.TELECOM_SERVICE);
+ mDefaultDialerUid.set(
+ getPackageUid(mPhone.getContext(), telecomManager.getDefaultDialerPackage()));
+
+ long currentTime = SystemClock.elapsedRealtime();
+ mVtDataUsageSnapshot = new NetworkStats(currentTime, 1);
+ mVtDataUsageUidSnapshot = new NetworkStats(currentTime, 1);
+
// Send a message to connect to the Ims Service and open a connection through
// getImsService().
sendEmptyMessage(EVENT_GET_IMS_SERVICE);
}
+ private int getPackageUid(Context context, String pkg) {
+ if (pkg == null) {
+ return NetworkStats.UID_ALL;
+ }
+
+ int uid = NetworkStats.UID_ALL;
+ try {
+ uid = context.getPackageManager().getPackageUid(pkg, 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ loge("Cannot find package uid. pkg = " + pkg);
+ }
+ return uid;
+ }
+
private PendingIntent createIncomingCallPendingIntent() {
Intent intent = new Intent(ImsManager.ACTION_IMS_INCOMING_CALL);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
@@ -2746,13 +2784,9 @@
ImsCall call = (ImsCall) ar.userObj;
Long usage = (long) ar.result;
log("VT data usage update. usage = " + usage + ", imsCall = " + call);
-
- Long oldUsage = 0L;
- if (mVtDataUsageMap.containsKey(call.uniqueId)) {
- oldUsage = mVtDataUsageMap.get(call.uniqueId);
+ if (usage > 0) {
+ updateVtDataUsage(call, usage);
}
- mTotalVtDataUsage += (usage - oldUsage);
- mVtDataUsageMap.put(call.uniqueId, usage);
break;
case EVENT_DATA_ENABLED_CHANGED:
ar = (AsyncResult) msg.obj;
@@ -2784,6 +2818,50 @@
}
}
+ /**
+ * Update video call data usage
+ *
+ * @param call The IMS call
+ * @param dataUsage The aggregated data usage for the call
+ */
+ private void updateVtDataUsage(ImsCall call, long dataUsage) {
+ long oldUsage = 0L;
+ if (mVtDataUsageMap.containsKey(call.uniqueId)) {
+ oldUsage = mVtDataUsageMap.get(call.uniqueId);
+ }
+
+ long delta = dataUsage - oldUsage;
+ mVtDataUsageMap.put(call.uniqueId, dataUsage);
+
+ log("updateVtDataUsage: call=" + call + ", delta=" + delta);
+
+ long currentTime = SystemClock.elapsedRealtime();
+ int isRoaming = mPhone.getServiceState().getDataRoaming() ? 1 : 0;
+
+ // Create the snapshot of total video call data usage.
+ NetworkStats vtDataUsageSnapshot = new NetworkStats(currentTime, 1);
+ vtDataUsageSnapshot.combineAllValues(mVtDataUsageSnapshot);
+ // Since the modem only reports the total vt data usage rather than rx/tx separately,
+ // the only thing we can do here is splitting the usage into half rx and half tx.
+ // Uid -1 indicates this is for the overall device data usage.
+ vtDataUsageSnapshot.combineValues(new NetworkStats.Entry(
+ NetworkStatsService.VT_INTERFACE, -1, NetworkStats.SET_FOREGROUND,
+ NetworkStats.TAG_NONE, 1, isRoaming, delta / 2, 0, delta / 2, 0, 0));
+ mVtDataUsageSnapshot = vtDataUsageSnapshot;
+
+ // Create the snapshot of video call data usage per dialer. combineValues will create
+ // a separate entry if uid is different from the previous snapshot.
+ NetworkStats vtDataUsageUidSnapshot = new NetworkStats(currentTime, 1);
+ vtDataUsageUidSnapshot.combineAllValues(mVtDataUsageUidSnapshot);
+ // Since the modem only reports the total vt data usage rather than rx/tx separately,
+ // the only thing we can do here is splitting the usage into half rx and half tx.
+ vtDataUsageUidSnapshot.combineValues(new NetworkStats.Entry(
+ NetworkStatsService.VT_INTERFACE, mDefaultDialerUid.get(),
+ NetworkStats.SET_FOREGROUND, NetworkStats.TAG_NONE, 1, isRoaming, delta / 2,
+ 0, delta / 2, 0, 0));
+ mVtDataUsageUidSnapshot = vtDataUsageUidSnapshot;
+ }
+
@Override
protected void log(String msg) {
Rlog.d(LOG_TAG, "[ImsPhoneCallTracker] " + msg);
@@ -2839,10 +2917,9 @@
pw.println(" " + mImsFeatureStrings[i] + ": "
+ ((mImsFeatureEnabled[i]) ? "enabled" : "disabled"));
}
- pw.println(" mTotalVtDataUsage=" + mTotalVtDataUsage);
- for (Map.Entry<Integer, Long> entry : mVtDataUsageMap.entrySet()) {
- pw.println(" id=" + entry.getKey() + " ,usage=" + entry.getValue());
- }
+ pw.println(" mDefaultDialerUid=" + mDefaultDialerUid.get());
+ pw.println(" mVtDataUsageSnapshot=" + mVtDataUsageSnapshot);
+ pw.println(" mVtDataUsageUidSnapshot=" + mVtDataUsageUidSnapshot);
pw.flush();
pw.println("++++++++++++++++++++++++++++++++");
@@ -3082,11 +3159,13 @@
return isActiveCallVideo && isActiveCallOnWifi && isIncomingCallAudio && !isVoWifiEnabled;
}
- /** Get aggregated video call data usage since boot.
+ /**
+ * Get aggregated video call data usage since boot.
*
- * @return data usage in bytes
+ * @param perUidStats True if requesting data usage per uid, otherwise overall usage.
+ * @return Snapshot of video call data usage
*/
- public long getVtDataUsage() {
+ public NetworkStats getVtDataUsage(boolean perUidStats) {
// If there is an ongoing VT call, request the latest VT usage from the modem. The latest
// usage will return asynchronously so it won't be counted in this round, but it will be
@@ -3100,7 +3179,7 @@
}
}
- return mTotalVtDataUsage;
+ return perUidStats ? mVtDataUsageUidSnapshot : mVtDataUsageSnapshot;
}
public void registerPhoneStateListener(PhoneStateListener listener) {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java b/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
index 419e61b..d4718c5 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
@@ -59,6 +59,7 @@
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.provider.Telephony.ServiceStateTable;
+import android.telecom.TelecomManager;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -234,6 +235,8 @@
return mUsageStatManager;
case Context.BATTERY_SERVICE:
return mBatteryManager;
+ case Context.TELECOM_SERVICE:
+ return mTelecomManager;
case Context.DISPLAY_SERVICE:
case Context.POWER_SERVICE:
// PowerManager and DisplayManager are final classes so cannot be mocked,
@@ -492,6 +495,7 @@
private final UsageStatsManager mUsageStatManager = null;
private final WifiManager mWifiManager = mock(WifiManager.class);
private final BatteryManager mBatteryManager = mock(BatteryManager.class);
+ private final TelecomManager mTelecomManager = mock(TelecomManager.class);
private final ContentProvider mContentProvider = spy(new FakeContentProvider());