1d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk/*
2d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk * Copyright (C) 2015 The Android Open Source Project
3d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk *
4d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk * Licensed under the Apache License, Version 2.0 (the "License");
5d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk * you may not use this file except in compliance with the License.
6d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk * You may obtain a copy of the License at
7d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk *
8d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk *      http://www.apache.org/licenses/LICENSE-2.0
9d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk *
10d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk * Unless required by applicable law or agreed to in writing, software
11d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk * distributed under the License is distributed on an "AS IS" BASIS,
12d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk * See the License for the specific language governing permissions and
14d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk * limitations under the License.
15d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk */
16d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monkpackage com.android.settingslib.wifi;
17d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
18d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monkimport android.content.Intent;
19d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monkimport android.net.NetworkInfo;
20d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monkimport android.net.NetworkInfo.State;
21d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monkimport android.net.wifi.ScanResult;
22d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monkimport android.net.wifi.WifiConfiguration;
23d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monkimport android.net.wifi.WifiInfo;
24d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monkimport android.net.wifi.WifiManager;
25d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monkimport android.net.wifi.WifiSsid;
262b51cc30d523cce3609a498c466364caf3ce504eJason Monkimport android.os.HandlerThread;
272b51cc30d523cce3609a498c466364caf3ce504eJason Monkimport android.os.Looper;
28d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monkimport android.util.Log;
29d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
30d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monkimport com.android.settingslib.BaseTest;
312b51cc30d523cce3609a498c466364caf3ce504eJason Monkimport com.android.settingslib.wifi.WifiTracker.Scanner;
32d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monkimport com.android.settingslib.wifi.WifiTracker.WifiListener;
33d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
34d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monkimport org.mockito.ArgumentCaptor;
35d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monkimport org.mockito.Mockito;
36d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
37d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monkimport java.io.PrintWriter;
38d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monkimport java.io.StringWriter;
39d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monkimport java.util.ArrayList;
40d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monkimport java.util.List;
41d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
42d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monkpublic class WifiTrackerTest extends BaseTest {
43d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
44d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    private static final String TAG = "WifiTrackerTest";
45d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
46d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    private static final String[] TEST_SSIDS = new String[] {
47d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        "TEST_SSID_1",
48d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        "TEST_SSID_2",
49d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        "TEST_SSID_3",
50d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        "TEST_SSID_4",
51d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        "TEST_SSID_5",
52d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    };
53d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    private static final int NUM_NETWORKS = 5;
54d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
55d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    private WifiManager mWifiManager;
56d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    private WifiListener mWifiListener;
57d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
58d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    private WifiTracker mWifiTracker;
59d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
602b51cc30d523cce3609a498c466364caf3ce504eJason Monk    private HandlerThread mWorkerThread;
612b51cc30d523cce3609a498c466364caf3ce504eJason Monk    private Looper mLooper;
622b51cc30d523cce3609a498c466364caf3ce504eJason Monk    private HandlerThread mMainThread;
632b51cc30d523cce3609a498c466364caf3ce504eJason Monk    private Looper mMainLooper;
642b51cc30d523cce3609a498c466364caf3ce504eJason Monk
65d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    @Override
66d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    protected void setUp() throws Exception {
67d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        super.setUp();
68d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
69d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        mWifiManager = Mockito.mock(WifiManager.class);
70d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        mWifiListener = Mockito.mock(WifiListener.class);
712b51cc30d523cce3609a498c466364caf3ce504eJason Monk        mWorkerThread = new HandlerThread("TestHandlerThread");
722b51cc30d523cce3609a498c466364caf3ce504eJason Monk        mWorkerThread.start();
732b51cc30d523cce3609a498c466364caf3ce504eJason Monk        mLooper = mWorkerThread.getLooper();
742b51cc30d523cce3609a498c466364caf3ce504eJason Monk        mMainThread = new HandlerThread("TestHandlerThread");
752b51cc30d523cce3609a498c466364caf3ce504eJason Monk        mMainThread.start();
762b51cc30d523cce3609a498c466364caf3ce504eJason Monk        mMainLooper = mMainThread.getLooper();
772b51cc30d523cce3609a498c466364caf3ce504eJason Monk        mWifiTracker = new WifiTracker(mContext, mWifiListener, mLooper, true, true, true,
782b51cc30d523cce3609a498c466364caf3ce504eJason Monk                mWifiManager, mMainLooper);
79d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        mWifiTracker.mScanner = mWifiTracker.new Scanner();
80d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        Mockito.when(mWifiManager.isWifiEnabled()).thenReturn(true);
81d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    }
82d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
83d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    @Override
84d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    protected void tearDown() throws Exception {
85d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        StringWriter sw = new StringWriter();
86d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        PrintWriter pw = new PrintWriter(sw);
87d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        mWifiTracker.dump(pw);
88d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        pw.flush();
89d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        Log.d(TAG, sw.toString());
90d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        super.tearDown();
91d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    }
92d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
93d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    public void testAccessPointsCallback() {
942b51cc30d523cce3609a498c466364caf3ce504eJason Monk        sendScanResultsAndProcess(false);
95d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
96d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        Mockito.verify(mWifiListener, Mockito.atLeastOnce()).onAccessPointsChanged();
97d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    }
98d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
99d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    public void testConnectedCallback() {
100d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        sendConnected();
1012b51cc30d523cce3609a498c466364caf3ce504eJason Monk        waitForThreads();
102d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
103d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        Mockito.verify(mWifiListener, Mockito.atLeastOnce()).onConnectedChanged();
104d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        assertEquals(true, mWifiTracker.isConnected());
105d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    }
106d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
107d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    public void testWifiStateCallback() {
108d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        final int TEST_WIFI_STATE = WifiManager.WIFI_STATE_ENABLED;
109d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
110d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        Intent i = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION);
111d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        i.putExtra(WifiManager.EXTRA_WIFI_STATE, TEST_WIFI_STATE);
112d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        mWifiTracker.mReceiver.onReceive(mContext, i);
1132b51cc30d523cce3609a498c466364caf3ce504eJason Monk        waitForThreads();
114d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
115d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        ArgumentCaptor<Integer> wifiState = ArgumentCaptor.forClass(Integer.class);
116d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        Mockito.verify(mWifiListener, Mockito.atLeastOnce())
117d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk                .onWifiStateChanged(wifiState.capture());
118d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        assertEquals(TEST_WIFI_STATE, (int) wifiState.getValue());
119d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    }
120d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
121d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    public void testScanner() {
122d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        // TODO: Figure out how to verify more of the Scanner functionality.
123d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        // Make scans be successful.
124d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        Mockito.when(mWifiManager.startScan()).thenReturn(true);
125d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
1262b51cc30d523cce3609a498c466364caf3ce504eJason Monk        mWifiTracker.mScanner.handleMessage(mWifiTracker.mScanner.obtainMessage(Scanner.MSG_SCAN));
127d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        Mockito.verify(mWifiManager, Mockito.atLeastOnce()).startScan();
128d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    }
129d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
130d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    public void testNetworkSorting() {
131d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        List<WifiConfiguration> wifiConfigs = new ArrayList<WifiConfiguration>();
132d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        List<ScanResult> scanResults = new ArrayList<ScanResult>();
133d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        String[] expectedSsids = generateTestNetworks(wifiConfigs, scanResults, true);
134d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
135d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        // Tell WifiTracker we are connected now.
136d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        sendConnected();
137d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
138d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        // Send all of the configs and scan results to the tracker.
139d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        Mockito.when(mWifiManager.getConfiguredNetworks()).thenReturn(wifiConfigs);
140d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        Mockito.when(mWifiManager.getScanResults()).thenReturn(scanResults);
1412b51cc30d523cce3609a498c466364caf3ce504eJason Monk        sendScanResultsAndProcess(false);
142d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
143d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        List<AccessPoint> accessPoints = mWifiTracker.getAccessPoints();
144d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        assertEquals("Expected number of results", NUM_NETWORKS, accessPoints.size());
145d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        for (int i = 0; i < NUM_NETWORKS; i++) {
146d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk            assertEquals("Verifying slot " + i, expectedSsids[i], accessPoints.get(i).getSsid());
147d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        }
148d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    }
149d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
150d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    public void testSavedOnly() {
1512b51cc30d523cce3609a498c466364caf3ce504eJason Monk        mWifiTracker = new WifiTracker(mContext, mWifiListener, mLooper, true, false, true,
1522b51cc30d523cce3609a498c466364caf3ce504eJason Monk                mWifiManager, mMainLooper);
153d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        mWifiTracker.mScanner = mWifiTracker.new Scanner();
154d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
155d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        List<WifiConfiguration> wifiConfigs = new ArrayList<WifiConfiguration>();
156d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        List<ScanResult> scanResults = new ArrayList<ScanResult>();
157d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        generateTestNetworks(wifiConfigs, scanResults, true);
158d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
159d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        // Tell WifiTracker we are connected now.
160d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        sendConnected();
161d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
162d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        // Send all of the configs and scan results to the tracker.
163d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        Mockito.when(mWifiManager.getConfiguredNetworks()).thenReturn(wifiConfigs);
164d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        Mockito.when(mWifiManager.getScanResults()).thenReturn(scanResults);
1652b51cc30d523cce3609a498c466364caf3ce504eJason Monk        sendScanResultsAndProcess(false);
166d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
167d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        List<AccessPoint> accessPoints = mWifiTracker.getAccessPoints();
168d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        // Only expect the first two to come back in the results.
169d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        assertEquals("Expected number of results", 2, accessPoints.size());
170d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        assertEquals(TEST_SSIDS[1], accessPoints.get(0).getSsid());
171d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        assertEquals(TEST_SSIDS[0], accessPoints.get(1).getSsid());
172d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    }
173d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
174bf3d1af3d8bd32f410aa5cc44ccdc1df593ef210Jason Monk    /**
175bf3d1af3d8bd32f410aa5cc44ccdc1df593ef210Jason Monk     * This tests the case where Settings runs this on a non-looper thread for indexing.
176bf3d1af3d8bd32f410aa5cc44ccdc1df593ef210Jason Monk     */
177bf3d1af3d8bd32f410aa5cc44ccdc1df593ef210Jason Monk    public void testSavedOnlyNoLooper() {
178bf3d1af3d8bd32f410aa5cc44ccdc1df593ef210Jason Monk        mWifiTracker = new WifiTracker(mContext, mWifiListener, mLooper, true, false, true,
179bf3d1af3d8bd32f410aa5cc44ccdc1df593ef210Jason Monk                mWifiManager,  null);
180bf3d1af3d8bd32f410aa5cc44ccdc1df593ef210Jason Monk        mWifiTracker.mScanner = mWifiTracker.new Scanner();
181bf3d1af3d8bd32f410aa5cc44ccdc1df593ef210Jason Monk
182bf3d1af3d8bd32f410aa5cc44ccdc1df593ef210Jason Monk        List<WifiConfiguration> wifiConfigs = new ArrayList<WifiConfiguration>();
183bf3d1af3d8bd32f410aa5cc44ccdc1df593ef210Jason Monk        List<ScanResult> scanResults = new ArrayList<ScanResult>();
184bf3d1af3d8bd32f410aa5cc44ccdc1df593ef210Jason Monk        generateTestNetworks(wifiConfigs, scanResults, true);
185bf3d1af3d8bd32f410aa5cc44ccdc1df593ef210Jason Monk
186bf3d1af3d8bd32f410aa5cc44ccdc1df593ef210Jason Monk        // Send all of the configs and scan results to the tracker.
187bf3d1af3d8bd32f410aa5cc44ccdc1df593ef210Jason Monk        Mockito.when(mWifiManager.getConfiguredNetworks()).thenReturn(wifiConfigs);
188bf3d1af3d8bd32f410aa5cc44ccdc1df593ef210Jason Monk        Mockito.when(mWifiManager.getScanResults()).thenReturn(scanResults);
189bf3d1af3d8bd32f410aa5cc44ccdc1df593ef210Jason Monk        mWifiTracker.forceUpdate();
190bf3d1af3d8bd32f410aa5cc44ccdc1df593ef210Jason Monk
191bf3d1af3d8bd32f410aa5cc44ccdc1df593ef210Jason Monk        List<AccessPoint> accessPoints = mWifiTracker.getAccessPoints();
192bf3d1af3d8bd32f410aa5cc44ccdc1df593ef210Jason Monk        // Only expect the first two to come back in the results.
193bf3d1af3d8bd32f410aa5cc44ccdc1df593ef210Jason Monk        assertEquals("Expected number of results", 2, accessPoints.size());
194bf3d1af3d8bd32f410aa5cc44ccdc1df593ef210Jason Monk        assertEquals(TEST_SSIDS[1], accessPoints.get(0).getSsid());
195bf3d1af3d8bd32f410aa5cc44ccdc1df593ef210Jason Monk        assertEquals(TEST_SSIDS[0], accessPoints.get(1).getSsid());
196bf3d1af3d8bd32f410aa5cc44ccdc1df593ef210Jason Monk    }
197bf3d1af3d8bd32f410aa5cc44ccdc1df593ef210Jason Monk
198d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    public void testAvailableOnly() {
1992b51cc30d523cce3609a498c466364caf3ce504eJason Monk        mWifiTracker = new WifiTracker(mContext, mWifiListener, mLooper, false, true, true,
2002b51cc30d523cce3609a498c466364caf3ce504eJason Monk                mWifiManager, mMainLooper);
201d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        mWifiTracker.mScanner = mWifiTracker.new Scanner();
202d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
203d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        List<WifiConfiguration> wifiConfigs = new ArrayList<WifiConfiguration>();
204d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        List<ScanResult> scanResults = new ArrayList<ScanResult>();
205d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        String[] expectedSsids = generateTestNetworks(wifiConfigs, scanResults, true);
206d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
207d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        // Tell WifiTracker we are connected now.
208d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        sendConnected();
209d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
210d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        // Send all of the configs and scan results to the tracker.
211d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        Mockito.when(mWifiManager.getConfiguredNetworks()).thenReturn(wifiConfigs);
212d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        Mockito.when(mWifiManager.getScanResults()).thenReturn(scanResults);
2132b51cc30d523cce3609a498c466364caf3ce504eJason Monk        sendScanResultsAndProcess(false);
214d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
215d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        // Expect the last one (sorted order) to be left off since its only saved.
216d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        List<AccessPoint> accessPoints = mWifiTracker.getAccessPoints();
217d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        assertEquals("Expected number of results", NUM_NETWORKS - 1, accessPoints.size());
218d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        for (int i = 0; i < NUM_NETWORKS - 1; i++) {
219d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk            assertEquals("Verifying slot " + i, expectedSsids[i], accessPoints.get(i).getSsid());
220d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        }
221d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    }
222d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
223d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    public void testNonEphemeralConnected() {
2242b51cc30d523cce3609a498c466364caf3ce504eJason Monk        mWifiTracker = new WifiTracker(mContext, mWifiListener, mLooper, false, true, true,
2252b51cc30d523cce3609a498c466364caf3ce504eJason Monk                mWifiManager, mMainLooper);
226d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        mWifiTracker.mScanner = mWifiTracker.new Scanner();
227d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
228d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        List<WifiConfiguration> wifiConfigs = new ArrayList<WifiConfiguration>();
229d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        List<ScanResult> scanResults = new ArrayList<ScanResult>();
2302b51cc30d523cce3609a498c466364caf3ce504eJason Monk        generateTestNetworks(wifiConfigs, scanResults, false);
231d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
232d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        // Tell WifiTracker we are connected now.
233d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        sendConnected();
234d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
235d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        // Send all of the configs and scan results to the tracker.
236d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        Mockito.when(mWifiManager.getConfiguredNetworks()).thenReturn(wifiConfigs);
237d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        Mockito.when(mWifiManager.getScanResults()).thenReturn(scanResults);
238d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        // Do this twice to catch a bug that was happening in the caching, making things ephemeral.
2392b51cc30d523cce3609a498c466364caf3ce504eJason Monk        sendScanResultsAndProcess(true);
240d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
241d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        List<AccessPoint> accessPoints = mWifiTracker.getAccessPoints();
242d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        assertEquals("Expected number of results", NUM_NETWORKS - 1, accessPoints.size());
243d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        assertFalse("Connection is not ephemeral", accessPoints.get(0).isEphemeral());
244d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        assertTrue("Connected to wifi", accessPoints.get(0).isActive());
245d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    }
246d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
2476572eae9d278e7199440aeae9a91f9418e8ab4afJason Monk    public void testEnableResumeScanning() {
2486572eae9d278e7199440aeae9a91f9418e8ab4afJason Monk        mWifiTracker.mScanner = null;
2496572eae9d278e7199440aeae9a91f9418e8ab4afJason Monk
2506572eae9d278e7199440aeae9a91f9418e8ab4afJason Monk        Intent i = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION);
2516572eae9d278e7199440aeae9a91f9418e8ab4afJason Monk        // Make sure disable/enable cycle works with no scanner (no crashing).
2526572eae9d278e7199440aeae9a91f9418e8ab4afJason Monk        i.putExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_DISABLED);
2536572eae9d278e7199440aeae9a91f9418e8ab4afJason Monk        mWifiTracker.mReceiver.onReceive(mContext, i);
2546572eae9d278e7199440aeae9a91f9418e8ab4afJason Monk        i.putExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_ENABLED);
2556572eae9d278e7199440aeae9a91f9418e8ab4afJason Monk        mWifiTracker.mReceiver.onReceive(mContext, i);
2566572eae9d278e7199440aeae9a91f9418e8ab4afJason Monk
2576572eae9d278e7199440aeae9a91f9418e8ab4afJason Monk        Mockito.when(mWifiManager.isWifiEnabled()).thenReturn(false);
2586572eae9d278e7199440aeae9a91f9418e8ab4afJason Monk        i.putExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_DISABLED);
2596572eae9d278e7199440aeae9a91f9418e8ab4afJason Monk        mWifiTracker.mReceiver.onReceive(mContext, i);
2606572eae9d278e7199440aeae9a91f9418e8ab4afJason Monk        // Now enable scanning while wifi is off, it shouldn't start.
2616572eae9d278e7199440aeae9a91f9418e8ab4afJason Monk        mWifiTracker.resumeScanning();
2626572eae9d278e7199440aeae9a91f9418e8ab4afJason Monk        assertFalse(mWifiTracker.mScanner.isScanning());
2636572eae9d278e7199440aeae9a91f9418e8ab4afJason Monk
2646572eae9d278e7199440aeae9a91f9418e8ab4afJason Monk        // Turn on wifi and make sure scanning starts.
2656572eae9d278e7199440aeae9a91f9418e8ab4afJason Monk        i.putExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_ENABLED);
2666572eae9d278e7199440aeae9a91f9418e8ab4afJason Monk        mWifiTracker.mReceiver.onReceive(mContext, i);
2676572eae9d278e7199440aeae9a91f9418e8ab4afJason Monk        assertTrue(mWifiTracker.mScanner.isScanning());
2686572eae9d278e7199440aeae9a91f9418e8ab4afJason Monk    }
2696572eae9d278e7199440aeae9a91f9418e8ab4afJason Monk
270d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    private String[] generateTestNetworks(List<WifiConfiguration> wifiConfigs,
271d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk            List<ScanResult> scanResults, boolean connectedIsEphemeral) {
272d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        String[] expectedSsids = new String[NUM_NETWORKS];
273d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
274d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        // First is just saved;
275d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        addConfig(wifiConfigs, TEST_SSIDS[0]);
276d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        // This should come last since its not available.
277d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        expectedSsids[4] = TEST_SSIDS[0];
278d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
279d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        // Second is saved and available.
280d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        addConfig(wifiConfigs, TEST_SSIDS[1]);
281d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        addResult(scanResults, TEST_SSIDS[1], 0);
282d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        // This one is going to have a couple extra results, to verify de-duplication.
283d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        addResult(scanResults, TEST_SSIDS[1], 2);
284d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        addResult(scanResults, TEST_SSIDS[1], 1);
285d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        // This should come second since it is available and saved but not connected.
286d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        expectedSsids[1] = TEST_SSIDS[1];
287d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
288d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        // Third is just available, but higher rssi.
289d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        addResult(scanResults, TEST_SSIDS[2], 3);
290d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        // This comes after the next one since it has a lower rssi.
291d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        expectedSsids[3] = TEST_SSIDS[2];
292d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
293d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        // Fourth also just available but with even higher rssi.
294d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        addResult(scanResults, TEST_SSIDS[3], 4);
295d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        // This is the highest rssi but not saved so it should be after the saved+availables.
296d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        expectedSsids[2] = TEST_SSIDS[3];
297d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
298d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        // Last is going to be connected.
299d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        int netId = WifiConfiguration.INVALID_NETWORK_ID;
300d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        if (!connectedIsEphemeral) {
301d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk            netId = addConfig(wifiConfigs, TEST_SSIDS[4]);
302d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        }
303d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        addResult(scanResults, TEST_SSIDS[4], 2);
304d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        // Setup wifi connection to be this one.
305d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        WifiInfo wifiInfo = Mockito.mock(WifiInfo.class);
306d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        Mockito.when(wifiInfo.getSSID()).thenReturn(TEST_SSIDS[4]);
307d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        Mockito.when(wifiInfo.getNetworkId()).thenReturn(netId);
308d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        Mockito.when(mWifiManager.getConnectionInfo()).thenReturn(wifiInfo);
309d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        // This should come first since it is connected.
310d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        expectedSsids[0] = TEST_SSIDS[4];
311d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
312d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        return expectedSsids;
313d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    }
314d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
315d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    private void addResult(List<ScanResult> results, String ssid, int level) {
316d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        results.add(new ScanResult(WifiSsid.createFromAsciiEncoded(ssid),
317d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk                ssid, ssid, levelToRssi(level), AccessPoint.LOWER_FREQ_24GHZ, 0));
318d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    }
319d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
320d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    public static int levelToRssi(int level) {
321d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        // Reverse level to rssi calculation based off from WifiManager.calculateSignalLevel.
322d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        final int MAX_RSSI = -55;
323d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        final int MIN_RSSI = -100;
324d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        final int NUM_LEVELS = 4;
325d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        return level * (MAX_RSSI - MIN_RSSI) / (NUM_LEVELS - 1) + MIN_RSSI;
326d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    }
327d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
328d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    private int addConfig(List<WifiConfiguration> configs, String ssid) {
329d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        WifiConfiguration config = new WifiConfiguration();
330d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        config.networkId = configs.size();
331d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        config.SSID = '"' + ssid + '"';
332d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        configs.add(config);
333d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        return config.networkId;
334d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    }
335d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
336d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    private void sendConnected() {
337d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        NetworkInfo networkInfo = Mockito.mock(NetworkInfo.class);
338d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        Mockito.when(networkInfo.isConnected()).thenReturn(true);
339d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        Mockito.when(networkInfo.getState()).thenReturn(State.CONNECTED);
340d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
341d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, networkInfo);
342d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        mWifiTracker.mReceiver.onReceive(mContext, intent);
343d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    }
344d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
3452b51cc30d523cce3609a498c466364caf3ce504eJason Monk    private void sendScanResultsAndProcess(boolean sendTwice) {
346d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        Intent i = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
347d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk        mWifiTracker.mReceiver.onReceive(mContext, i);
3482b51cc30d523cce3609a498c466364caf3ce504eJason Monk        if (sendTwice) {
3492b51cc30d523cce3609a498c466364caf3ce504eJason Monk            mWifiTracker.mReceiver.onReceive(mContext, i);
3502b51cc30d523cce3609a498c466364caf3ce504eJason Monk        }
3512b51cc30d523cce3609a498c466364caf3ce504eJason Monk        waitForThreads();
3522b51cc30d523cce3609a498c466364caf3ce504eJason Monk    }
3532b51cc30d523cce3609a498c466364caf3ce504eJason Monk
3542b51cc30d523cce3609a498c466364caf3ce504eJason Monk    private void waitForThreads() {
3552b51cc30d523cce3609a498c466364caf3ce504eJason Monk        // Run all processing.
3562b51cc30d523cce3609a498c466364caf3ce504eJason Monk        mWorkerThread.quitSafely();
3572b51cc30d523cce3609a498c466364caf3ce504eJason Monk        try {
3582b51cc30d523cce3609a498c466364caf3ce504eJason Monk            mWorkerThread.join();
3592b51cc30d523cce3609a498c466364caf3ce504eJason Monk        } catch (InterruptedException e) {
3602b51cc30d523cce3609a498c466364caf3ce504eJason Monk        }
3612b51cc30d523cce3609a498c466364caf3ce504eJason Monk        // Send all callbacks.
3622b51cc30d523cce3609a498c466364caf3ce504eJason Monk        mMainThread.quitSafely();
3632b51cc30d523cce3609a498c466364caf3ce504eJason Monk        try {
3642b51cc30d523cce3609a498c466364caf3ce504eJason Monk            mMainThread.join();
3652b51cc30d523cce3609a498c466364caf3ce504eJason Monk        } catch (InterruptedException e) {
3662b51cc30d523cce3609a498c466364caf3ce504eJason Monk        }
367d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk    }
368d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk
369d52356aa5e82c7c5db61672bbe8d0f44861f3e59Jason Monk}
370