SystemUI: Show daily data usage in QS footer

Author: Adithya <gh0strider.2k18.reborn@gmail.com>
Date:   Fri Sep 10 14:20:54 2021 +0530

    SystemUI: Show daily data usage in QS footer

     * Refactor existing build text view
     * Adapt to T

    Squashed:

     * SettingsLib: Add method to get daily data usage
     * SystemUI: Show wifi usage in QS footer when available
     * SystemUI: Move QS page indicator to the right

    Change-Id: Ifcd39167e6522935a8a29dc89d7e5f415893d266
    Signed-off-by: Adithya R <gh0strider.2k18.reborn@gmail.com>

Author: Adithya R <gh0strider.2k18.reborn@gmail.com>
Date:   Thu Sep 29 00:49:35 2022 +0530

    SystemUI: Hide QS data usage if no wifi/sims

    Instead of showing dummy text like '0 B used today'.

    Change-Id: I066751ad7f791e2efcaab43a20b6228f144d0c0d

Author: Adithya R <gh0strider.2k18.reborn@gmail.com>
Date:   Tue Oct 11 01:00:28 2022 +0530

    SystemUI: Avoid NPE in QS footer data usage

    In some rare cases, can hit this NPE.

    10-09 12:32:52.244  2316  2316 E AndroidRuntime: FATAL EXCEPTION: main
    10-09 12:32:52.244  2316  2316 E AndroidRuntime: Process: com.android.systemui, PID: 2316
    10-09 12:32:52.244  2316  2316 E AndroidRuntime: java.lang.NullPointerException: Attempt to get length of null array
    10-09 12:32:52.244  2316  2316 E AndroidRuntime:        at java.util.Set.of(Set.java:692)
    10-09 12:32:52.244  2316  2316 E AndroidRuntime:        at com.android.settingslib.net.DataUsageUtils.getNormalizedMobileTemplate(DataUsageUtils.java:67)
    10-09 12:32:52.244  2316  2316 E AndroidRuntime:        at com.android.settingslib.net.DataUsageUtils.getMobileTemplate(DataUsageUtils.java:57)
    10-09 12:32:52.244  2316  2316 E AndroidRuntime:        at com.android.settingslib.net.DataUsageController.getDailyDataUsageInfo(DataUsageController.java:109)
    10-09 12:32:52.244  2316  2316 E AndroidRuntime:        at com.android.systemui.qs.QSFooterView.setUsageText(QSFooterView.java:117)
    10-09 12:32:52.244  2316  2316 E AndroidRuntime:        at com.android.systemui.qs.QSFooterView.setNoSims(QSFooterView.java:184)
    10-09 12:32:52.244  2316  2316 E AndroidRuntime:        at com.android.systemui.qs.QSFooterViewController$2.setNoSims(QSFooterViewController.java:73)
    10-09 12:32:52.244  2316  2316 E AndroidRuntime:        at com.android.systemui.statusbar.connectivity.CallbackHandler.handleMessage(CallbackHandler.java:84)
    10-09 12:32:52.244  2316  2316 E AndroidRuntime:        at android.os.Handler.dispatchMessage(Handler.java:106)
    10-09 12:32:52.244  2316  2316 E AndroidRuntime:        at android.os.Looper.loopOnce(Looper.java:201)
    10-09 12:32:52.244  2316  2316 E AndroidRuntime:        at android.os.Looper.loop(Looper.java:288)
    10-09 12:32:52.244  2316  2316 E AndroidRuntime:        at android.app.ActivityThread.main(ActivityThread.java:7898)
    10-09 12:32:52.244  2316  2316 E AndroidRuntime:        at java.lang.reflect.Method.invoke(Native Method)
    10-09 12:32:52.244  2316  2316 E AndroidRuntime:        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
    10-09 12:32:52.244  2316  2316 E AndroidRuntime:        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)

    Change-Id: Ib5ab5da259a80b7f1e3a12b0c8a5078eb976fd20

Co-authored-by: AnkitGourav <Ankitgourav035@gmail.com>
Co-authored-by: Anushek Prasal <anushekprasal@gmail.com>
Co-authored-by: Jyotiraditya Panda <jyotiraditya@aospa.co>
Change-Id: I316b2a2cbdd69307cacd444bb6100c5c7dc56af4
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
index d088c3b..0c4e9c6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
@@ -26,6 +26,7 @@
 import android.net.NetworkPolicy;
 import android.net.NetworkPolicyManager;
 import android.net.NetworkTemplate;
+import android.net.wifi.WifiManager;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.text.format.DateUtils;
@@ -39,6 +40,7 @@
 import java.time.ZonedDateTime;
 import java.util.Iterator;
 import java.util.Locale;
+import java.util.Set;
 
 public class DataUsageController {
 
@@ -52,6 +54,7 @@
     private final Context mContext;
     private final NetworkPolicyManager mPolicyManager;
     private final NetworkStatsManager mNetworkStatsManager;
+    private final WifiManager mWifiManager;
 
     private Callback mCallback;
     private NetworkNameProvider mNetworkController;
@@ -61,6 +64,7 @@
         mContext = context;
         mPolicyManager = NetworkPolicyManager.from(mContext);
         mNetworkStatsManager = context.getSystemService(NetworkStatsManager.class);
+        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
         mSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
     }
 
@@ -94,6 +98,42 @@
         return null;
     }
 
+    public DataUsageInfo getDataUsageInfo() {
+        NetworkTemplate template = DataUsageUtils.getMobileTemplate(mContext, mSubscriptionId);
+
+        return getDataUsageInfo(template);
+    }
+
+    public DataUsageInfo getDailyDataUsageInfo() {
+        NetworkTemplate template = DataUsageUtils.getMobileTemplate(mContext, mSubscriptionId);
+
+        return getDailyDataUsageInfo(template);
+    }
+
+    public DataUsageInfo getWifiDataUsageInfo() {
+        return getWifiDataUsageInfo(false);
+    }
+
+    public DataUsageInfo getWifiDataUsageInfo(boolean currentNetwork) {
+        return getDataUsageInfo(getWifiNetworkTemplate(currentNetwork));
+    }
+
+    public DataUsageInfo getWifiDailyDataUsageInfo(boolean currentNetwork) {
+        return getDailyDataUsageInfo(getWifiNetworkTemplate(currentNetwork));
+    }
+
+    public NetworkTemplate getWifiNetworkTemplate(boolean currentNetwork) {
+        final NetworkTemplate.Builder builder =
+                new NetworkTemplate.Builder(NetworkTemplate.MATCH_WIFI);
+        if (currentNetwork) {
+            final String networkKey = mWifiManager.getConnectionInfo().getNetworkKey();
+            if (networkKey != null) {
+                builder.setWifiNetworkKeys(Set.of(networkKey));
+            }
+        }
+        return builder.build();
+    }
+
     public DataUsageInfo getDataUsageInfo(NetworkTemplate template) {
         final NetworkPolicy policy = findNetworkPolicy(template);
         final long now = System.currentTimeMillis();
@@ -131,6 +171,34 @@
         return usage;
     }
 
+    public DataUsageInfo getDailyDataUsageInfo(NetworkTemplate template) {
+        final NetworkPolicy policy = findNetworkPolicy(template);
+        final long end = System.currentTimeMillis();
+        long start = end - DataUsageUtils.getTodayMillis();
+
+        final long totalBytes = getUsageLevel(template, start, end);
+        if (totalBytes < 0L) {
+            return warn("no entry data");
+        }
+        final DataUsageInfo usage = new DataUsageInfo();
+        usage.startDate = start;
+        usage.usageLevel = totalBytes;
+        usage.period = formatDateRange(start, end);
+        usage.cycleStart = start;
+        usage.cycleEnd = end;
+
+        if (policy != null) {
+            usage.limitLevel = policy.limitBytes > 0 ? policy.limitBytes : 0;
+            usage.warningLevel = policy.warningBytes > 0 ? policy.warningBytes : 0;
+        } else {
+            usage.warningLevel = getDefaultWarningLevel();
+        }
+        if (usage != null && mNetworkController != null) {
+            usage.carrier = mNetworkController.getMobileDataNetworkName();
+        }
+        return usage;
+    }
+
     /**
      * Get the total usage level recorded in the network history
      * @param template the network template to retrieve the network history
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
new file mode 100644
index 0000000..bfb31e0
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.net;
+
+import android.content.Context;
+import android.net.NetworkStats;
+import android.net.NetworkTemplate;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.text.format.Time;
+import android.util.Log;
+
+import com.android.internal.util.ArrayUtils;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Utils class for data usage
+ */
+public class DataUsageUtils {
+    private static final String TAG = "DataUsageUtils";
+
+    /**
+     * Return mobile NetworkTemplate based on {@code subId}
+     */
+    public static NetworkTemplate getMobileTemplate(Context context, int subId) {
+        final TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class);
+        final int mobileDefaultSubId = telephonyManager.getSubscriptionId();
+
+        final SubscriptionManager subscriptionManager =
+                context.getSystemService(SubscriptionManager.class);
+        final List<SubscriptionInfo> subInfoList =
+                subscriptionManager.getAvailableSubscriptionInfoList();
+        if (subInfoList == null) {
+            Log.i(TAG, "Subscription is not inited: " + subId);
+            return getMobileTemplateForSubId(telephonyManager, mobileDefaultSubId);
+        }
+
+        for (SubscriptionInfo subInfo : subInfoList) {
+            if ((subInfo != null) && (subInfo.getSubscriptionId() == subId)) {
+                return getNormalizedMobileTemplate(telephonyManager, subId);
+            }
+        }
+        Log.i(TAG, "Subscription is not active: " + subId);
+        return getMobileTemplateForSubId(telephonyManager, mobileDefaultSubId);
+    }
+
+    private static NetworkTemplate getNormalizedMobileTemplate(
+            TelephonyManager telephonyManager, int subId) {
+        final NetworkTemplate mobileTemplate = getMobileTemplateForSubId(telephonyManager, subId);
+        final String[] mergedSubscriberIds = telephonyManager
+                .createForSubscriptionId(subId).getMergedImsisFromGroup();
+        if (ArrayUtils.isEmpty(mergedSubscriberIds)) {
+            Log.i(TAG, "mergedSubscriberIds is null.");
+            return mobileTemplate;
+        }
+
+        return normalizeMobileTemplate(mobileTemplate, Set.of(mergedSubscriberIds));
+    }
+
+    private static NetworkTemplate normalizeMobileTemplate(
+            NetworkTemplate template, Set<String> mergedSet) {
+        if (template.getSubscriberIds().isEmpty()) return template;
+        // The input template should have at most 1 subscriberId.
+        final String subscriberId = template.getSubscriberIds().iterator().next();
+
+        if (mergedSet.contains(subscriberId)) {
+            // Requested template subscriber is part of the merge group; return
+            // a template that matches all merged subscribers.
+            return new NetworkTemplate.Builder(template.getMatchRule())
+                    .setSubscriberIds(mergedSet)
+                    .setWifiNetworkKeys(template.getWifiNetworkKeys())
+                    .setMeteredness(NetworkStats.METERED_YES).build();
+        }
+
+        return template;
+    }
+
+    private static NetworkTemplate getMobileTemplateForSubId(
+            TelephonyManager telephonyManager, int subId) {
+        // Create template that matches any mobile network when the subscriberId is null.
+        String subscriberId = telephonyManager.getSubscriberId(subId);
+        return subscriberId != null
+                ? new NetworkTemplate.Builder(NetworkTemplate.MATCH_CARRIER)
+                .setSubscriberIds(Set.of(subscriberId))
+                .setMeteredness(NetworkStats.METERED_YES)
+                .build()
+                : new NetworkTemplate.Builder(NetworkTemplate.MATCH_MOBILE)
+                        .setMeteredness(NetworkStats.METERED_YES)
+                        .build();
+    }
+
+    /**
+     * Returns today's passed time in Millisecond
+     */
+    public static long getTodayMillis() {
+        final long passedMillis;
+        Time time = new Time();
+        time.set(System.currentTimeMillis());
+        passedMillis = ((time.hour * 60 * 60) + (time.minute * 60) + time.second) * 1000;
+        return passedMillis;
+    }
+}
diff --git a/packages/SystemUI/res/values/leaf_strings.xml b/packages/SystemUI/res/values/leaf_strings.xml
index 04dc126..288d919 100644
--- a/packages/SystemUI/res/values/leaf_strings.xml
+++ b/packages/SystemUI/res/values/leaf_strings.xml
@@ -25,4 +25,9 @@
         <item quantity="one">%d device connected</item>
         <item quantity="other">%d devices connected</item>
     </plurals>
+
+     <!-- Data usage info in QS footer -->
+    <string name="usage_data">used today</string>
+    <string name="usage_data_default_suffix">Data</string>
+    <string name="usage_wifi_default_suffix">Wi-Fi</string>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java
index c908e6e..b335640 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java
@@ -21,12 +21,23 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.database.ContentObserver;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
 import android.net.Uri;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
 import android.os.Build;
 import android.os.Handler;
 import android.os.UserHandle;
 import android.provider.Settings;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.text.BidiFormatter;
+import android.text.format.Formatter;
+import android.text.format.Formatter.BytesResult;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.View;
 import android.widget.FrameLayout;
 import android.widget.TextView;
@@ -35,15 +46,20 @@
 import androidx.annotation.VisibleForTesting;
 
 import com.android.settingslib.development.DevelopmentSettingsEnabler;
+import com.android.settingslib.net.DataUsageController;
 import com.android.systemui.res.R;
 
+import java.util.List;
+
 /**
  * Footer of expanded Quick Settings, tiles page indicator, (optionally) build number and
  * {@link FooterActionsView}
  */
 public class QSFooterView extends FrameLayout {
+    private static final String TAG = "QSFooterView";
+
     private PageIndicator mPageIndicator;
-    private TextView mBuildText;
+    private TextView mUsageText;
     private View mEditButton;
 
     @Nullable
@@ -53,51 +69,119 @@
     private boolean mExpanded;
     private float mExpansionAmount;
 
-    private boolean mShouldShowBuildText;
+    private boolean mShouldShowUsageText;
 
     @Nullable
     private OnClickListener mExpandClickListener;
 
-    private final ContentObserver mDeveloperSettingsObserver = new ContentObserver(
-            new Handler(mContext.getMainLooper())) {
-        @Override
-        public void onChange(boolean selfChange, Uri uri) {
-            super.onChange(selfChange, uri);
-            setBuildText();
-        }
-    };
+    private DataUsageController mDataController;
+    private SubscriptionManager mSubManager;
+
+    private boolean mHasNoSims;
+    private boolean mIsWifiConnected;
+    private String mWifiSsid;
 
     public QSFooterView(Context context, AttributeSet attrs) {
         super(context, attrs);
+        mDataController = new DataUsageController(context);
+        mSubManager = (SubscriptionManager) context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
     }
 
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
         mPageIndicator = findViewById(R.id.footer_page_indicator);
-        mBuildText = findViewById(R.id.build);
+        mUsageText = findViewById(R.id.build);
         mEditButton = findViewById(android.R.id.edit);
 
         updateResources();
         setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
-        setBuildText();
+        setUsageText();
     }
 
-    private void setBuildText() {
-        if (mBuildText == null) return;
-        if (DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)) {
-            mBuildText.setText(mContext.getString(
-                    com.android.internal.R.string.bugreport_status,
-                    Build.VERSION.RELEASE_OR_CODENAME,
-                    Build.ID));
-            // Set as selected for marquee before its made visible, then it won't be announced when
-            // it's made visible.
-            mBuildText.setSelected(true);
-            mShouldShowBuildText = true;
+    private void setUsageText() {
+        if (mUsageText == null || !mExpanded) return;
+        DataUsageController.DataUsageInfo info;
+        String suffix;
+        if (mIsWifiConnected) {
+            info = mDataController.getWifiDailyDataUsageInfo(true);
+            if (info == null) {
+                info = mDataController.getWifiDailyDataUsageInfo(false);
+                suffix = mContext.getResources().getString(R.string.usage_wifi_default_suffix);
+            } else {
+                suffix = getWifiSsid();
+            }
+        } else if (!mHasNoSims) {
+            mDataController.setSubscriptionId(
+                    SubscriptionManager.getDefaultDataSubscriptionId());
+            info = mDataController.getDailyDataUsageInfo();
+            suffix = getSlotCarrierName();
         } else {
-            mBuildText.setText(null);
-            mShouldShowBuildText = false;
-            mBuildText.setSelected(false);
+            mShouldShowUsageText = false;
+            mUsageText.setText(null);
+            updateVisibilities();
+            return;
+        }
+        if (info == null) {
+            Log.w(TAG, "setUsageText: DataUsageInfo is NULL.");
+            return;
+        }
+        mShouldShowUsageText = true;
+        mUsageText.setText(formatDataUsage(info.usageLevel) + " " +
+                mContext.getResources().getString(R.string.usage_data) +
+                " (" + suffix + ")");
+        updateVisibilities();
+    }
+
+    private CharSequence formatDataUsage(long byteValue) {
+        final BytesResult res = Formatter.formatBytes(mContext.getResources(), byteValue,
+                Formatter.FLAG_IEC_UNITS);
+        return BidiFormatter.getInstance().unicodeWrap(mContext.getString(
+                com.android.internal.R.string.fileSizeSuffix, res.value, res.units));
+    }
+
+    private String getSlotCarrierName() {
+        CharSequence result = mContext.getResources().getString(R.string.usage_data_default_suffix);
+        int subId = mSubManager.getDefaultDataSubscriptionId();
+        final List<SubscriptionInfo> subInfoList =
+                mSubManager.getActiveSubscriptionInfoList(true);
+        if (subInfoList != null) {
+            for (SubscriptionInfo subInfo : subInfoList) {
+                if (subId == subInfo.getSubscriptionId()) {
+                    result = subInfo.getDisplayName();
+                    break;
+                }
+            }
+        }
+        return result.toString();
+    }
+
+    private String getWifiSsid() {
+        if (mWifiSsid == null) {
+            return mContext.getResources().getString(R.string.usage_wifi_default_suffix);
+        } else {
+            return mWifiSsid.replace("\"", "");
+        }
+    }
+
+    protected void setWifiSsid(String ssid) {
+        if (mWifiSsid != ssid) {
+            mWifiSsid = ssid;
+            setUsageText();
+        }
+    }
+
+    protected void setIsWifiConnected(boolean connected) {
+        if (mIsWifiConnected != connected) {
+            mIsWifiConnected = connected;
+            setUsageText();
+        }
+    }
+
+    protected void setNoSims(boolean hasNoSims) {
+        if (mHasNoSims != hasNoSims) {
+            mHasNoSims = hasNoSims;
+            setUsageText();
         }
     }
 
@@ -122,7 +206,7 @@
     private TouchAnimator createFooterAnimator() {
         TouchAnimator.Builder builder = new TouchAnimator.Builder()
                 .addFloat(mPageIndicator, "alpha", 0, 1)
-                .addFloat(mBuildText, "alpha", 0, 1)
+                .addFloat(mUsageText, "alpha", 0, 1)
                 .addFloat(mEditButton, "alpha", 0, 1)
                 .setStartDelay(0.9f);
         return builder.build();
@@ -149,21 +233,18 @@
         if (mFooterAnimator != null) {
             mFooterAnimator.setPosition(headerExpansionFraction);
         }
-    }
 
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        mContext.getContentResolver().registerContentObserver(
-                Settings.Global.getUriFor(Settings.Global.DEVELOPMENT_SETTINGS_ENABLED), false,
-                mDeveloperSettingsObserver, UserHandle.USER_ALL);
-    }
-
-    @Override
-    @VisibleForTesting
-    public void onDetachedFromWindow() {
-        mContext.getContentResolver().unregisterContentObserver(mDeveloperSettingsObserver);
-        super.onDetachedFromWindow();
+        if (mUsageText == null) return;
+        if (headerExpansionFraction == 1.0f) {
+            mUsageText.postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    mUsageText.setSelected(true);
+                }
+            }, 1000);
+        } else {
+            mUsageText.setSelected(false);
+        }
     }
 
     void disable(int state2) {
@@ -176,16 +257,12 @@
     void updateEverything() {
         post(() -> {
             updateVisibilities();
-            updateClickabilities();
+            setUsageText();
             setClickable(false);
         });
     }
 
-    private void updateClickabilities() {
-        mBuildText.setLongClickable(mBuildText.getVisibility() == View.VISIBLE);
-    }
-
     private void updateVisibilities() {
-        mBuildText.setVisibility(mExpanded && mShouldShowBuildText ? View.VISIBLE : View.INVISIBLE);
+        mUsageText.setVisibility(mExpanded && mShouldShowUsageText ? View.VISIBLE : View.INVISIBLE);
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java
index ffbd06f..43d2e89 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java
@@ -16,8 +16,15 @@
 
 package com.android.systemui.qs;
 
+import android.content.BroadcastReceiver;
+import android.content.Context;
 import android.content.ClipData;
 import android.content.ClipboardManager;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.net.NetworkScoreManager;
+import android.net.wifi.WifiManager;
 import android.text.TextUtils;
 import android.view.View;
 import android.widget.TextView;
@@ -29,8 +36,12 @@
 import com.android.systemui.qs.dagger.QSScope;
 import com.android.systemui.retail.domain.interactor.RetailModeInteractor;
 import com.android.systemui.settings.UserTracker;
+import com.android.systemui.statusbar.connectivity.NetworkController;
+import com.android.systemui.statusbar.connectivity.SignalCallback;
 import com.android.systemui.util.ViewController;
 
+import com.android.settingslib.wifi.WifiStatusTracker;
+
 import javax.inject.Inject;
 
 /**
@@ -41,12 +52,29 @@
 
     private final UserTracker mUserTracker;
     private final QSPanelController mQsPanelController;
-    private final TextView mBuildText;
     private final PageIndicator mPageIndicator;
     private final View mEditButton;
     private final FalsingManager mFalsingManager;
     private final ActivityStarter mActivityStarter;
     private final RetailModeInteractor mRetailModeInteractor;
+    private final WifiStatusTracker mWifiTracker;
+    private final NetworkController mNetworkController;
+    private final Context mContext;
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            mWifiTracker.handleBroadcast(intent);
+            onWifiStatusUpdated();
+        }
+    };
+
+    private final SignalCallback mSignalCallback = new SignalCallback() {
+        @Override
+        public void setNoSims(boolean show, boolean simDetected) {
+            mView.setNoSims(show);
+         }
+    };
 
     @Inject
     QSFooterViewController(QSFooterView view,
@@ -54,8 +82,9 @@
             FalsingManager falsingManager,
             ActivityStarter activityStarter,
             QSPanelController qsPanelController,
-            RetailModeInteractor retailModeInteractor
-    ) {
+            RetailModeInteractor retailModeInteractor,
+            NetworkController networkController,
+            Context context) {
         super(view);
         mUserTracker = userTracker;
         mQsPanelController = qsPanelController;
@@ -63,27 +92,18 @@
         mActivityStarter = activityStarter;
         mRetailModeInteractor = retailModeInteractor;
 
-        mBuildText = mView.findViewById(R.id.build);
+        mNetworkController = networkController;
+        mContext = context;
         mPageIndicator = mView.findViewById(R.id.footer_page_indicator);
         mEditButton = mView.findViewById(android.R.id.edit);
+        mWifiTracker = new WifiStatusTracker(context, context.getSystemService(WifiManager.class),
+                context.getSystemService(NetworkScoreManager.class),
+                context.getSystemService(ConnectivityManager.class),
+                        this::onWifiStatusUpdated);
     }
 
     @Override
     protected void onViewAttached() {
-        mBuildText.setOnLongClickListener(view -> {
-            CharSequence buildText = mBuildText.getText();
-            if (!TextUtils.isEmpty(buildText)) {
-                ClipboardManager service =
-                        mUserTracker.getUserContext().getSystemService(ClipboardManager.class);
-                String label = getResources().getString(R.string.build_number_clip_data_label);
-                service.setPrimaryClip(ClipData.newPlainText(label, buildText));
-                Toast.makeText(getContext(), R.string.build_number_copy_toast, Toast.LENGTH_SHORT)
-                        .show();
-                return true;
-            }
-            return false;
-        });
-
         mEditButton.setOnClickListener(view -> {
             if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
                 return;
@@ -92,11 +112,22 @@
                     .postQSRunnableDismissingKeyguard(() -> mQsPanelController.showEdit(view));
         });
         mQsPanelController.setFooterPageIndicator(mPageIndicator);
-        mView.updateEverything();
+        final IntentFilter filter = new IntentFilter();
+        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+        filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+        filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
+        mContext.registerReceiver(mReceiver, filter);
+        mWifiTracker.fetchInitialState();
+        mWifiTracker.setListening(true);
+        onWifiStatusUpdated();
+        mNetworkController.addCallback(mSignalCallback);
     }
 
     @Override
-    protected void onViewDetached() {}
+    protected void onViewDetached() {
+        mContext.unregisterReceiver(mReceiver);
+        mNetworkController.removeCallback(mSignalCallback);
+    }
 
     @Override
     public void setVisibility(int visibility) {
@@ -125,4 +156,9 @@
     public void disable(int state1, int state2, boolean animate) {
         mView.disable(state2);
     }
+
+    private void onWifiStatusUpdated() {
+        mView.setIsWifiConnected(mWifiTracker.connected);
+        mView.setWifiSsid(mWifiTracker.ssid);
+    }
 }