summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Fabian Kozynski <kozynski@google.com> 2021-01-12 17:39:40 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2021-01-12 17:39:40 +0000
commit2cc4d5ece19c89852814912e55b14798db1fcef7 (patch)
treef4359abfe3e7a30960b40079501cf84919347d82
parent829a1454db3e15436c80e5a984552f6236d331da (diff)
parent4d2758609cade0a6d8616493818ef5940c09402e (diff)
Merge "Migrate to WifiPickerTracker"
-rw-r--r--packages/SystemUI/AndroidManifest.xml1
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java241
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java32
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/AccessPointControllerImplTest.kt229
7 files changed, 490 insertions, 60 deletions
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index a06bb931771f..e036d87f2492 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -78,6 +78,7 @@
<uses-permission android:name="android.permission.REQUEST_NETWORK_SCORES" />
<uses-permission android:name="android.permission.CONTROL_VPN" />
<uses-permission android:name="android.permission.PEERS_MAC_ADDRESS"/>
+ <uses-permission android:name="android.permission.READ_WIFI_CREDENTIAL"/>
<!-- Physical hardware -->
<uses-permission android:name="android.permission.MANAGE_USB" />
<uses-permission android:name="android.permission.CONTROL_DISPLAY_BRIGHTNESS" />
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 4d89dea7cb70..19eac77136c6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -54,6 +54,7 @@ import com.android.systemui.statusbar.policy.NetworkController.AccessPointContro
import com.android.systemui.statusbar.policy.NetworkController.IconState;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
import com.android.systemui.statusbar.policy.WifiIcons;
+import com.android.wifitrackerlib.WifiEntry;
import java.util.List;
@@ -80,12 +81,13 @@ public class WifiTile extends QSTileImpl<SignalState> {
StatusBarStateController statusBarStateController,
ActivityStarter activityStarter,
QSLogger qsLogger,
- NetworkController networkController
+ NetworkController networkController,
+ AccessPointController accessPointController
) {
super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController,
activityStarter, qsLogger);
mController = networkController;
- mWifiController = mController.getAccessPointController();
+ mWifiController = accessPointController;
mDetailAdapter = (WifiDetailAdapter) createDetailAdapter();
mController.observe(getLifecycle(), mSignalCallback);
}
@@ -325,7 +327,7 @@ public class WifiTile extends QSTileImpl<SignalState> {
NetworkController.AccessPointController.AccessPointCallback, QSDetailItems.Callback {
private QSDetailItems mItems;
- private AccessPoint[] mAccessPoints;
+ private WifiEntry[] mAccessPoints;
@Override
public CharSequence getTitle() {
@@ -366,8 +368,8 @@ public class WifiTile extends QSTileImpl<SignalState> {
}
@Override
- public void onAccessPointsChanged(final List<AccessPoint> accessPoints) {
- mAccessPoints = accessPoints.toArray(new AccessPoint[accessPoints.size()]);
+ public void onAccessPointsChanged(final List<WifiEntry> accessPoints) {
+ mAccessPoints = accessPoints.toArray(new WifiEntry[accessPoints.size()]);
filterUnreachableAPs();
updateItems();
@@ -376,15 +378,15 @@ public class WifiTile extends QSTileImpl<SignalState> {
/** Filter unreachable APs from mAccessPoints */
private void filterUnreachableAPs() {
int numReachable = 0;
- for (AccessPoint ap : mAccessPoints) {
- if (ap.isReachable()) numReachable++;
+ for (WifiEntry ap : mAccessPoints) {
+ if (isWifiEntryReachable(ap)) numReachable++;
}
if (numReachable != mAccessPoints.length) {
- AccessPoint[] unfiltered = mAccessPoints;
- mAccessPoints = new AccessPoint[numReachable];
+ WifiEntry[] unfiltered = mAccessPoints;
+ mAccessPoints = new WifiEntry[numReachable];
int i = 0;
- for (AccessPoint ap : unfiltered) {
- if (ap.isReachable()) mAccessPoints[i++] = ap;
+ for (WifiEntry ap : unfiltered) {
+ if (isWifiEntryReachable(ap)) mAccessPoints[i++] = ap;
}
}
}
@@ -397,8 +399,8 @@ public class WifiTile extends QSTileImpl<SignalState> {
@Override
public void onDetailItemClick(Item item) {
if (item == null || item.tag == null) return;
- final AccessPoint ap = (AccessPoint) item.tag;
- if (!ap.isActive()) {
+ final WifiEntry ap = (WifiEntry) item.tag;
+ if (ap.getConnectedState() == WifiEntry.CONNECTED_STATE_DISCONNECTED) {
if (mWifiController.connect(ap)) {
mHost.collapsePanels();
}
@@ -442,12 +444,12 @@ public class WifiTile extends QSTileImpl<SignalState> {
if (mAccessPoints != null) {
items = new Item[mAccessPoints.length];
for (int i = 0; i < mAccessPoints.length; i++) {
- final AccessPoint ap = mAccessPoints[i];
+ final WifiEntry ap = mAccessPoints[i];
final Item item = new Item();
item.tag = ap;
item.iconResId = mWifiController.getIcon(ap);
item.line1 = ap.getSsid();
- item.line2 = ap.isActive() ? ap.getSummary() : null;
+ item.line2 = ap.getSummary();
item.icon2 = ap.getSecurity() != AccessPoint.SECURITY_NONE
? R.drawable.qs_ic_wifi_lock
: -1;
@@ -457,4 +459,8 @@ public class WifiTile extends QSTileImpl<SignalState> {
mItems.setItems(items);
}
}
+
+ private static boolean isWifiEntryReachable(WifiEntry ap) {
+ return ap.getLevel() != WifiEntry.WIFI_LEVEL_UNREACHABLE;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java
index 53d02280a03b..ab58286859cc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java
@@ -16,25 +16,47 @@
package com.android.systemui.statusbar.policy;
-import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
-import android.net.wifi.WifiManager.ActionListener;
+import android.net.ConnectivityManager;
+import android.net.NetworkScoreManager;
+import android.net.wifi.WifiManager;
+import android.os.Handler;
+import android.os.SimpleClock;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
+import android.util.IndentingPrintWriter;
import android.util.Log;
-import com.android.settingslib.wifi.AccessPoint;
-import com.android.settingslib.wifi.WifiTracker;
-import com.android.settingslib.wifi.WifiTracker.WifiListener;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LifecycleRegistry;
+
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.settings.UserTracker;
+import com.android.wifitrackerlib.WifiEntry;
+import com.android.wifitrackerlib.WifiPickerTracker;
import java.io.PrintWriter;
+import java.time.Clock;
+import java.time.ZoneOffset;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
+import java.util.concurrent.Executor;
+
+import javax.inject.Inject;
public class AccessPointControllerImpl
- implements NetworkController.AccessPointController, WifiListener {
+ implements NetworkController.AccessPointController,
+ WifiPickerTracker.WifiPickerTrackerCallback, LifecycleOwner {
private static final String TAG = "AccessPointController";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -44,24 +66,51 @@ public class AccessPointControllerImpl
private static final int[] ICONS = WifiIcons.WIFI_FULL_ICONS;
- private final Context mContext;
private final ArrayList<AccessPointCallback> mCallbacks = new ArrayList<AccessPointCallback>();
- private final WifiTracker mWifiTracker;
private final UserManager mUserManager;
+ private final Executor mMainExecutor;
+
+ private @Nullable WifiPickerTracker mWifiPickerTracker;
+ private WifiPickerTrackerFactory mWifiPickerTrackerFactory;
+
+ private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this);
private int mCurrentUser;
- public AccessPointControllerImpl(Context context) {
- mContext = context;
- mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- mWifiTracker = new WifiTracker(context, this, false, true);
- mCurrentUser = ActivityManager.getCurrentUser();
+ public AccessPointControllerImpl(
+ UserManager userManager,
+ UserTracker userTracker,
+ Executor mainExecutor,
+ WifiPickerTrackerFactory wifiPickerTrackerFactory
+ ) {
+ mUserManager = userManager;
+ mCurrentUser = userTracker.getUserId();
+ mMainExecutor = mainExecutor;
+ mWifiPickerTrackerFactory = wifiPickerTrackerFactory;
+ mMainExecutor.execute(() -> mLifecycle.setCurrentState(Lifecycle.State.CREATED));
+ }
+
+ /**
+ * Initializes the controller.
+ *
+ * Will create a WifiPickerTracker associated to this controller.
+ */
+ public void init() {
+ if (mWifiPickerTracker == null) {
+ mWifiPickerTracker = mWifiPickerTrackerFactory.create(this.getLifecycle(), this);
+ }
+ }
+
+ @NonNull
+ @Override
+ public Lifecycle getLifecycle() {
+ return mLifecycle;
}
@Override
protected void finalize() throws Throwable {
+ mMainExecutor.execute(() -> mLifecycle.setCurrentState(Lifecycle.State.DESTROYED));
super.finalize();
- mWifiTracker.onDestroy();
}
public boolean canConfigWifi() {
@@ -79,7 +128,7 @@ public class AccessPointControllerImpl
if (DEBUG) Log.d(TAG, "addCallback " + callback);
mCallbacks.add(callback);
if (mCallbacks.size() == 1) {
- mWifiTracker.onStart();
+ mMainExecutor.execute(() -> mLifecycle.setCurrentState(Lifecycle.State.STARTED));
}
}
@@ -89,37 +138,59 @@ public class AccessPointControllerImpl
if (DEBUG) Log.d(TAG, "removeCallback " + callback);
mCallbacks.remove(callback);
if (mCallbacks.isEmpty()) {
- mWifiTracker.onStop();
+ mMainExecutor.execute(() -> mLifecycle.setCurrentState(Lifecycle.State.CREATED));
}
}
@Override
public void scanForAccessPoints() {
- fireAcccessPointsCallback(mWifiTracker.getAccessPoints());
+ if (mWifiPickerTracker == null) {
+ fireAcccessPointsCallback(Collections.emptyList());
+ return;
+ }
+ List<WifiEntry> entries = mWifiPickerTracker.getWifiEntries();
+ WifiEntry connectedEntry = mWifiPickerTracker.getConnectedWifiEntry();
+ if (connectedEntry != null) {
+ entries.add(0, connectedEntry);
+ }
+ fireAcccessPointsCallback(entries);
}
@Override
- public int getIcon(AccessPoint ap) {
+ public int getIcon(WifiEntry ap) {
int level = ap.getLevel();
- return ICONS[level >= 0 ? level : 0];
+ return ICONS[Math.max(0, level)];
}
- public boolean connect(AccessPoint ap) {
+ /**
+ * Connects to a {@link WifiEntry} if it's saved or does not require security.
+ *
+ * If the entry is not saved and requires security, will trigger
+ * {@link AccessPointCallback#onSettingsActivityTriggered}.
+ * @param ap
+ * @return {@code true} if {@link AccessPointCallback#onSettingsActivityTriggered} is triggered
+ */
+ public boolean connect(WifiEntry ap) {
if (ap == null) return false;
- if (DEBUG) Log.d(TAG, "connect networkId=" + ap.getConfig().networkId);
+ if (DEBUG) {
+ if (ap.getWifiConfiguration() != null) {
+ Log.d(TAG, "connect networkId=" + ap.getWifiConfiguration().networkId);
+ } else {
+ Log.d(TAG, "connect to unsaved network " + ap.getTitle());
+ }
+ }
if (ap.isSaved()) {
- mWifiTracker.getManager().connect(ap.getConfig().networkId, mConnectListener);
+ ap.connect(mConnectCallback);
} else {
// Unknown network, need to add it.
- if (ap.getSecurity() != AccessPoint.SECURITY_NONE) {
+ if (ap.getSecurity() != WifiEntry.SECURITY_NONE) {
Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS);
- intent.putExtra(EXTRA_START_CONNECT_SSID, ap.getSsidStr());
+ intent.putExtra(EXTRA_START_CONNECT_SSID, ap.getSsid());
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
fireSettingsIntentCallback(intent);
return true;
} else {
- ap.generateOpenNetworkConfig();
- mWifiTracker.getManager().connect(ap.getConfig(), mConnectListener);
+ ap.connect(mConnectCallback);
}
}
return false;
@@ -131,39 +202,129 @@ public class AccessPointControllerImpl
}
}
- private void fireAcccessPointsCallback(List<AccessPoint> aps) {
+ private void fireAcccessPointsCallback(List<WifiEntry> aps) {
for (AccessPointCallback callback : mCallbacks) {
callback.onAccessPointsChanged(aps);
}
}
public void dump(PrintWriter pw) {
- mWifiTracker.dump(pw);
+ IndentingPrintWriter ipw = new IndentingPrintWriter(pw);
+ ipw.println("AccessPointControllerImpl:");
+ ipw.increaseIndent();
+ ipw.println("Callbacks: " + Arrays.toString(mCallbacks.toArray()));
+ ipw.println("WifiPickerTracker: " + mWifiPickerTracker.toString());
+ if (mWifiPickerTracker != null && !mCallbacks.isEmpty()) {
+ ipw.println("Connected: " + mWifiPickerTracker.getConnectedWifiEntry());
+ ipw.println("Other wifi entries: "
+ + Arrays.toString(mWifiPickerTracker.getWifiEntries().toArray()));
+ } else if (mWifiPickerTracker != null) {
+ ipw.println("WifiPickerTracker not started, cannot get reliable entries");
+ }
+ ipw.decreaseIndent();
}
@Override
- public void onWifiStateChanged(int state) {
+ public void onWifiStateChanged() {
+ scanForAccessPoints();
}
@Override
- public void onConnectedChanged() {
- fireAcccessPointsCallback(mWifiTracker.getAccessPoints());
+ public void onWifiEntriesChanged() {
+ scanForAccessPoints();
}
@Override
- public void onAccessPointsChanged() {
- fireAcccessPointsCallback(mWifiTracker.getAccessPoints());
+ public void onNumSavedNetworksChanged() {
+ // Do nothing
}
- private final ActionListener mConnectListener = new ActionListener() {
- @Override
- public void onSuccess() {
- if (DEBUG) Log.d(TAG, "connect success");
- }
+ @Override
+ public void onNumSavedSubscriptionsChanged() {
+ // Do nothing
+ }
+ private final WifiEntry.ConnectCallback mConnectCallback = new WifiEntry.ConnectCallback() {
@Override
- public void onFailure(int reason) {
- if (DEBUG) Log.d(TAG, "connect failure reason=" + reason);
+ public void onConnectResult(int status) {
+ if (status == CONNECT_STATUS_SUCCESS) {
+ if (DEBUG) Log.d(TAG, "connect success");
+ } else {
+ if (DEBUG) Log.d(TAG, "connect failure reason=" + status);
+ }
}
};
+
+ /**
+ * Factory for creating {@link WifiPickerTracker}.
+ *
+ * Uses the same time intervals as the Settings page for Wifi.
+ */
+ @SysUISingleton
+ public static class WifiPickerTrackerFactory {
+
+ // Max age of tracked WifiEntries
+ private static final long MAX_SCAN_AGE_MILLIS = 15_000;
+ // Interval between initiating WifiPickerTracker scans
+ private static final long SCAN_INTERVAL_MILLIS = 10_000;
+
+ private final Context mContext;
+ private final @Nullable WifiManager mWifiManager;
+ private final ConnectivityManager mConnectivityManager;
+ private final NetworkScoreManager mNetworkScoreManager;
+ private final Handler mMainHandler;
+ private final Handler mWorkerHandler;
+ private final Clock mClock = new SimpleClock(ZoneOffset.UTC) {
+ @Override
+ public long millis() {
+ return SystemClock.elapsedRealtime();
+ }
+ };
+
+ @Inject
+ public WifiPickerTrackerFactory(
+ Context context,
+ @Nullable WifiManager wifiManager,
+ ConnectivityManager connectivityManager,
+ NetworkScoreManager networkScoreManager,
+ @Main Handler mainHandler,
+ @Background Handler workerHandler
+ ) {
+ mContext = context;
+ mWifiManager = wifiManager;
+ mConnectivityManager = connectivityManager;
+ mNetworkScoreManager = networkScoreManager;
+ mMainHandler = mainHandler;
+ mWorkerHandler = workerHandler;
+ }
+
+ /**
+ * Create a {@link WifiPickerTracker}
+ *
+ * @param lifecycle
+ * @param listener
+ * @return a new {@link WifiPickerTracker} or {@code null} if {@link WifiManager} is null.
+ */
+ public @Nullable WifiPickerTracker create(
+ Lifecycle lifecycle,
+ WifiPickerTracker.WifiPickerTrackerCallback listener
+ ) {
+ if (mWifiManager == null) {
+ return null;
+ }
+ return new WifiPickerTracker(
+ lifecycle,
+ mContext,
+ mWifiManager,
+ mConnectivityManager,
+ mNetworkScoreManager,
+ mMainHandler,
+ mWorkerHandler,
+ mClock,
+ MAX_SCAN_AGE_MILLIS,
+ SCAN_INTERVAL_MILLIS,
+ listener
+ );
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index f92860b70116..b012dc4c7159 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -21,9 +21,9 @@ import android.content.Intent;
import android.telephony.SubscriptionInfo;
import com.android.settingslib.net.DataUsageController;
-import com.android.settingslib.wifi.AccessPoint;
import com.android.systemui.demomode.DemoMode;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
+import com.android.wifitrackerlib.WifiEntry;
import java.util.List;
@@ -123,12 +123,12 @@ public interface NetworkController extends CallbackController<SignalCallback>, D
void addAccessPointCallback(AccessPointCallback callback);
void removeAccessPointCallback(AccessPointCallback callback);
void scanForAccessPoints();
- int getIcon(AccessPoint ap);
- boolean connect(AccessPoint ap);
+ int getIcon(WifiEntry ap);
+ boolean connect(WifiEntry ap);
boolean canConfigWifi();
public interface AccessPointCallback {
- void onAccessPointsChanged(List<AccessPoint> accessPoints);
+ void onAccessPointsChanged(List<WifiEntry> accessPoints);
void onSettingsActivityTriggered(Intent settingsIntent);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index e41996604c99..5f5a83c5c50c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -187,6 +187,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
TelephonyManager telephonyManager,
@Nullable WifiManager wifiManager,
NetworkScoreManager networkScoreManager,
+ AccessPointControllerImpl accessPointController,
DemoModeController demoModeController) {
this(context, connectivityManager,
telephonyManager,
@@ -194,7 +195,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
networkScoreManager,
SubscriptionManager.from(context), Config.readConfig(context), bgLooper,
new CallbackHandler(),
- new AccessPointControllerImpl(context),
+ accessPointController,
new DataUsageController(context),
new SubscriptionDefaults(),
deviceProvisionedController,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
index 914105fdc4c4..069b4051af50 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
@@ -16,6 +16,12 @@
package com.android.systemui.statusbar.policy.dagger;
+import android.os.UserManager;
+
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.settings.UserTracker;
+import com.android.systemui.statusbar.policy.AccessPointControllerImpl;
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.BluetoothControllerImpl;
import com.android.systemui.statusbar.policy.CastController;
@@ -45,8 +51,11 @@ import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
+import java.util.concurrent.Executor;
+
import dagger.Binds;
import dagger.Module;
+import dagger.Provides;
/** Dagger Module for code in the statusbar.policy package. */
@@ -109,4 +118,27 @@ public interface StatusBarPolicyModule {
@Binds
ZenModeController provideZenModeController(ZenModeControllerImpl controllerImpl);
+ /** */
+ @Binds
+ NetworkController.AccessPointController provideAccessPointController(
+ AccessPointControllerImpl accessPointControllerImpl);
+
+ /** */
+ @SysUISingleton
+ @Provides
+ static AccessPointControllerImpl provideAccessPointControllerImpl(
+ UserManager userManager,
+ UserTracker userTracker,
+ @Main Executor mainExecutor,
+ AccessPointControllerImpl.WifiPickerTrackerFactory wifiPickerTrackerFactory
+ ) {
+ AccessPointControllerImpl controller = new AccessPointControllerImpl(
+ userManager,
+ userTracker,
+ mainExecutor,
+ wifiPickerTrackerFactory
+ );
+ controller.init();
+ return controller;
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/AccessPointControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/AccessPointControllerImplTest.kt
new file mode 100644
index 000000000000..4068f93f5ee3
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/AccessPointControllerImplTest.kt
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2020 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.systemui.statusbar.policy
+
+import android.os.UserManager
+import android.test.suitebuilder.annotation.SmallTest
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import androidx.lifecycle.Lifecycle
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.util.mockito.capture
+import com.android.wifitrackerlib.WifiEntry
+import com.android.wifitrackerlib.WifiPickerTracker
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyList
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+import java.util.concurrent.Executor
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper(setAsMainLooper = true)
+class AccessPointControllerImplTest : SysuiTestCase() {
+
+ @Mock
+ private lateinit var userManager: UserManager
+ @Mock
+ private lateinit var userTracker: UserTracker
+ @Mock
+ private lateinit var wifiPickerTrackerFactory:
+ AccessPointControllerImpl.WifiPickerTrackerFactory
+ @Mock
+ private lateinit var wifiPickerTracker: WifiPickerTracker
+ @Mock
+ private lateinit var callback: NetworkController.AccessPointController.AccessPointCallback
+ @Mock
+ private lateinit var otherCallback: NetworkController.AccessPointController.AccessPointCallback
+ @Mock
+ private lateinit var wifiEntryConnected: WifiEntry
+ @Mock
+ private lateinit var wifiEntryOther: WifiEntry
+ @Captor
+ private lateinit var wifiEntryListCaptor: ArgumentCaptor<List<WifiEntry>>
+
+ private val instantExecutor = Executor { it.run() }
+ private lateinit var controller: AccessPointControllerImpl
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ `when`(wifiPickerTrackerFactory.create(any(), any())).thenReturn(wifiPickerTracker)
+
+ `when`(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntryConnected)
+ `when`(wifiPickerTracker.wifiEntries).thenReturn(ArrayList<WifiEntry>().apply {
+ add(wifiEntryOther)
+ })
+
+ controller = AccessPointControllerImpl(
+ userManager,
+ userTracker,
+ instantExecutor,
+ wifiPickerTrackerFactory
+ )
+
+ controller.init()
+ }
+
+ @Test
+ fun testInitialLifecycleStateCreated() {
+ assertThat(controller.lifecycle.currentState).isEqualTo(Lifecycle.State.CREATED)
+ }
+
+ @Test
+ fun testLifecycleStartedAfterFirstCallback() {
+ controller.addAccessPointCallback(callback)
+ assertThat(controller.lifecycle.currentState).isEqualTo(Lifecycle.State.STARTED)
+ }
+
+ @Test
+ fun testLifecycleBackToCreatedAfterRemovingOnlyCallback() {
+ controller.addAccessPointCallback(callback)
+ controller.removeAccessPointCallback(callback)
+
+ assertThat(controller.lifecycle.currentState).isEqualTo(Lifecycle.State.CREATED)
+ }
+
+ @Test
+ fun testLifecycleStillStartedAfterRemovingSecondCallback() {
+ controller.addAccessPointCallback(callback)
+ controller.addAccessPointCallback(otherCallback)
+ controller.removeAccessPointCallback(callback)
+
+ assertThat(controller.lifecycle.currentState).isEqualTo(Lifecycle.State.STARTED)
+ }
+
+ @Test
+ fun testScanForAccessPointsTriggersCallbackWithEntriesInOrder() {
+ controller.addAccessPointCallback(callback)
+ controller.scanForAccessPoints()
+
+ verify(callback).onAccessPointsChanged(capture(wifiEntryListCaptor))
+
+ assertThat(wifiEntryListCaptor.value).containsExactly(wifiEntryConnected, wifiEntryOther)
+ }
+
+ @Test
+ fun testOnWifiStateChangedTriggersCallbackWithEntriesInOrder() {
+ controller.addAccessPointCallback(callback)
+ controller.onWifiStateChanged()
+
+ verify(callback).onAccessPointsChanged(capture(wifiEntryListCaptor))
+
+ assertThat(wifiEntryListCaptor.value).containsExactly(wifiEntryConnected, wifiEntryOther)
+ }
+
+ @Test
+ fun testOnWifiEntriesChangedTriggersCallbackWithEntriesInOrder() {
+ controller.addAccessPointCallback(callback)
+ controller.onWifiEntriesChanged()
+
+ verify(callback).onAccessPointsChanged(capture(wifiEntryListCaptor))
+
+ assertThat(wifiEntryListCaptor.value).containsExactly(wifiEntryConnected, wifiEntryOther)
+ }
+
+ @Test
+ fun testOnNumSavedNetworksChangedDoesntTriggerCallback() {
+ controller.addAccessPointCallback(callback)
+ controller.onNumSavedNetworksChanged()
+
+ verify(callback, never()).onAccessPointsChanged(anyList())
+ }
+
+ @Test
+ fun testOnNumSavedSubscriptionsChangedDoesntTriggerCallback() {
+ controller.addAccessPointCallback(callback)
+ controller.onNumSavedSubscriptionsChanged()
+
+ verify(callback, never()).onAccessPointsChanged(anyList())
+ }
+
+ @Test
+ fun testReturnEmptyListWhenNoWifiPickerTracker() {
+ `when`(wifiPickerTrackerFactory.create(any(), any())).thenReturn(null)
+ val otherController = AccessPointControllerImpl(
+ userManager,
+ userTracker,
+ instantExecutor,
+ wifiPickerTrackerFactory
+ )
+ otherController.init()
+
+ otherController.addAccessPointCallback(callback)
+ otherController.scanForAccessPoints()
+
+ verify(callback).onAccessPointsChanged(capture(wifiEntryListCaptor))
+
+ assertThat(wifiEntryListCaptor.value).isEmpty()
+ }
+
+ @Test
+ fun connectToNullEntry() {
+ controller.addAccessPointCallback(callback)
+
+ assertThat(controller.connect(null)).isFalse()
+
+ verify(callback, never()).onSettingsActivityTriggered(any())
+ }
+
+ @Test
+ fun connectToSavedWifiEntry() {
+ controller.addAccessPointCallback(callback)
+ `when`(wifiEntryOther.isSaved).thenReturn(true)
+
+ assertThat(controller.connect(wifiEntryOther)).isFalse()
+
+ verify(wifiEntryOther).connect(any())
+ verify(callback, never()).onSettingsActivityTriggered(any())
+ }
+
+ @Test
+ fun connectToSecuredNotSavedWifiEntry() {
+ controller.addAccessPointCallback(callback)
+ `when`(wifiEntryOther.isSaved).thenReturn(false)
+ `when`(wifiEntryOther.security).thenReturn(WifiEntry.SECURITY_EAP)
+
+ // True means we will launch WifiSettings
+ assertThat(controller.connect(wifiEntryOther)).isTrue()
+
+ verify(wifiEntryOther, never()).connect(any())
+ verify(callback).onSettingsActivityTriggered(any())
+ }
+
+ @Test
+ fun connectToNotSecuredNotSavedWifiEntry() {
+ controller.addAccessPointCallback(callback)
+ `when`(wifiEntryOther.isSaved).thenReturn(false)
+ `when`(wifiEntryOther.security).thenReturn(WifiEntry.SECURITY_NONE)
+
+ assertThat(controller.connect(wifiEntryOther)).isFalse()
+
+ verify(wifiEntryOther).connect(any())
+ verify(callback, never()).onSettingsActivityTriggered(any())
+ }
+} \ No newline at end of file