Make the WifiTrackerLib inheritable and cutomisable.

Bug: 149540986
Test: manual wifi picker test, and atest WifiTrackerLibTests
Change-Id: I93b6d7724508165abb45d6cde35a2578f7ed00fe
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/NetworkRequestEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/NetworkRequestEntry.java
index ccda30d..7e3f1c5 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/NetworkRequestEntry.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/NetworkRequestEntry.java
@@ -39,7 +39,7 @@
  */
 @VisibleForTesting
 public class NetworkRequestEntry extends StandardWifiEntry {
-    static final String KEY_PREFIX = "NetworkRequestEntry:";
+    public static final String KEY_PREFIX = "NetworkRequestEntry:";
 
     NetworkRequestEntry(@NonNull Context context, @NonNull Handler callbackHandler,
             @NonNull String key, @NonNull WifiManager wifiManager,
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/OsuWifiEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/OsuWifiEntry.java
index ff2786d..5574a0d 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/OsuWifiEntry.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/OsuWifiEntry.java
@@ -180,7 +180,7 @@
     }
 
     @Override
-    String getScanResultDescription() {
+    protected String getScanResultDescription() {
         // TODO(b/70983952): Fill this method in.
         return "";
     }
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointNetworkDetailsTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointNetworkDetailsTracker.java
index e4efcb9..ffab8fa 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointNetworkDetailsTracker.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointNetworkDetailsTracker.java
@@ -50,7 +50,7 @@
 /**
  * Implementation of NetworkDetailsTracker that tracks a single PasspointWifiEntry.
  */
-class PasspointNetworkDetailsTracker extends NetworkDetailsTracker {
+public class PasspointNetworkDetailsTracker extends NetworkDetailsTracker {
     private static final String TAG = "PasspointNetworkDetailsTracker";
 
     private final PasspointWifiEntry mChosenEntry;
@@ -58,7 +58,7 @@
     private NetworkInfo mCurrentNetworkInfo;
     private WifiConfiguration mCurrentWifiConfig;
 
-    PasspointNetworkDetailsTracker(@NonNull Lifecycle lifecycle,
+    public PasspointNetworkDetailsTracker(@NonNull Lifecycle lifecycle,
             @NonNull Context context,
             @NonNull WifiManager wifiManager,
             @NonNull ConnectivityManager connectivityManager,
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointWifiEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointWifiEntry.java
index 656744c..4d04b2e 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointWifiEntry.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointWifiEntry.java
@@ -64,7 +64,7 @@
  */
 @VisibleForTesting
 public class PasspointWifiEntry extends WifiEntry implements WifiEntry.WifiEntryCallback {
-    static final String KEY_PREFIX = "PasspointWifiEntry:";
+    public static final String KEY_PREFIX = "PasspointWifiEntry:";
 
     private final Object mLock = new Object();
     // Scan result list must be thread safe for generating the verbose scan summary
@@ -583,7 +583,7 @@
     }
 
     @Override
-    String getScanResultDescription() {
+    protected String getScanResultDescription() {
         // TODO(b/70983952): Fill this method in.
         return "";
     }
@@ -606,4 +606,9 @@
     public void onUpdated() {
         notifyOnUpdated();
     }
+
+    /** Get the PasspointConfiguration instance of the entry. */
+    public PasspointConfiguration getPasspointConfig() {
+        return mPasspointConfig;
+    }
 }
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java
index 2986672..6f42898 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java
@@ -47,14 +47,14 @@
 /**
  * Implementation of NetworkDetailsTracker that tracks a single StandardWifiEntry.
  */
-class StandardNetworkDetailsTracker extends NetworkDetailsTracker {
+public class StandardNetworkDetailsTracker extends NetworkDetailsTracker {
     private static final String TAG = "StandardNetworkDetailsTracker";
 
     private final StandardWifiEntry mChosenEntry;
     private final boolean mIsNetworkRequest;
     private NetworkInfo mCurrentNetworkInfo;
 
-    StandardNetworkDetailsTracker(@NonNull Lifecycle lifecycle,
+    public StandardNetworkDetailsTracker(@NonNull Lifecycle lifecycle,
             @NonNull Context context,
             @NonNull WifiManager wifiManager,
             @NonNull ConnectivityManager connectivityManager,
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java
index 7980121..e9cf4d0 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java
@@ -83,7 +83,7 @@
  */
 @VisibleForTesting
 public class StandardWifiEntry extends WifiEntry {
-    static final String KEY_PREFIX = "StandardWifiEntry:";
+    public static final String KEY_PREFIX = "StandardWifiEntry:";
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(value = {
@@ -868,7 +868,7 @@
     }
 
     @Override
-    String getScanResultDescription() {
+    protected String getScanResultDescription() {
         synchronized (mLock) {
             if (mCurrentScanResults.size() == 0) {
                 return "";
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java
index b5acaee..7f58e14 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java
@@ -82,7 +82,7 @@
 /**
  * Utility methods for WifiTrackerLib.
  */
-class Utils {
+public class Utils {
     /** Copy of the @hide Settings.Global.USE_OPEN_WIFI_PACKAGE constant. */
     static final String SETTINGS_GLOBAL_USE_OPEN_WIFI_PACKAGE = "use_open_wifi_package";
 
@@ -97,7 +97,7 @@
 
     // Returns the ScanResult with the best RSSI from a list of ScanResults.
     @Nullable
-    static ScanResult getBestScanResultByLevel(@NonNull List<ScanResult> scanResults) {
+    public static ScanResult getBestScanResultByLevel(@NonNull List<ScanResult> scanResults) {
         if (scanResults.isEmpty()) return null;
 
         return Collections.max(scanResults, comparingInt(scanResult -> scanResult.level));
@@ -324,7 +324,7 @@
     }
 
     @Speed
-    static int getAverageSpeedFromScanResults(@NonNull WifiNetworkScoreCache scoreCache,
+    public static int getAverageSpeedFromScanResults(@NonNull WifiNetworkScoreCache scoreCache,
             @NonNull List<ScanResult> scanResults) {
         int count = 0;
         int totalSpeed = 0;
@@ -347,7 +347,7 @@
     }
 
     @Speed
-    static int getSpeedFromWifiInfo(@NonNull WifiNetworkScoreCache scoreCache,
+    public static int getSpeedFromWifiInfo(@NonNull WifiNetworkScoreCache scoreCache,
             @NonNull WifiInfo wifiInfo) {
         final WifiKey wifiKey;
         try {
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java
index 5bbb338..693366c 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java
@@ -50,6 +50,7 @@
 import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
 import java.util.StringJoiner;
 import java.util.stream.Collectors;
 
@@ -240,7 +241,9 @@
     private boolean mIsDefaultNetwork;
     protected boolean mIsLowQuality;
 
-    WifiEntry(@NonNull Handler callbackHandler, @NonNull WifiManager wifiManager,
+    private Optional<ManageSubscriptionAction> mManageSubscriptionAction = Optional.empty();
+
+    public WifiEntry(@NonNull Handler callbackHandler, @NonNull WifiManager wifiManager,
             @NonNull WifiNetworkScoreCache scoreCache,
             boolean forSavedNetworksPage) throws IllegalArgumentException {
         checkNotNull(callbackHandler, "Cannot construct with null handler!");
@@ -537,8 +540,7 @@
 
     /** Returns whether a user can manage their subscription through this WifiEntry */
     public boolean canManageSubscription() {
-        // Subclasses should implement this method.
-        return false;
+        return mManageSubscriptionAction.isPresent();
     };
 
     /**
@@ -553,12 +555,24 @@
 
     /** Allows the user to manage their subscription via an external flow */
     public void manageSubscription() {
-        // Subclasses should implement this method.
+        mManageSubscriptionAction.ifPresent(ManageSubscriptionAction::onExecute);
     };
 
+    /** Set the action to be called on calling WifiEntry#manageSubscription. */
+    public void setManageSubscriptionAction(
+            @NonNull ManageSubscriptionAction manageSubscriptionAction) {
+        // only notify update on 1st time
+        boolean notify = !mManageSubscriptionAction.isPresent();
+
+        mManageSubscriptionAction = Optional.of(manageSubscriptionAction);
+        if (notify) {
+            notifyOnUpdated();
+        }
+    }
+
     /** Returns the ScanResult information of a WifiEntry */
     @NonNull
-    String getScanResultDescription() {
+    protected String getScanResultDescription() {
         return "";
     }
 
@@ -970,4 +984,14 @@
                 .append(mIsDefaultNetwork)
                 .toString();
     }
+
+    /**
+     * The action used to execute the calling of WifiEntry#manageSubscription.
+     */
+    public interface ManageSubscriptionAction {
+        /**
+         * Execute the action of managing subscription.
+         */
+        void onExecute();
+    }
 }
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java
index 310eabe..367a98e 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java
@@ -258,6 +258,13 @@
     @Override
     protected void handleConfiguredNetworksChangedAction(@NonNull Intent intent) {
         checkNotNull(intent, "Intent cannot be null!");
+
+        processConfiguredNetworksChanged();
+    }
+
+    @WorkerThread
+    /** All wifi entries and saved entries needs to be updated. */
+    protected void processConfiguredNetworksChanged() {
         updateWifiConfigurations(mWifiManager.getPrivilegedConfiguredNetworks());
         updatePasspointConfigurations(mWifiManager.getPasspointConfigurations());
         // Update scans since config changes may result in different entries being shown.
@@ -343,7 +350,7 @@
      * Update the list returned by getWifiEntries() with the current states of the entry caches.
      */
     @WorkerThread
-    private void updateWifiEntries() {
+    protected void updateWifiEntries() {
         synchronized (mLock) {
             mConnectedWifiEntry = mStandardWifiEntryCache.values().stream().filter(entry -> {
                 final @WifiEntry.ConnectedState int connectedState = entry.getConnectedState();
@@ -395,6 +402,8 @@
             mWifiEntries.addAll(mOsuWifiEntryCache.values().stream().filter(entry ->
                     entry.getConnectedState() == CONNECTED_STATE_DISCONNECTED
                             && !entry.isAlreadyProvisioned()).collect(toList()));
+            mWifiEntries.addAll(getContextualWifiEntries().stream().filter(entry ->
+                    entry.getConnectedState() == CONNECTED_STATE_DISCONNECTED).collect(toList()));
             Collections.sort(mWifiEntries);
             if (isVerboseLoggingEnabled()) {
                 Log.v(TAG, "Connected WifiEntry: " + mConnectedWifiEntry);
@@ -428,6 +437,20 @@
     }
 
     /**
+     * Get the contextual WifiEntries added according to customized conditions.
+     */
+    protected List<WifiEntry> getContextualWifiEntries() {
+        return Collections.emptyList();
+    }
+
+    /**
+     * Update the contextual wifi entry according to customized conditions.
+     */
+    protected void updateContextualWifiEntryScans(@NonNull List<ScanResult> scanResults) {
+        // do nothing
+    }
+
+    /**
      * Updates or removes scan results for the corresponding StandardWifiEntries.
      * New entries will be created for scan results without an existing entry.
      * Unreachable entries will be removed.
@@ -638,6 +661,7 @@
             updatePasspointWifiEntryScans(Collections.emptyList());
             updateOsuWifiEntryScans(Collections.emptyList());
             updateNetworkRequestEntryScans(Collections.emptyList());
+            updateContextualWifiEntryScans(Collections.emptyList());
             return;
         }
 
@@ -657,6 +681,7 @@
         updatePasspointWifiEntryScans(scanResults);
         updateOsuWifiEntryScans(scanResults);
         updateNetworkRequestEntryScans(scanResults);
+        updateContextualWifiEntryScans(scanResults);
     }
 
     /**