diff --git a/sdk/src/java/org/lineageos/internal/statusbar/NetworkTraffic.java b/sdk/src/java/org/lineageos/internal/statusbar/NetworkTraffic.java index 02853d0f..f03b96ed 100644 --- a/sdk/src/java/org/lineageos/internal/statusbar/NetworkTraffic.java +++ b/sdk/src/java/org/lineageos/internal/statusbar/NetworkTraffic.java @@ -1,5 +1,5 @@ /** - * Copyright (C) 2017-2018 The LineageOS project + * Copyright (C) 2017-2019 The LineageOS project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,6 +28,10 @@ import android.graphics.drawable.Drawable; import android.graphics.PorterDuff; import android.graphics.Rect; import android.net.ConnectivityManager; +import android.net.LinkProperties; +import android.net.Network; +import android.net.NetworkCapabilities; +import android.net.NetworkRequest; import android.net.TrafficStats; import android.os.Handler; import android.os.UserHandle; @@ -43,9 +47,13 @@ import lineageos.providers.LineageSettings; import org.lineageos.platform.internal.R; +import java.util.HashMap; + public class NetworkTraffic extends TextView { private static final String TAG = "NetworkTraffic"; + private static final boolean DEBUG = false; + private static final int MODE_DISABLED = 0; private static final int MODE_UPSTREAM_ONLY = 1; private static final int MODE_DOWNSTREAM_ONLY = 2; @@ -71,8 +79,8 @@ public class NetworkTraffic extends TextView { private boolean mNetworkTrafficIsVisible; private long mTxKbps; private long mRxKbps; - private long mLastTxBytesTotal; - private long mLastRxBytesTotal; + private long mLastTxBytes; + private long mLastRxBytes; private long mLastUpdateTime; private int mTextSizeSingle; private int mTextSizeMulti; @@ -86,6 +94,22 @@ public class NetworkTraffic extends TextView { private SettingsObserver mObserver; private Drawable mDrawable; + // Network tracking related variables + final private ConnectivityManager mConnectivityManager; + final private HashMap mNetworkMap = new HashMap<>(); + private boolean mNetworksChanged = true; + + public class NetworkState { + public NetworkCapabilities mNetworkCapabilities; + public LinkProperties mLinkProperties; + + public NetworkState(NetworkCapabilities networkCapabilities, + LinkProperties linkProperties) { + mNetworkCapabilities = networkCapabilities; + mLinkProperties = linkProperties; + } + }; + public NetworkTraffic(Context context) { this(context, null); } @@ -104,6 +128,13 @@ public class NetworkTraffic extends TextView { mNetworkTrafficIsVisible = false; mObserver = new SettingsObserver(mTrafficHandler); + + mConnectivityManager = getContext().getSystemService(ConnectivityManager.class); + final NetworkRequest request = new NetworkRequest.Builder() + .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) + .build(); + mConnectivityManager.registerNetworkCallback(request, mNetworkCallback); } private LineageStatusBarItem.DarkReceiver mDarkReceiver = @@ -154,18 +185,40 @@ public class NetworkTraffic extends TextView { private Handler mTrafficHandler = new Handler() { @Override public void handleMessage(Message msg) { - long now = SystemClock.elapsedRealtime(); - long timeDelta = now - mLastUpdateTime; + final long now = SystemClock.elapsedRealtime(); + final long timeDelta = now - mLastUpdateTime; /* ms */ if (msg.what == MESSAGE_TYPE_PERIODIC_REFRESH && timeDelta >= REFRESH_INTERVAL * 0.95f) { // Update counters + long txBytes = 0; + long rxBytes = 0; + // Sum stats from interfaces of interest + for (NetworkState state : mNetworkMap.values()) { + final String iface = state.mLinkProperties.getInterfaceName(); + if (iface == null) { + continue; + } + if (DEBUG) { + Log.d(TAG, "adding stats from interface " + iface); + } + txBytes += TrafficStats.getTxBytes(iface); + rxBytes += TrafficStats.getRxBytes(iface); + } + + final long txBytesDelta = txBytes - mLastTxBytes; + final long rxBytesDelta = rxBytes - mLastRxBytes; + + if (!mNetworksChanged && timeDelta > 0 && txBytesDelta >= 0 && rxBytesDelta >= 0) { + mTxKbps = (long) (txBytesDelta * 8f / 1000f / (timeDelta / 1000f)); + mRxKbps = (long) (rxBytesDelta * 8f / 1000f / (timeDelta / 1000f)); + } else if (mNetworksChanged) { + mTxKbps = 0; + mRxKbps = 0; + mNetworksChanged = false; + } + mLastTxBytes = txBytes; + mLastRxBytes = rxBytes; mLastUpdateTime = now; - long txBytes = TrafficStats.getTotalTxBytes() - mLastTxBytesTotal; - long rxBytes = TrafficStats.getTotalRxBytes() - mLastRxBytesTotal; - mTxKbps = (long) (txBytes * 8f / (timeDelta / 1000f) / 1000f); - mRxKbps = (long) (rxBytes * 8f / (timeDelta / 1000f) / 1000f); - mLastTxBytesTotal += txBytes; - mLastRxBytesTotal += rxBytes; } final boolean enabled = mMode != MODE_DISABLED && isConnectionAvailable(); @@ -366,4 +419,41 @@ public class NetworkTraffic extends TextView { mDrawable.setColorFilter(mIconTint, PorterDuff.Mode.MULTIPLY); } } + + private ConnectivityManager.NetworkCallback mNetworkCallback = + new ConnectivityManager.NetworkCallback() { + @Override + public void onAvailable(Network network) { + mNetworkMap.put(network, + new NetworkState(mConnectivityManager.getNetworkCapabilities(network), + mConnectivityManager.getLinkProperties(network))); + mNetworksChanged = true; + } + + @Override + public void onCapabilitiesChanged(Network network, + NetworkCapabilities networkCapabilities) { + if (mNetworkMap.containsKey(network)) { + mNetworkMap.put(network, new NetworkState(networkCapabilities, + mConnectivityManager.getLinkProperties(network))); + mNetworksChanged = true; + } + } + + @Override + public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) { + if (mNetworkMap.containsKey(network)) { + mNetworkMap.put(network, + new NetworkState(mConnectivityManager.getNetworkCapabilities(network), + linkProperties)); + mNetworksChanged = true; + } + } + + @Override + public void onLost(Network network) { + mNetworkMap.remove(network); + mNetworksChanged = true; + } + }; }