Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2f14f544 authored by Jack Yu's avatar Jack Yu
Browse files

Added video calling data usage per-uid support

Now the VT call data usage will be counted under
current dialer's data usage as well as the total
device data usage.

Test: Manual
bug: 37671326

Merged-Id: Ic7a87bf816bb12f1be9d66ee9aafb54174df0235
Change-Id: Ic7a87bf816bb12f1be9d66ee9aafb54174df0235
parent 0886e96a
Loading
Loading
Loading
Loading
+11 −3
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.content.IntentFilter;
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 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
        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);
    }

    /**
+25 −29
Original line number Diff line number Diff line
@@ -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.app.PendingIntent;
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.Handler;
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.ImsEcbm;
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 @@ public class ImsPhone extends ImsPhoneBase {
    }

    @Override
    public long getVtDataUsage() {
        return mCT.getVtDataUsage();
    public NetworkStats getVtDataUsage(boolean perUidStats) {
        return mCT.getVtDataUsage(perUidStats);
    }

    private void updateRoamingState(boolean newRoaming) {
+96 −17
Original line number Diff line number Diff line
@@ -22,8 +22,10 @@ import android.content.Context;
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.PersistableBundle;
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.TelephonyManager;
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.TelephonyProto.TelephonyCallSession.Event.
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.ArrayList;
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 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
                    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 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
    // 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 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
        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 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
                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 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
                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 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
        }
    }

    /**
     * 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 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
            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 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
        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 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
            }
        }

        return mTotalVtDataUsage;
        return perUidStats ? mVtDataUsageUidSnapshot : mVtDataUsageSnapshot;
    }

    public void registerPhoneStateListener(PhoneStateListener listener) {
+4 −0
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ import android.os.UserManager;
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 @@ public class ContextFixture implements TestFixture<Context> {
                    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 @@ public class ContextFixture implements TestFixture<Context> {
    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());