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

Commit a91ad3e4 authored by Michael W's avatar Michael W
Browse files

SystemUI: NetworkTraffic: Refactor message handling

* In certain network situations (e.g. while changing from wifi to
  cellular) it can happen, that the HashMap is modified while the stats
  are currently being recalculated
* We can prevent this by moving adding and removing of any network
  to the same handler so the callbacks can happen without breaking the
  flow
* Move the existing code in handleMessage into some little helper
  methods so it stays simple and readable

Fixes: https://gitlab.com/LineageOS/issues/android/-/issues/2870
Change-Id: I38c0c27a4f76fab5aeee013beab346c088bbbd59
parent 7fa4c750
Loading
Loading
Loading
Loading
+100 −46
Original line number Diff line number Diff line
@@ -65,6 +65,8 @@ public class NetworkTraffic extends TextView {

    private static final int MESSAGE_TYPE_PERIODIC_REFRESH = 0;
    private static final int MESSAGE_TYPE_UPDATE_VIEW = 1;
    private static final int MESSAGE_TYPE_ADD_NETWORK = 2;
    private static final int MESSAGE_TYPE_REMOVE_NETWORK = 3;

    private static final int REFRESH_INTERVAL = 2000;

@@ -185,10 +187,35 @@ public class NetworkTraffic extends TextView {
    private Handler mTrafficHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MESSAGE_TYPE_PERIODIC_REFRESH:
                    recalculateStats();
                    displayStatsAndReschedule();
                    break;

                case MESSAGE_TYPE_UPDATE_VIEW:
                    displayStatsAndReschedule();
                    break;

                case MESSAGE_TYPE_ADD_NETWORK:
                    final LinkPropertiesHolder lph = (LinkPropertiesHolder) msg.obj;
                    mLinkPropertiesMap.put(lph.getNetwork(), lph.getLinkProperties());
                    mNetworksChanged = true;
                    break;

                case MESSAGE_TYPE_REMOVE_NETWORK:
                    mLinkPropertiesMap.remove((Network) msg.obj);
                    mNetworksChanged = true;
                    break;
            }
        }

        private void recalculateStats() {
            final long now = SystemClock.elapsedRealtime();
            final long timeDelta = now - mLastUpdateTime; /* ms */
            if (msg.what == MESSAGE_TYPE_PERIODIC_REFRESH
                    && timeDelta >= REFRESH_INTERVAL * 0.95f) {
            if (timeDelta < REFRESH_INTERVAL * 0.95f) {
                return;
            }
            // Sum tx and rx bytes from all sources of interest
            long txBytes = 0;
            long rxBytes = 0;
@@ -236,6 +263,7 @@ public class NetworkTraffic extends TextView {
            mLastUpdateTime = now;
        }

        private void displayStatsAndReschedule() {
            final boolean enabled = mMode != MODE_DISABLED && isConnectionAvailable();
            final boolean showUpstream =
                    mMode == MODE_UPSTREAM_ONLY || mMode == MODE_UPSTREAM_AND_DOWNSTREAM;
@@ -478,14 +506,40 @@ public class NetworkTraffic extends TextView {
            new ConnectivityManager.NetworkCallback() {
        @Override
        public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) {
            mLinkPropertiesMap.put(network, linkProperties);
            mNetworksChanged = true;
            Message msg = new Message();
            msg.what = MESSAGE_TYPE_ADD_NETWORK;
            msg.obj = new LinkPropertiesHolder(network, linkProperties);
            mTrafficHandler.sendMessage(msg);
        }

        @Override
        public void onLost(Network network) {
            mLinkPropertiesMap.remove(network);
            mNetworksChanged = true;
            Message msg = new Message();
            msg.what = MESSAGE_TYPE_REMOVE_NETWORK;
            msg.obj = network;
            mTrafficHandler.sendMessage(msg);
        }
    };

    private class LinkPropertiesHolder {
        private Network mNetwork;
        private LinkProperties mLinkProperties;

        public LinkPropertiesHolder(Network network, LinkProperties linkProperties) {
            mNetwork = network;
            mLinkProperties = linkProperties;
        }

        public LinkPropertiesHolder(Network network) {
            mNetwork = network;
        }

        public Network getNetwork() {
            return mNetwork;
        }

        public LinkProperties getLinkProperties() {
            return mLinkProperties;
        }
    }
}