Dialer: Recording data usage for video call

Add a new feature for recording video call data usage.
Call NetworkstatsService API to record the total video
call data usage at the end of a video call.

Change-Id: If569e5e62b2c9926a29add655610347aa72fc4ab
CRs-Fixed: 1039373
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 70493df..b87e31f 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -61,6 +61,8 @@
     <uses-permission android:name="android.permission.BROADCAST_STICKY" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
     <!-- This tells the activity manager to not delay any of our activity
      start requests, even if they happen immediately after the user
      presses home. -->
diff --git a/InCallUI/src/com/android/incallui/InCallMessageController.java b/InCallUI/src/com/android/incallui/InCallMessageController.java
index d019f6b..aa5a57e 100644
--- a/InCallUI/src/com/android/incallui/InCallMessageController.java
+++ b/InCallUI/src/com/android/incallui/InCallMessageController.java
@@ -30,7 +30,16 @@
 
 import android.content.Context;
 import android.content.res.Resources;
+import android.net.ConnectivityManager;
+import android.net.IConnectivityManager;
+import android.net.INetworkStatsService;
+import android.net.LinkProperties;
+import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
+import android.net.NetworkState;
 import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.ServiceManager;
 
 import com.android.incallui.InCallPresenter.InCallDetailsListener;
 import com.android.incallui.InCallVideoCallCallbackNotifier.VideoEventListener;
@@ -51,6 +60,11 @@
         CallList.Listener, SessionModificationListener, InCallSessionModificationCauseListener,
         InCallDetailsListener {
 
+    private INetworkStatsService mStatsService;
+    private IConnectivityManager mConnManager;
+    private long previousLteUsage;
+    private long previousWlanUsage;
+
     private static InCallMessageController sInCallMessageController;
 
     private PrimaryCallTracker mPrimaryCallTracker;
@@ -78,6 +92,10 @@
         InCallPresenter.getInstance().addListener(mPrimaryCallTracker);
         InCallVideoCallCallbackNotifier.getInstance().addSessionModificationListener(this);
         InCallPresenter.getInstance().addDetailsListener(this);
+        mStatsService = INetworkStatsService.Stub.asInterface(
+                ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
+        mConnManager = IConnectivityManager.Stub.asInterface(
+                ServiceManager.getService(Context.CONNECTIVITY_SERVICE));
     }
 
     /**
@@ -95,6 +113,10 @@
         InCallVideoCallCallbackNotifier.getInstance().removeSessionModificationListener(this);
         InCallPresenter.getInstance().removeDetailsListener(this);
         mPrimaryCallTracker = null;
+        mStatsService = null;
+        mConnManager = null;
+        previousLteUsage = 0;
+        previousWlanUsage = 0;
     }
 
     /**
@@ -223,6 +245,12 @@
         Log.i(this, "onDetailsChanged LTE data value = " + lteUsage + " WiFi data value = " +
                 wlanUsage);
 
+        if (mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_video_call_datausage_enable)) {
+            recordDataUsage(lteUsage, wlanUsage);
+        }
+
+
         if (QtiImsExtUtils.isCarrierConfigEnabled(mContext,
                 QtiCarrierConfigs.SHOW_DATA_USAGE_TOAST)) {
             final String dataUsageChangedText = mContext.getResources().getString(
@@ -397,4 +425,97 @@
                 break;
         }
     }
+
+     /**
+      * This method is used to ignore the repeatly calling onDetailsChanged
+      */
+     private boolean hasDataUsageChanged(long lteUsage, long wlanUsage) {
+         boolean hasChanged = false;
+         if (previousLteUsage != lteUsage) {
+             hasChanged = true;
+             previousLteUsage = lteUsage;
+         }
+         if (previousWlanUsage != wlanUsage) {
+             hasChanged = true;
+             previousWlanUsage = wlanUsage;
+         }
+         return hasChanged;
+     }
+
+     private void recordDataUsage(long lteUsage, long wlanUsage) {
+         String wifiIface;
+         String imsIface;
+         if(!hasDataUsageChanged(lteUsage, wlanUsage)) {
+             return;
+         }
+
+         if (wlanUsage != 0) {
+             wifiIface = getWifiIface();
+             if (wifiIface != null)
+                 recordUsage(wifiIface, ConnectivityManager.TYPE_WIFI, wlanUsage, 0);
+         }
+
+         if (lteUsage != 0 ) {
+             imsIface = getImsIface();
+             if (imsIface != null)
+                 recordUsage(imsIface, ConnectivityManager.TYPE_MOBILE, lteUsage, 0);
+         }
+     }
+
+     private void recordUsage(String ifaces, int ifaceType, long rx, long tx) {
+         if (ifaces == null) {
+             Log.d(this, "recordDataUseage ifaces is null");
+             return;
+         }
+         Log.d(this,"recordDataUseage ifaces ="+ ifaces + "   ifaceType=" + ifaceType +
+                 "rx = " + rx + " tx =" + tx);
+
+         try {
+             mStatsService.recordVideoCallData(ifaces, ifaceType, rx, tx);
+         } catch (RuntimeException e) {
+             Log.e(this, "recordDataUseage RuntimeException" + e);
+         } catch (RemoteException e) {
+             Log.e(this, "recordDataUseage RemoteException" + e);
+         }
+     }
+
+    private String getImsIface() {
+        final NetworkState[] states;
+        try {
+            states = mConnManager.getAllNetworkState();
+        } catch (RemoteException e) {
+            Log.e(this, "getVoiceCallIfaces RemoteException" + e);
+            return null;
+        }
+
+        if (states != null) {
+            for (NetworkState state : states) {
+                if (state.networkInfo.isConnected() && state.networkCapabilities.hasCapability(
+                        NetworkCapabilities.NET_CAPABILITY_IMS)) {
+                    final boolean isMobile = ConnectivityManager.isNetworkTypeMobile(
+                            state.networkInfo.getType());
+                    final String baseIface = state.linkProperties.getInterfaceName();
+                    if (isMobile)
+                        return baseIface;
+                }
+            }
+        }
+        return null;
+    }
+
+    private String getWifiIface() {
+        final LinkProperties wifiLinkProperties;
+        try {
+            wifiLinkProperties =
+                    mConnManager.getLinkPropertiesForType(ConnectivityManager.TYPE_WIFI);
+            if (wifiLinkProperties != null) {
+                return wifiLinkProperties.getInterfaceName();
+            }
+        } catch (RemoteException e) {
+            Log.e(this, "get wifi Iface RemoteException" + e);
+        }
+        return null;
+    }
+
+
 }