Display more information on network detail page

For connected network, show all information at detail page. For
disconnected network, show signal strength, Mac address, etc.

Bug: 124707751
Test: atest
Test: manual test
Change-Id: I401621abf9bba5dc7900b47a811d595adc906c13
diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
index 89565df..5588977 100644
--- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
@@ -66,6 +66,7 @@
 import com.android.settings.wifi.WifiDialog.WifiDialogListener;
 import com.android.settings.wifi.WifiUtils;
 import com.android.settings.wifi.dpp.WifiDppUtils;
+import com.android.settings.wifi.savedaccesspoints.SavedAccessPointsWifiSettings;
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -75,6 +76,8 @@
 import com.android.settingslib.widget.ActionButtonsPreference;
 import com.android.settingslib.widget.LayoutPreference;
 import com.android.settingslib.wifi.AccessPoint;
+import com.android.settingslib.wifi.WifiTracker;
+import com.android.settingslib.wifi.WifiTrackerFactory;
 
 import java.net.Inet4Address;
 import java.net.Inet6Address;
@@ -136,7 +139,9 @@
     private WifiConfiguration mWifiConfig;
     private WifiInfo mWifiInfo;
     private final WifiManager mWifiManager;
+    private final WifiTracker mWifiTracker;
     private final MetricsFeatureProvider mMetricsFeatureProvider;
+    private boolean mIsOutOfRange;
 
     // UI elements - in order of appearance
     private ActionButtonsPreference mButtonsPref;
@@ -176,7 +181,7 @@
                     // fall through
                 case WifiManager.NETWORK_STATE_CHANGED_ACTION:
                 case WifiManager.RSSI_CHANGED_ACTION:
-                    updateLiveNetworkInfo();
+                    updateNetworkInfo();
                     break;
             }
         }
@@ -206,14 +211,16 @@
         @Override
         public void onCapabilitiesChanged(Network network, NetworkCapabilities nc) {
             // If the network just validated or lost Internet access, refresh network state.
-            // Don't do this on every NetworkCapabilities change because refreshNetworkState
-            // sends IPCs to the system server from the UI thread, which can cause jank.
+            // Don't do this on every NetworkCapabilities change because update accesspoint notify
+            // changed for accesspoint changed on the main thread, which can cause jank.
             if (network.equals(mNetwork) && !nc.equals(mNetworkCapabilities)) {
                 if (hasCapabilityChanged(nc, NET_CAPABILITY_VALIDATED) ||
                         hasCapabilityChanged(nc, NET_CAPABILITY_CAPTIVE_PORTAL)) {
-                    refreshNetworkState();
+                    mAccessPoint.update(mWifiConfig, mWifiInfo, mNetworkInfo);
+                    refreshEntityHeader();
                 }
                 mNetworkCapabilities = nc;
+                refreshButtons();
                 updateIpLayerInfo();
             }
         }
@@ -226,6 +233,29 @@
         }
     };
 
+    private final WifiTracker.WifiListener mWifiListener = new WifiTracker.WifiListener() {
+        /** Called when the state of Wifi has changed. */
+        public void onWifiStateChanged(int state) {
+            Log.d(TAG, "onWifiStateChanged(" + state + ")");
+            // Do nothing.
+        }
+
+        /** Called when the connection state of wifi has changed. */
+        public void onConnectedChanged() {
+            Log.d(TAG, "onConnectedChanged");
+            // Do nothing.
+        }
+
+        /**
+         * Called to indicate the list of AccessPoints has been updated and
+         * {@link WifiTracker#getAccessPoints()} should be called to get the updated list.
+         */
+        public void onAccessPointsChanged() {
+            Log.d(TAG, "onAccessPointsChanged");
+            updateNetworkInfo();
+        }
+    };
+
     public static WifiDetailPreferenceController newInstance(
             AccessPoint accessPoint,
             ConnectivityManager connectivityManager,
@@ -270,6 +300,17 @@
 
         mLifecycle = lifecycle;
         lifecycle.addObserver(this);
+
+        if (SavedAccessPointsWifiSettings.usingDetailsFragment(mContext)) {
+            mWifiTracker = WifiTrackerFactory.create(
+                    mFragment.getActivity(),
+                    mWifiListener,
+                    mLifecycle,
+                    true /*includeSaved*/,
+                    true /*includeScans*/);
+        } else {
+            mWifiTracker = null;
+        }
     }
 
     @Override
@@ -360,7 +401,7 @@
         mNetwork = mWifiManager.getCurrentNetwork();
         mLinkProperties = mConnectivityManager.getLinkProperties(mNetwork);
         mNetworkCapabilities = mConnectivityManager.getNetworkCapabilities(mNetwork);
-        updateLiveNetworkInfo();
+        updateNetworkInfo();
         mContext.registerReceiver(mReceiver, mFilter);
         mConnectivityManager.registerNetworkCallback(mNetworkRequest, mNetworkCallback,
                 mHandler);
@@ -377,72 +418,73 @@
         mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
     }
 
-    // TODO(b/124707751): Refactoring the code later, keeping it currently for stability.
-    protected void updateSavedNetworkInfo() {
-        mSignalStrengthPref.setVisible(false);
-        mFrequencyPref.setVisible(false);
-        mTxLinkSpeedPref.setVisible(false);
-        mRxLinkSpeedPref.setVisible(false);
-
-        // MAC Address Pref
-        mMacAddressPref.setSummary(mWifiConfig.getRandomizedMacAddress().toString());
-
-        refreshEntityHeader();
-
-        updateIpLayerInfo();
-
-        // Update whether the forget button should be displayed.
-        mButtonsPref.setButton1Visible(canForgetNetwork());
-    }
-
-    private void updateLiveNetworkInfo() {
-        // No need to fetch LinkProperties and NetworkCapabilities, they are updated by the
-        // callbacks. mNetwork doesn't change except in onResume.
-        mNetworkInfo = mConnectivityManager.getNetworkInfo(mNetwork);
-        mWifiInfo = mWifiManager.getConnectionInfo();
-        if (mNetwork == null || mNetworkInfo == null || mWifiInfo == null) {
-            exitActivity();
+    private void updateNetworkInfo() {
+        if(!updateAccessPoint()) {
             return;
         }
 
-        // Update whether the forget button should be displayed.
-        mButtonsPref.setButton1Visible(canForgetNetwork());
+        // refresh header
+        refreshEntityHeader();
 
-        refreshNetworkState();
+        // refresh Buttons
+        refreshButtons();
 
         // Update Connection Header icon and Signal Strength Preference
         refreshRssiViews();
-
-        // MAC Address Pref
-        mMacAddressPref.setSummary(mWifiInfo.getMacAddress());
-
-        // Transmit Link Speed Pref
-        int txLinkSpeedMbps = mWifiInfo.getTxLinkSpeedMbps();
-        mTxLinkSpeedPref.setVisible(txLinkSpeedMbps >= 0);
-        mTxLinkSpeedPref.setSummary(mContext.getString(
-                R.string.tx_link_speed, mWifiInfo.getTxLinkSpeedMbps()));
-
-        // Receive Link Speed Pref
-        int rxLinkSpeedMbps = mWifiInfo.getRxLinkSpeedMbps();
-        mRxLinkSpeedPref.setVisible(rxLinkSpeedMbps >= 0);
-        mRxLinkSpeedPref.setSummary(mContext.getString(
-                R.string.rx_link_speed, mWifiInfo.getRxLinkSpeedMbps()));
-
         // Frequency Pref
-        final int frequency = mWifiInfo.getFrequency();
-        String band = null;
-        if (frequency >= AccessPoint.LOWER_FREQ_24GHZ
-                && frequency < AccessPoint.HIGHER_FREQ_24GHZ) {
-            band = mContext.getResources().getString(R.string.wifi_band_24ghz);
-        } else if (frequency >= AccessPoint.LOWER_FREQ_5GHZ
-                && frequency < AccessPoint.HIGHER_FREQ_5GHZ) {
-            band = mContext.getResources().getString(R.string.wifi_band_5ghz);
-        } else {
-            Log.e(TAG, "Unexpected frequency " + frequency);
-        }
-        mFrequencyPref.setSummary(band);
-
+        refreshFrequency();
+        // Transmit Link Speed Pref
+        refreshTxSpeed();
+        // Receive Link Speed Pref
+        refreshRxSpeed();
+        // IP related information
         updateIpLayerInfo();
+        // MAC Address Pref
+        refreshMacAddress();
+
+    }
+
+    private boolean updateAccessPoint() {
+        boolean changed = false;
+        if (mWifiTracker != null) {
+            updateAccessPointFromScannedList();
+            // refresh UI if signal level changed for disconnect network.
+            changed = mRssiSignalLevel != mAccessPoint.getLevel();
+        }
+
+        if (mAccessPoint.isActive()) {
+            // No need to fetch LinkProperties and NetworkCapabilities, they are updated by the
+            // callbacks. mNetwork doesn't change except in onResume.
+            mNetworkInfo = mConnectivityManager.getNetworkInfo(mNetwork);
+            mWifiInfo = mWifiManager.getConnectionInfo();
+            if (mNetwork == null || mNetworkInfo == null || mWifiInfo == null) {
+                exitActivity();
+                return false;
+            }
+
+            changed |= mAccessPoint.update(mWifiConfig, mWifiInfo, mNetworkInfo);
+            // If feature for saved network not enabled, always return true.
+            return mWifiTracker == null || changed;
+        }
+
+        return changed;
+    }
+
+    private void updateAccessPointFromScannedList() {
+        mIsOutOfRange = true;
+
+        if (mAccessPoint.getConfig() == null) {
+            return;
+        }
+
+        for (AccessPoint ap : mWifiTracker.getAccessPoints()) {
+            if (ap.getConfig() != null
+                    && mAccessPoint.matches(ap.getConfig())) {
+                mAccessPoint = ap;
+                mIsOutOfRange = false;
+                return;
+            }
+        }
     }
 
     private void exitActivity() {
@@ -452,14 +494,16 @@
         mFragment.getActivity().finish();
     }
 
-    private void refreshNetworkState() {
-        mAccessPoint.update(mWifiConfig, mWifiInfo, mNetworkInfo);
-        refreshEntityHeader();
-    }
-
     private void refreshRssiViews() {
         int signalLevel = mAccessPoint.getLevel();
 
+        // Disappears signal view if not in range. e.g. for saved networks.
+        if (mIsOutOfRange) {
+            mSignalStrengthPref.setVisible(false);
+            mRssiSignalLevel = -1;
+            return;
+        }
+
         if (mRssiSignalLevel == signalLevel) {
             return;
         }
@@ -477,6 +521,84 @@
         mSignalStrengthPref.setIcon(wifiIconDark);
 
         mSignalStrengthPref.setSummary(mSignalStr[mRssiSignalLevel]);
+        mSignalStrengthPref.setVisible(true);
+    }
+
+    private void refreshFrequency() {
+        if (mWifiInfo == null) {
+            mFrequencyPref.setVisible(false);
+            return;
+        }
+
+        final int frequency = mWifiInfo.getFrequency();
+        String band = null;
+        if (frequency >= AccessPoint.LOWER_FREQ_24GHZ
+                && frequency < AccessPoint.HIGHER_FREQ_24GHZ) {
+            band = mContext.getResources().getString(R.string.wifi_band_24ghz);
+        } else if (frequency >= AccessPoint.LOWER_FREQ_5GHZ
+                && frequency < AccessPoint.HIGHER_FREQ_5GHZ) {
+            band = mContext.getResources().getString(R.string.wifi_band_5ghz);
+        } else {
+            Log.e(TAG, "Unexpected frequency " + frequency);
+        }
+        mFrequencyPref.setSummary(band);
+        mFrequencyPref.setVisible(true);
+    }
+
+    private void refreshTxSpeed() {
+        if (mWifiInfo == null) {
+            mTxLinkSpeedPref.setVisible(false);
+            return;
+        }
+
+        int txLinkSpeedMbps = mWifiInfo.getTxLinkSpeedMbps();
+        mTxLinkSpeedPref.setVisible(txLinkSpeedMbps >= 0);
+        mTxLinkSpeedPref.setSummary(mContext.getString(
+                R.string.tx_link_speed, mWifiInfo.getTxLinkSpeedMbps()));
+    }
+
+    private void refreshRxSpeed() {
+        if (mWifiInfo == null) {
+            mRxLinkSpeedPref.setVisible(false);
+            return;
+        }
+
+        int rxLinkSpeedMbps = mWifiInfo.getRxLinkSpeedMbps();
+        mRxLinkSpeedPref.setVisible(rxLinkSpeedMbps >= 0);
+        mRxLinkSpeedPref.setSummary(mContext.getString(
+                R.string.rx_link_speed, mWifiInfo.getRxLinkSpeedMbps()));
+    }
+
+    private void refreshMacAddress() {
+        String macAddress = getMacAddress();
+        if (macAddress == null) {
+            mMacAddressPref.setVisible(false);
+            return;
+        }
+
+        mMacAddressPref.setVisible(true);
+        mMacAddressPref.setSummary(macAddress);
+    }
+
+    private String getMacAddress() {
+        if (mWifiInfo != null) {
+            // get MAC address from connected network information
+            return mWifiInfo.getMacAddress();
+        }
+
+        // return randomized MAC address
+        if (mWifiConfig.macRandomizationSetting == WifiConfiguration.RANDOMIZATION_PERSISTENT) {
+            return mWifiConfig.getRandomizedMacAddress().toString();
+        }
+
+        // return device MAC address
+        final String[] macAddresses = mWifiManager.getFactoryMacAddresses();
+        if (macAddresses != null && macAddresses.length > 0) {
+            return macAddresses[0];
+        }
+
+        Log.e(TAG, "Can't get device MAC address!");
+        return null;
     }
 
     private void updatePreference(Preference pref, String detailText) {
@@ -488,13 +610,17 @@
         }
     }
 
-    private void updateIpLayerInfo() {
+    private void refreshButtons() {
+        mButtonsPref.setButton1Visible(canForgetNetwork());
         mButtonsPref.setButton2Visible(canSignIntoNetwork());
         mButtonsPref.setButton3Visible(canShareNetwork());
         mButtonsPref.setVisible(
                 canSignIntoNetwork() || canForgetNetwork() || canShareNetwork());
+    }
 
-        if (mNetwork == null || mLinkProperties == null) {
+    private void updateIpLayerInfo() {
+        // Hide IP layer info if not a connected network.
+        if (!mAccessPoint.isActive() || mNetwork == null || mLinkProperties == null) {
             mIpAddressPref.setVisible(false);
             mSubnetPref.setVisible(false);
             mGatewayPref.setVisible(false);
diff --git a/src/com/android/settings/wifi/details/WifiDetailSavedNetworkPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailSavedNetworkPreferenceController.java
deleted file mode 100644
index 3407890..0000000
--- a/src/com/android/settings/wifi/details/WifiDetailSavedNetworkPreferenceController.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.settings.wifi.details;
-
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.wifi.WifiManager;
-import android.os.Handler;
-
-import androidx.fragment.app.Fragment;
-
-import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.wifi.AccessPoint;
-
-public class WifiDetailSavedNetworkPreferenceController extends WifiDetailPreferenceController {
-
-    WifiDetailSavedNetworkPreferenceController(AccessPoint accessPoint,
-            ConnectivityManager connectivityManager, Context context,
-            Fragment fragment, Handler handler,
-            Lifecycle lifecycle,
-            WifiManager wifiManager,
-            MetricsFeatureProvider metricsFeatureProvider,
-            IconInjector injector) {
-        super(accessPoint, connectivityManager, context, fragment, handler, lifecycle, wifiManager,
-                metricsFeatureProvider, injector);
-    }
-
-    public static WifiDetailSavedNetworkPreferenceController newInstance(
-            AccessPoint accessPoint,
-            ConnectivityManager connectivityManager,
-            Context context,
-            Fragment fragment,
-            Handler handler,
-            Lifecycle lifecycle,
-            WifiManager wifiManager,
-            MetricsFeatureProvider metricsFeatureProvider) {
-        return new WifiDetailSavedNetworkPreferenceController(
-                accessPoint, connectivityManager, context, fragment, handler, lifecycle,
-                wifiManager, metricsFeatureProvider, new IconInjector(context));
-    }
-
-    @Override
-    public void onPause() {
-        // Do nothing
-    }
-
-    @Override
-    public void onResume() {
-        updateSavedNetworkInfo();
-    }
-}
diff --git a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
index 7edd227..66587ed 100644
--- a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
+++ b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
@@ -51,9 +51,6 @@
 
     private static final String TAG = "WifiNetworkDetailsFrg";
 
-    // Extra for if current fragment shows saved network status or not.
-    public static final String EXTRA_IS_SAVED_NETWORK = "SavedNetwork";
-
     private AccessPoint mAccessPoint;
     private WifiDetailPreferenceController mWifiDetailPreferenceController;
 
@@ -126,30 +123,15 @@
         final List<AbstractPreferenceController> controllers = new ArrayList<>();
         final ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
 
-        final boolean isDisplaySavedNetworkDetails =
-                getArguments().getBoolean(EXTRA_IS_SAVED_NETWORK, false /* defaultValue */);
-        if (isDisplaySavedNetworkDetails) {
-            mWifiDetailPreferenceController =
-                    WifiDetailSavedNetworkPreferenceController.newInstance(
-                            mAccessPoint,
-                            cm,
-                            context,
-                            this,
-                            new Handler(Looper.getMainLooper()),  // UI thread.
-                            getSettingsLifecycle(),
-                            context.getSystemService(WifiManager.class),
-                            mMetricsFeatureProvider);
-        } else {
-            mWifiDetailPreferenceController = WifiDetailPreferenceController.newInstance(
-                    mAccessPoint,
-                    cm,
-                    context,
-                    this,
-                    new Handler(Looper.getMainLooper()),  // UI thread.
-                    getSettingsLifecycle(),
-                    context.getSystemService(WifiManager.class),
-                    mMetricsFeatureProvider);
-        }
+        mWifiDetailPreferenceController = WifiDetailPreferenceController.newInstance(
+                mAccessPoint,
+                cm,
+                context,
+                this,
+                new Handler(Looper.getMainLooper()),  // UI thread.
+                getSettingsLifecycle(),
+                context.getSystemService(WifiManager.class),
+                mMetricsFeatureProvider);
 
         controllers.add(mWifiDetailPreferenceController);
         controllers.add(new WifiMeteredPreferenceController(context, mAccessPoint.getConfig()));
diff --git a/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsWifiSettings.java b/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsWifiSettings.java
index ea858f3..3f600e6 100644
--- a/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsWifiSettings.java
+++ b/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsWifiSettings.java
@@ -108,7 +108,6 @@
             }
             final Bundle savedState = new Bundle();
             mSelectedAccessPoint.saveWifiState(savedState);
-            savedState.putBoolean(WifiNetworkDetailsFragment.EXTRA_IS_SAVED_NETWORK, true);
 
             new SubSettingLauncher(getContext())
                     .setTitleText(mSelectedAccessPoint.getTitle())