summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe LaPenna <jlapenna@google.com>2017-02-15 17:31:38 -0800
committerJoe LaPenna <jlapenna@google.com>2017-02-22 13:14:23 -0800
commit408ffe650e232c941168713e1203aafa4cdd06ed (patch)
tree43416c6cc078748c95305e835bd803b7ddad9711
parent197976bcaf5ac84447dbfdfb7ed6e5cab2654b14 (diff)
downloadNetworkRecommendation-408ffe650e232c941168713e1203aafa4cdd06ed.tar.gz
Update notify code.
Test: mma NetworkRecommendation RunNetworkRecommendationRoboTests Bug: 34944625 Change-Id: I102afdcd78cb0dc013b7c7965fd8d78d346e9d01
-rw-r--r--robotests/src/android/net/RecommendationResult.java48
-rw-r--r--robotests/src/com/android/networkrecommendation/BroadcastIntentTestHelper.java63
-rw-r--r--robotests/src/com/android/networkrecommendation/TestData.java41
-rw-r--r--robotests/src/com/android/networkrecommendation/notify/WifiNotificationControllerTest.java371
-rw-r--r--robotests/src/com/android/networkrecommendation/notify/WifiNotificationHelperTest.java149
-rw-r--r--robotests/src/com/android/networkrecommendation/shadows/BitmapGetPixelsShadow.java14
-rw-r--r--robotests/src/com/android/networkrecommendation/util/ScanResultUtilTest.java2
-rw-r--r--robotests/src/com/android/networkrecommendation/util/SsidUtilTest.java2
-rw-r--r--src/com/android/networkrecommendation/notify/WifiNotificationController.java430
-rw-r--r--src/com/android/networkrecommendation/notify/WifiNotificationHelper.java216
-rw-r--r--src/com/android/networkrecommendation/util/RoboCompatUtil.java11
-rw-r--r--src/com/android/networkrecommendation/util/ScanResultUtil.java1
-rw-r--r--tests/src/com/android/networkrecommendation/notify/WifiNotificationControllerTest.java269
13 files changed, 1056 insertions, 561 deletions
diff --git a/robotests/src/android/net/RecommendationResult.java b/robotests/src/android/net/RecommendationResult.java
new file mode 100644
index 0000000..dafb1fc
--- /dev/null
+++ b/robotests/src/android/net/RecommendationResult.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017 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 android.net;
+
+import android.annotation.Nullable;
+import android.net.wifi.WifiConfiguration;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A placeholder class to prevent ClassNotFound exceptions caused by lack of visibility.
+ */
+public class RecommendationResult implements Parcelable {
+
+ protected RecommendationResult(Parcel in) {
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ }
+
+ public boolean hasRecommendation() {
+ return false;
+ }
+
+ @Nullable
+ public WifiConfiguration getWifiConfiguration() {
+ return null;
+ }
+}
diff --git a/robotests/src/com/android/networkrecommendation/BroadcastIntentTestHelper.java b/robotests/src/com/android/networkrecommendation/BroadcastIntentTestHelper.java
new file mode 100644
index 0000000..fd674b8
--- /dev/null
+++ b/robotests/src/com/android/networkrecommendation/BroadcastIntentTestHelper.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 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.networkrecommendation;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.NetworkInfo;
+import android.net.wifi.WifiManager;
+import android.os.PowerManager;
+
+/** Convenience methods for sending Intent broadcasts. */
+public class BroadcastIntentTestHelper {
+
+ private final Context mContext;
+
+ public BroadcastIntentTestHelper(Context context) {
+ mContext = context;
+ }
+
+ public void sendPowerSaveModeChanged() {
+ Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
+ mContext.sendBroadcast(intent);
+ }
+
+ public void sendWifiStateChanged() {
+ Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION);
+ mContext.sendBroadcast(intent);
+ }
+
+ public void sendNetworkStateChanged(NetworkInfo networkInfo) {
+ Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+ intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, networkInfo);
+ mContext.sendBroadcast(intent);
+ }
+
+ public void sendScanResultsAvailable() {
+ Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
+ mContext.sendBroadcast(intent);
+ }
+
+ public void sendWifiApStateChanged() {
+ Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
+ mContext.sendBroadcast(intent);
+ }
+
+ public void sendConfiguredNetworksChanged() {
+ Intent intent = new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
+ mContext.sendBroadcast(intent);
+ }
+}
diff --git a/robotests/src/com/android/networkrecommendation/TestData.java b/robotests/src/com/android/networkrecommendation/TestData.java
new file mode 100644
index 0000000..aad9d5b
--- /dev/null
+++ b/robotests/src/com/android/networkrecommendation/TestData.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2017 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.networkrecommendation;
+
+import com.android.networkrecommendation.util.SsidUtil;
+
+/**
+ * Stock objects which can be re-used in multiple tests.
+ *
+ * <p>Objects here should be kept simple and generic; test-specific variants should be created
+ * inside tests as opposed to here.
+ */
+public class TestData {
+
+ // SSID and BSSID values
+ public static final String UNQUOTED_SSID_1 = "ssid1";
+ public static final String UNQUOTED_SSID_2 = "ssid2";
+ public static final String UNQUOTED_SSID_3 = "ssid3";
+ public static final String SSID_1 = SsidUtil.quoteSsid(UNQUOTED_SSID_1);
+ public static final String SSID_2 = SsidUtil.quoteSsid(UNQUOTED_SSID_2);
+ public static final String SSID_3 = SsidUtil.quoteSsid(UNQUOTED_SSID_3);
+ public static final String BSSID_1 = "01:01:01:01:01:01";
+ public static final String BSSID_2 = "02:02:02:02:02:02";
+ public static final String BSSID_3 = "03:03:03:03:03:03";
+
+ // Can't instantiate.
+ private TestData() {}
+}
diff --git a/robotests/src/com/android/networkrecommendation/notify/WifiNotificationControllerTest.java b/robotests/src/com/android/networkrecommendation/notify/WifiNotificationControllerTest.java
new file mode 100644
index 0000000..30098ce
--- /dev/null
+++ b/robotests/src/com/android/networkrecommendation/notify/WifiNotificationControllerTest.java
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2017 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.networkrecommendation.notify;
+
+import static com.android.networkrecommendation.PlatformTestObjectFactory.createOpenNetworkScanResult;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.content.ContentResolver;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.DetailedState;
+import android.net.NetworkInfo.State;
+import android.net.RecommendationRequest;
+import android.net.RecommendationResult;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
+import android.os.Handler;
+import android.provider.Settings;
+import com.android.networkrecommendation.BroadcastIntentTestHelper;
+import com.android.networkrecommendation.SynchronousNetworkRecommendationProvider;
+import com.android.networkrecommendation.TestData;
+import com.android.networkrecommendation.util.RoboCompatUtil;
+import com.google.common.collect.Lists;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.shadows.ShadowLooper;
+import org.robolectric.shadows.ShadowSettings;
+
+/**
+ * Instrumentation tests for {@link com.android.networkrecommendation.WifiNotificationController}.
+ */
+@RunWith(RobolectricTestRunner.class)
+@Config(manifest = "packages/services/NetworkRecommendation/AndroidManifest.xml", sdk = 23)
+public class WifiNotificationControllerTest {
+
+ @Mock private WifiManager mWifiManager;
+ @Mock private NotificationManager mNotificationManager;
+ @Mock private WifiNotificationHelper mWifiNotificationHelper;
+ @Mock private SynchronousNetworkRecommendationProvider mNetworkRecommendationProvider;
+ @Mock private NetworkInfo mNetworkInfo;
+ @Mock private RecommendationResult mRecommendationResult;
+ @Mock private RoboCompatUtil mRoboCompatUtil;
+ @Captor private ArgumentCaptor<List<ScanResult>> mScanResultCaptor;
+ private ContentResolver mContentResolver;
+ private Handler mHandler;
+ private WifiNotificationController mWifiNotificationController;
+ private BroadcastIntentTestHelper mBroadcastIntentTestHelper;
+
+ /** Initialize objects before each test run. */
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ // Needed for the NotificationEnabledSettingObserver.
+ mContentResolver = RuntimeEnvironment.application.getContentResolver();
+ ShadowSettings.ShadowGlobal.putInt(
+ mContentResolver, Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 1);
+ mHandler = new Handler(ShadowLooper.getMainLooper());
+
+ RoboCompatUtil.setInstanceForTesting(mRoboCompatUtil);
+
+ mWifiNotificationController =
+ new WifiNotificationController(
+ RuntimeEnvironment.application,
+ mContentResolver,
+ mHandler,
+ mNetworkRecommendationProvider,
+ mWifiManager,
+ mNotificationManager,
+ mWifiNotificationHelper);
+ mWifiNotificationController.start();
+
+ when(mNetworkInfo.getState()).thenReturn(State.UNKNOWN);
+ mBroadcastIntentTestHelper = new BroadcastIntentTestHelper(RuntimeEnvironment.application);
+ }
+
+ private void setOpenAccessPoints() {
+ List<ScanResult> scanResults =
+ Lists.newArrayList(
+ createOpenNetworkScanResult(TestData.UNQUOTED_SSID_1, TestData.BSSID_1),
+ createOpenNetworkScanResult(TestData.UNQUOTED_SSID_2, TestData.BSSID_2),
+ createOpenNetworkScanResult(TestData.UNQUOTED_SSID_3, TestData.BSSID_3));
+ assertFalse(scanResults.isEmpty());
+ when(mWifiManager.getScanResults()).thenReturn(scanResults);
+ }
+
+ private static WifiConfiguration createFakeConfig() {
+ WifiConfiguration config = new WifiConfiguration();
+ config.SSID = TestData.SSID_1;
+ config.BSSID = TestData.BSSID_1;
+ config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+ return config;
+ }
+
+ private void createFakeBitmap() {
+ when(mWifiNotificationHelper.createNotificationBadgeBitmap(any(), any()))
+ .thenReturn(Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888));
+ }
+
+ /**
+ * When the NetworkRecommendationService associated with this WifiNotificationController is
+ * unbound, this WifiWakeupController should no longer function.
+ */
+ @Test
+ public void wifiNotificationControllerStopped() {
+ mWifiNotificationController.stop();
+
+ assertFalse(
+ ShadowApplication.getInstance()
+ .hasReceiverForIntent(
+ new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)));
+ }
+
+ /** Verifies that a notification is displayed (and retracted) given system events. */
+ @Test
+ public void verifyNotificationDisplayedWhenNetworkRecommended() throws Exception {
+ when(mWifiManager.getWifiState()).thenReturn(WifiManager.WIFI_STATE_ENABLED);
+
+ mBroadcastIntentTestHelper.sendWifiStateChanged();
+ when(mNetworkInfo.getDetailedState()).thenReturn(DetailedState.DISCONNECTED);
+ mBroadcastIntentTestHelper.sendNetworkStateChanged(mNetworkInfo);
+ setOpenAccessPoints();
+ createFakeBitmap();
+
+ when(mNetworkRecommendationProvider.requestRecommendation(any(RecommendationRequest.class)))
+ .thenReturn(mRecommendationResult);
+ when(mRecommendationResult.getWifiConfiguration()).thenReturn(createFakeConfig());
+
+ // The notification should not be displayed after only two scan results.
+ mBroadcastIntentTestHelper.sendScanResultsAvailable();
+ mBroadcastIntentTestHelper.sendScanResultsAvailable();
+ verify(mNotificationManager, never())
+ .notify(anyString(), anyInt(), any(Notification.class));
+
+ verify(mWifiManager, times(2)).getScanResults();
+
+ // Changing to and from "SCANNING" state should not affect the counter.
+ when(mNetworkInfo.getDetailedState()).thenReturn(DetailedState.SCANNING);
+ mBroadcastIntentTestHelper.sendNetworkStateChanged(mNetworkInfo);
+ when(mNetworkInfo.getDetailedState()).thenReturn(DetailedState.DISCONNECTED);
+ mBroadcastIntentTestHelper.sendNetworkStateChanged(mNetworkInfo);
+
+ verify(mNotificationManager, never())
+ .notify(anyString(), anyInt(), any(Notification.class));
+
+ // The third scan result notification will trigger the notification.
+ mBroadcastIntentTestHelper.sendScanResultsAvailable();
+
+ verify(mWifiNotificationHelper)
+ .createMainNotification(any(WifiConfiguration.class), any(Bitmap.class));
+ verify(mNotificationManager).notify(anyString(), anyInt(), any(Notification.class));
+ verify(mNotificationManager, never()).cancel(anyString(), anyInt());
+ }
+
+ /** Verifies that a notification is not displayed for bad networks. */
+ @Test
+ public void verifyNotificationNotDisplayedWhenNoNetworkRecommended() throws Exception {
+ when(mWifiManager.getWifiState()).thenReturn(WifiManager.WIFI_STATE_ENABLED);
+
+ mBroadcastIntentTestHelper.sendWifiStateChanged();
+ when(mNetworkInfo.getDetailedState()).thenReturn(DetailedState.DISCONNECTED);
+ mBroadcastIntentTestHelper.sendNetworkStateChanged(mNetworkInfo);
+ setOpenAccessPoints();
+ createFakeBitmap();
+
+ // Recommendation result with no WifiConfiguration returned.
+ when(mNetworkRecommendationProvider.requestRecommendation(any(RecommendationRequest.class)))
+ .thenReturn(mRecommendationResult);
+ when(mRecommendationResult.getWifiConfiguration()).thenReturn(null);
+
+ mBroadcastIntentTestHelper.sendScanResultsAvailable();
+ mBroadcastIntentTestHelper.sendScanResultsAvailable();
+ mBroadcastIntentTestHelper.sendScanResultsAvailable();
+ mBroadcastIntentTestHelper.sendScanResultsAvailable();
+ verify(mNotificationManager, never())
+ .notify(anyString(), anyInt(), any(Notification.class));
+ }
+
+ /**
+ * Verifies the notifications flow (Connect -> connecting -> connected) when user clicks on
+ * Connect button.
+ */
+ @Test
+ public void verifyNotificationsFlowOnConnectToNetwork() throws Exception {
+ when(mWifiManager.getWifiState()).thenReturn(WifiManager.WIFI_STATE_ENABLED);
+
+ mBroadcastIntentTestHelper.sendWifiStateChanged();
+ when(mNetworkInfo.getDetailedState()).thenReturn(DetailedState.DISCONNECTED);
+ mBroadcastIntentTestHelper.sendNetworkStateChanged(mNetworkInfo);
+ setOpenAccessPoints();
+ createFakeBitmap();
+
+ when(mNetworkRecommendationProvider.requestRecommendation(any(RecommendationRequest.class)))
+ .thenReturn(mRecommendationResult);
+ when(mRecommendationResult.getWifiConfiguration()).thenReturn(createFakeConfig());
+
+ mBroadcastIntentTestHelper.sendScanResultsAvailable();
+ mBroadcastIntentTestHelper.sendScanResultsAvailable();
+ mBroadcastIntentTestHelper.sendScanResultsAvailable();
+ verify(mWifiNotificationHelper)
+ .createMainNotification(any(WifiConfiguration.class), any(Bitmap.class));
+ verify(mNotificationManager).notify(anyString(), anyInt(), any(Notification.class));
+
+ // Send connect intent, should attempt to connect to Wi-Fi
+ Intent intent =
+ new Intent(WifiNotificationController.ACTION_CONNECT_TO_RECOMMENDED_NETWORK);
+ ShadowApplication.getInstance().sendBroadcast(intent);
+ verify(mRoboCompatUtil).connectToWifi(any(WifiManager.class), any(WifiConfiguration.class));
+ verify(mWifiNotificationHelper)
+ .createConnectingNotification(any(WifiConfiguration.class), any(Bitmap.class));
+
+ // Show connecting notification.
+ verify(mNotificationManager, times(2))
+ .notify(anyString(), anyInt(), any(Notification.class));
+
+ // Verify show connected notification.
+ when(mNetworkInfo.getDetailedState()).thenReturn(DetailedState.CONNECTED);
+ mBroadcastIntentTestHelper.sendNetworkStateChanged(mNetworkInfo);
+ verify(mWifiNotificationHelper)
+ .createConnectedNotification(any(WifiConfiguration.class), any(Bitmap.class));
+ verify(mNotificationManager, times(3))
+ .notify(anyString(), anyInt(), any(Notification.class));
+
+ // Dismissed the connected notification.
+ ShadowLooper.runMainLooperToNextTask();
+ verify(mNotificationManager).cancel(anyString(), anyInt());
+ }
+
+ /** Verifies the Failure to Connect notification after attempting to connect. */
+ @Test
+ public void verifyNotificationsFlowOnFailedToConnectToNetwork() throws Exception {
+ when(mWifiManager.getWifiState()).thenReturn(WifiManager.WIFI_STATE_ENABLED);
+
+ mBroadcastIntentTestHelper.sendWifiStateChanged();
+ when(mNetworkInfo.getDetailedState()).thenReturn(DetailedState.DISCONNECTED);
+ mBroadcastIntentTestHelper.sendNetworkStateChanged(mNetworkInfo);
+ setOpenAccessPoints();
+ createFakeBitmap();
+
+ when(mNetworkRecommendationProvider.requestRecommendation(any(RecommendationRequest.class)))
+ .thenReturn(mRecommendationResult);
+ when(mRecommendationResult.getWifiConfiguration()).thenReturn(createFakeConfig());
+
+ mBroadcastIntentTestHelper.sendScanResultsAvailable();
+ mBroadcastIntentTestHelper.sendScanResultsAvailable();
+ mBroadcastIntentTestHelper.sendScanResultsAvailable();
+ verify(mWifiNotificationHelper)
+ .createMainNotification(any(WifiConfiguration.class), any(Bitmap.class));
+ verify(mNotificationManager).notify(anyString(), anyInt(), any(Notification.class));
+
+ // Send connect intent, should attempt to connect to Wi-Fi
+ Intent intent =
+ new Intent(WifiNotificationController.ACTION_CONNECT_TO_RECOMMENDED_NETWORK);
+ ShadowApplication.getInstance().sendBroadcast(intent);
+ verify(mRoboCompatUtil).connectToWifi(any(WifiManager.class), any(WifiConfiguration.class));
+ verify(mWifiNotificationHelper)
+ .createConnectingNotification(any(WifiConfiguration.class), any(Bitmap.class));
+
+ // Show connecting notification.
+ verify(mNotificationManager, times(2))
+ .notify(anyString(), anyInt(), any(Notification.class));
+
+ // Show failed to connect notification.
+ ShadowLooper.runMainLooperToNextTask();
+ verify(mWifiNotificationHelper)
+ .createFailedToConnectNotification(any(WifiConfiguration.class));
+
+ // Dismissed the cancel notification.
+ ShadowLooper.runMainLooperToNextTask();
+ verify(mNotificationManager).cancel(anyString(), anyInt());
+ }
+
+ /** Verifies the flow where notification is dismissed. */
+ @Test
+ public void verifyNotificationsFlowOnDismissMainNotification() throws Exception {
+ when(mWifiManager.getWifiState()).thenReturn(WifiManager.WIFI_STATE_ENABLED);
+
+ mBroadcastIntentTestHelper.sendWifiStateChanged();
+ when(mNetworkInfo.getDetailedState()).thenReturn(DetailedState.DISCONNECTED);
+ mBroadcastIntentTestHelper.sendNetworkStateChanged(mNetworkInfo);
+ setOpenAccessPoints();
+ createFakeBitmap();
+
+ when(mNetworkRecommendationProvider.requestRecommendation(any(RecommendationRequest.class)))
+ .thenReturn(mRecommendationResult);
+ when(mRecommendationResult.getWifiConfiguration()).thenReturn(createFakeConfig());
+
+ mBroadcastIntentTestHelper.sendScanResultsAvailable();
+ mBroadcastIntentTestHelper.sendScanResultsAvailable();
+ mBroadcastIntentTestHelper.sendScanResultsAvailable();
+
+ // Show main notification
+ verify(mWifiNotificationHelper)
+ .createMainNotification(any(WifiConfiguration.class), any(Bitmap.class));
+ verify(mNotificationManager).notify(anyString(), anyInt(), any(Notification.class));
+
+ // Send dismiss intent
+ Intent intent = new Intent(WifiNotificationController.ACTION_NOTIFICATION_DELETED);
+ ShadowApplication.getInstance().sendBroadcast(intent);
+ }
+
+ /** Verifies saved networks are skipped when getting network recommendations */
+ @Test
+ public void verifyNotificationsFlowSkipSavedNetworks() throws Exception {
+ when(mWifiManager.getWifiState()).thenReturn(WifiManager.WIFI_STATE_ENABLED);
+
+ mBroadcastIntentTestHelper.sendWifiStateChanged();
+ when(mNetworkInfo.getDetailedState()).thenReturn(DetailedState.DISCONNECTED);
+ mBroadcastIntentTestHelper.sendNetworkStateChanged(mNetworkInfo);
+
+ // First scan result and saved WifiConfiguration should be equal
+ when(mWifiManager.getScanResults())
+ .thenReturn(
+ Lists.newArrayList(
+ createOpenNetworkScanResult(
+ TestData.UNQUOTED_SSID_1, TestData.BSSID_1)));
+ when(mWifiManager.getConfiguredNetworks())
+ .thenReturn(Lists.newArrayList(createFakeConfig()));
+ mBroadcastIntentTestHelper.sendScanResultsAvailable();
+ verify(mRoboCompatUtil).createRecommendationRequest(mScanResultCaptor.capture());
+
+ assertEquals(new ArrayList<>(), mScanResultCaptor.getValue());
+ }
+
+ /** Test dump() does not crash. */
+ @Test
+ public void testDump() {
+ StringWriter stringWriter = new StringWriter();
+ mWifiNotificationController.dump(
+ new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);
+ }
+}
diff --git a/robotests/src/com/android/networkrecommendation/notify/WifiNotificationHelperTest.java b/robotests/src/com/android/networkrecommendation/notify/WifiNotificationHelperTest.java
new file mode 100644
index 0000000..6351600
--- /dev/null
+++ b/robotests/src/com/android/networkrecommendation/notify/WifiNotificationHelperTest.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2017 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.networkrecommendation.notify;
+
+import static com.android.networkrecommendation.PlatformTestObjectFactory.createOpenNetworkScanResult;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.net.ScoredNetwork;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
+import com.android.networkrecommendation.SynchronousNetworkRecommendationProvider;
+import com.android.networkrecommendation.TestData;
+import com.android.networkrecommendation.shadows.BitmapGetPixelsShadow;
+import com.android.networkrecommendation.util.RoboCompatUtil;
+import com.google.common.collect.Lists;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowSettings;
+
+/** Unit tests for {@link WifiNotificationHelper} */
+@RunWith(RobolectricTestRunner.class)
+@Config(manifest = "packages/services/NetworkRecommendation/AndroidManifest.xml", sdk = 23,
+shadows={BitmapGetPixelsShadow.class})
+public class WifiNotificationHelperTest {
+
+ private Context mContext;
+
+ @Mock
+ private SynchronousNetworkRecommendationProvider mSynchronousNetworkRecommendationProvider;
+
+ @Mock private RoboCompatUtil mRoboCompatUtil;
+
+ private WifiNotificationHelper mWifiNotificationHelper;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ RoboCompatUtil.setInstanceForTesting(mRoboCompatUtil);
+ mContext = RuntimeEnvironment.application;
+
+ mWifiNotificationHelper =
+ new WifiNotificationHelper(mContext, mSynchronousNetworkRecommendationProvider);
+ }
+
+ private static WifiConfiguration createFakeConfig() {
+ WifiConfiguration config = new WifiConfiguration();
+ config.SSID = TestData.SSID_1;
+ config.BSSID = TestData.BSSID_1;
+ config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+ return config;
+ }
+
+ private static Bitmap createFakeIcon() {
+ return Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
+ }
+
+ private static void assertValidNotification(Notification notification) {
+ assertNotNull(notification);
+ assertNotNull(notification.getSmallIcon());
+ assertNotNull(notification.getLargeIcon());
+ }
+
+ @Test
+ public void createMainNotification() {
+ assertValidNotification(
+ mWifiNotificationHelper.createMainNotification(
+ createFakeConfig(), createFakeIcon()));
+ }
+
+ @Test
+ public void createConnectingNotification() {
+ assertValidNotification(
+ mWifiNotificationHelper.createConnectingNotification(
+ createFakeConfig(), createFakeIcon()));
+ }
+
+ @Test
+ public void createConnectedNotification() {
+ assertValidNotification(
+ mWifiNotificationHelper.createConnectedNotification(
+ createFakeConfig(), createFakeIcon()));
+ }
+
+ @Test
+ public void createFailedToConnectNotification() {
+ assertValidNotification(
+ mWifiNotificationHelper.createFailedToConnectNotification(createFakeConfig()));
+ }
+
+ @Test
+ public void createNotificationBadgeBitmap() {
+ WifiConfiguration wifiConfig = createFakeConfig();
+ List<ScanResult> scanResultList =
+ Lists.newArrayList(createOpenNetworkScanResult(wifiConfig.SSID, wifiConfig.BSSID));
+ when(mSynchronousNetworkRecommendationProvider.getCachedScoredNetwork(any()))
+ .thenReturn(Mockito.mock(ScoredNetwork.class));
+ when(mRoboCompatUtil.calculateBadge(any(), anyInt())).thenReturn(ScoredNetwork.BADGING_4K);
+ when(mRoboCompatUtil.getWifiIcon(anyInt(), anyInt(), any()))
+ .thenReturn(mContext.getDrawable(android.R.drawable.stat_sys_warning));
+
+ assertNotNull(
+ mWifiNotificationHelper.createNotificationBadgeBitmap(wifiConfig, scanResultList));
+
+ ShadowSettings.ShadowGlobal.putInt(
+ mContext.getContentResolver(),
+ WifiNotificationHelper.NETWORK_SCORING_UI_ENABLED,
+ 1);
+ assertNotNull(
+ mWifiNotificationHelper.createNotificationBadgeBitmap(wifiConfig, scanResultList));
+ }
+
+ @Test
+ public void createNotificationBadgeBitmap_noMatchingScanResults() {
+ WifiConfiguration wifiConfig = createFakeConfig();
+ List<ScanResult> scanResultList = new ArrayList<>();
+
+ assertNull(
+ mWifiNotificationHelper.createNotificationBadgeBitmap(wifiConfig, scanResultList));
+ }
+}
diff --git a/robotests/src/com/android/networkrecommendation/shadows/BitmapGetPixelsShadow.java b/robotests/src/com/android/networkrecommendation/shadows/BitmapGetPixelsShadow.java
new file mode 100644
index 0000000..8912305
--- /dev/null
+++ b/robotests/src/com/android/networkrecommendation/shadows/BitmapGetPixelsShadow.java
@@ -0,0 +1,14 @@
+package com.android.networkrecommendation.shadows;
+
+import android.annotation.ColorInt;
+import android.graphics.Bitmap;
+
+import org.robolectric.annotation.Implements;
+import org.robolectric.shadows.ShadowBitmap;
+
+@Implements(Bitmap.class)
+public class BitmapGetPixelsShadow extends ShadowBitmap {
+ public void getPixels(@ColorInt int[] pixels, int offset, int stride,
+ int x, int y, int width, int height) {
+ }
+}
diff --git a/robotests/src/com/android/networkrecommendation/util/ScanResultUtilTest.java b/robotests/src/com/android/networkrecommendation/util/ScanResultUtilTest.java
index 6900c9b..a55a598 100644
--- a/robotests/src/com/android/networkrecommendation/util/ScanResultUtilTest.java
+++ b/robotests/src/com/android/networkrecommendation/util/ScanResultUtilTest.java
@@ -36,7 +36,7 @@ import org.robolectric.annotation.Config;
/** Unit tests for {@link ScanResultUtil}. */
@RunWith(RobolectricTestRunner.class)
-@Config(sdk = 21, manifest = Config.NONE)
+@Config(manifest = "packages/services/NetworkRecommendation/AndroidManifest.xml", sdk = 23)
public class ScanResultUtilTest {
@Before
diff --git a/robotests/src/com/android/networkrecommendation/util/SsidUtilTest.java b/robotests/src/com/android/networkrecommendation/util/SsidUtilTest.java
index 25672b4..053c38d 100644
--- a/robotests/src/com/android/networkrecommendation/util/SsidUtilTest.java
+++ b/robotests/src/com/android/networkrecommendation/util/SsidUtilTest.java
@@ -25,7 +25,7 @@ import org.robolectric.annotation.Config;
/** Tests for {@link SsidUtil}. */
@RunWith(RobolectricTestRunner.class)
-@Config(manifest = Config.NONE)
+@Config(manifest = "packages/services/NetworkRecommendation/AndroidManifest.xml", sdk = 23)
public class SsidUtilTest {
@Test
diff --git a/src/com/android/networkrecommendation/notify/WifiNotificationController.java b/src/com/android/networkrecommendation/notify/WifiNotificationController.java
index a7afcdd..28fafc2 100644
--- a/src/com/android/networkrecommendation/notify/WifiNotificationController.java
+++ b/src/com/android/networkrecommendation/notify/WifiNotificationController.java
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.android.networkrecommendation.notify;
import android.app.Notification;
@@ -34,110 +33,115 @@ import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.provider.Settings;
+import android.support.annotation.IntDef;
import android.support.annotation.Nullable;
-import android.support.annotation.VisibleForTesting;
-
import com.android.networkrecommendation.R;
import com.android.networkrecommendation.SynchronousNetworkRecommendationProvider;
-
+import com.android.networkrecommendation.util.RoboCompatUtil;
+import com.android.networkrecommendation.util.ScanResultUtil;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
-/**
- * Takes care of handling the "open wi-fi network available" notification
- * @hide
- */
+/** Takes care of handling the "open wi-fi network available" notification */
public class WifiNotificationController {
- /**
- * The icon to show in the 'available networks' notification. This will also
- * be the ID of the Notification given to the NotificationManager.
- */
- private static final int ICON_NETWORKS_AVAILABLE = R.drawable.stat_notify_wifi_in_range;
- /**
- * When a notification is shown, we wait this amount before possibly showing it again.
- */
+ /** The unique ID of the Notification given to the NotificationManager. */
+ private static final int NOTIFICATION_ID = R.string.wifi_available;
+
+ /** When a notification is shown, we wait this amount before possibly showing it again. */
private final long mNotificationRepeatDelayMs;
- /**
- * Whether the user has set the setting to show the 'available networks' notification.
- */
+
+ /** Whether the user has set the setting to show the 'available networks' notification. */
private boolean mNotificationEnabled;
- /**
- * Observes the user setting to keep {@link #mNotificationEnabled} in sync.
- */
+
+ /** Observes the user setting to keep {@link #mNotificationEnabled} in sync. */
private final NotificationEnabledSettingObserver mNotificationEnabledSettingObserver;
+
/**
- * The {@link System#currentTimeMillis()} must be at least this value for us
- * to show the notification again.
+ * The {@link System#currentTimeMillis()} must be at least this value for us to show the
+ * notification again.
*/
private long mNotificationRepeatTime;
+
+ /** These are all of the possible states for the open networks available notification. */
+ @IntDef({
+ State.HIDDEN,
+ State.SHOWING_CONNECT_ACTIONS,
+ State.SHOWING_CONNECTING,
+ State.SHOWING_CONNECTED,
+ State.SHOWING_FAILURE
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface State {
+ int HIDDEN = 0;
+ int SHOWING_CONNECT_ACTIONS = 1;
+ int SHOWING_CONNECTING = 2;
+ int SHOWING_CONNECTED = 3;
+ int SHOWING_FAILURE = 4;
+ }
+
/**
- * Whether the notification is being shown.
+ * The {@link System#currentTimeMillis()} must be at least this value to log that open networks
+ * are available.
*/
- private boolean mNotificationShown;
+ private long mOpenNetworksLoggingRepeatTime;
+
+ /** Current state of the notification. */
+ @State private int mNotificationState = State.HIDDEN;
+
/**
- * The number of continuous scans that must occur before consider the
- * supplicant in a scanning state. This allows supplicant to associate with
- * remembered networks that are in the scan results.
+ * The number of continuous scans that must occur before consider the supplicant in a scanning
+ * state. This allows supplicant to associate with remembered networks that are in the scan
+ * results.
*/
private static final int NUM_SCANS_BEFORE_ACTUALLY_SCANNING = 3;
+
/**
- * The number of scans since the last network state change. When this
- * exceeds {@link #NUM_SCANS_BEFORE_ACTUALLY_SCANNING}, we consider the
- * supplicant to actually be scanning. When the network state changes to
- * something other than scanning, we reset this to 0.
+ * The number of scans since the last network state change. When this exceeds {@link
+ * #NUM_SCANS_BEFORE_ACTUALLY_SCANNING}, we consider the supplicant to actually be scanning.
+ * When the network state changes to something other than scanning, we reset this to 0.
*/
private int mNumScansSinceNetworkStateChange;
- /**
- * Time in milliseconds to display the Connecting notification.
- */
+
+ /** Time in milliseconds to display the Connecting notification. */
private static final int TIME_TO_SHOW_CONNECTING_MILLIS = 10000;
- /**
- * Time in milliseconds to display the Connected notification.
- */
+
+ /** Time in milliseconds to display the Connected notification. */
private static final int TIME_TO_SHOW_CONNECTED_MILLIS = 5000;
- /**
- * Time in milliseconds to display the Failed To Connect notification.
- */
+
+ /** Time in milliseconds to display the Failed To Connect notification. */
private static final int TIME_TO_SHOW_FAILED_MILLIS = 5000;
+
/**
- * Try to connect to provided WifiConfiguration since user wants to
- * connect to the recommended open access point.
+ * Try to connect to provided WifiConfiguration since user wants to connect to the recommended
+ * open access point.
*/
static final String ACTION_CONNECT_TO_RECOMMENDED_NETWORK =
- "com.android.networkrecommendation.CONNECT_TO_RECOMMENDED_NETWORK";
- /**
- * Handles behavior when notification is deleted.
- */
+ "com.android.networkrecommendation.notify.CONNECT_TO_RECOMMENDED_NETWORK";
+
+ /** Open wifi picker to see all available networks. */
+ static final String ACTION_PICK_WIFI_NETWORK =
+ "com.android.networkrecommendation.notify.ACTION_PICK_WIFI_NETWORK";
+
+ /** Handles behavior when notification is deleted. */
static final String ACTION_NOTIFICATION_DELETED =
- "com.android.networkrecommendation.NOTIFICATION_DELETED";
- /**
- * Network recommended by {@link NetworkScoreManager#requestRecommendation}.
- */
+ "com.android.networkrecommendation.notify.NOTIFICATION_DELETED";
+
+ /** Network recommended by {@link NetworkScoreManager#requestRecommendation}. */
private WifiConfiguration mRecommendedNetwork;
+
+ /** Badge icon of the recommended network. */
private Bitmap mNotificationBadgeBitmap;
- /**
- * Whether {@link WifiNotificationController} has been started.
- */
+
+ /** Whether {@link WifiNotificationController} has been started. */
private final AtomicBoolean mStarted;
- /**
- * Runnable to dismiss notification.
- */
- @VisibleForTesting
- final Runnable mDismissNotificationRunnable = () -> {
- removeNotification();
- };
- /**
- * Runnable to show Failed To Connect notification.
- */
- @VisibleForTesting
- final Runnable mShowFailedToConnectNotificationRunnable = () -> {
- showFailedToConnectNotification();
- };
- private static final String TAG = "WifiNotification";
+ private static final String NOTIFICATION_TAG = "WifiNotification";
private final Context mContext;
private final Handler mHandler;
@@ -150,10 +154,13 @@ public class WifiNotificationController {
private NetworkInfo.DetailedState mDetailedState;
private volatile int mWifiState;
- public WifiNotificationController(Context context, ContentResolver contentResolver,
+ public WifiNotificationController(
+ Context context,
+ ContentResolver contentResolver,
Handler handler,
SynchronousNetworkRecommendationProvider networkRecommendationProvider,
- WifiManager wifiManager, NotificationManager notificationManager,
+ WifiManager wifiManager,
+ NotificationManager notificationManager,
WifiNotificationHelper helper) {
mContext = context;
mContentResolver = contentResolver;
@@ -165,8 +172,12 @@ public class WifiNotificationController {
mStarted = new AtomicBoolean(false);
// Setting is in seconds
- mNotificationRepeatDelayMs = Settings.Global.getInt(
- contentResolver, Settings.Global.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, 900) * 1000L;
+ mNotificationRepeatDelayMs =
+ TimeUnit.SECONDS.toMillis(
+ Settings.Global.getInt(
+ contentResolver,
+ Settings.Global.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY,
+ 900));
mNotificationEnabledSettingObserver = new NotificationEnabledSettingObserver(mHandler);
}
@@ -176,7 +187,7 @@ public class WifiNotificationController {
return;
}
- mWifiState = WifiManager.WIFI_STATE_UNKNOWN;
+ mWifiState = mWifiManager.getWifiState();
mDetailedState = NetworkInfo.DetailedState.IDLE;
IntentFilter filter = new IntentFilter();
@@ -200,78 +211,81 @@ public class WifiNotificationController {
mNotificationEnabledSettingObserver.register();
}
- private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
- mWifiState = mWifiManager.getWifiState();
- resetNotification();
- } else if (intent.getAction().equals(
- WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
- mNetworkInfo = (NetworkInfo) intent.getParcelableExtra(
- WifiManager.EXTRA_NETWORK_INFO);
- NetworkInfo.DetailedState detailedState =
- mNetworkInfo.getDetailedState();
- if (detailedState != NetworkInfo.DetailedState.SCANNING
- && detailedState != mDetailedState) {
- mDetailedState = detailedState;
- switch (mDetailedState) {
- case CONNECTED:
- updateNotificationOnConnect();
- break;
- case DISCONNECTED:
- case CAPTIVE_PORTAL_CHECK:
- resetNotification();
- break;
-
- // TODO: figure out if these are failure cases when connecting
- case IDLE:
- case SCANNING:
- case CONNECTING:
- case AUTHENTICATING:
- case OBTAINING_IPADDR:
- case SUSPENDED:
- case FAILED:
- case BLOCKED:
- case VERIFYING_POOR_LINK:
- break;
+ private final BroadcastReceiver mBroadcastReceiver =
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getAction().equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
+ mWifiState = mWifiManager.getWifiState();
+ resetNotification();
+ } else if (intent.getAction()
+ .equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
+ mNetworkInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
+ NetworkInfo.DetailedState detailedState = mNetworkInfo.getDetailedState();
+ if (detailedState != NetworkInfo.DetailedState.SCANNING
+ && detailedState != mDetailedState) {
+ mDetailedState = detailedState;
+ switch (mDetailedState) {
+ case CONNECTED:
+ updateNotificationOnConnect();
+ break;
+ case DISCONNECTED:
+ case CAPTIVE_PORTAL_CHECK:
+ resetNotification();
+ break;
+
+ // TODO: figure out if these are failure cases when connecting
+ case IDLE:
+ case SCANNING:
+ case CONNECTING:
+ case DISCONNECTING:
+ case AUTHENTICATING:
+ case OBTAINING_IPADDR:
+ case SUSPENDED:
+ case FAILED:
+ case BLOCKED:
+ case VERIFYING_POOR_LINK:
+ break;
+ }
+ }
+ } else if (intent.getAction()
+ .equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
+ checkAndSetNotification(mNetworkInfo, mWifiManager.getScanResults());
+ } else if (intent.getAction().equals(ACTION_CONNECT_TO_RECOMMENDED_NETWORK)) {
+ connectToRecommendedNetwork();
+ } else if (intent.getAction().equals(ACTION_NOTIFICATION_DELETED)) {
+ handleNotificationDeleted();
+ } else if (intent.getAction().equals(ACTION_PICK_WIFI_NETWORK)) {
+ openWifiPicker();
}
}
- } else if (intent.getAction().equals(
- WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
- checkAndSetNotification(mNetworkInfo, mWifiManager.getScanResults());
- } else if (intent.getAction().equals(ACTION_CONNECT_TO_RECOMMENDED_NETWORK)) {
- connectToRecommendedNetwork();
- } else if (intent.getAction().equals(ACTION_NOTIFICATION_DELETED)) {
- handleNotificationDeleted();
- }
- }
- };
-
- private void checkAndSetNotification(NetworkInfo networkInfo,
- List<ScanResult> scanResults) {
+ };
+ private void checkAndSetNotification(NetworkInfo networkInfo, List<ScanResult> scanResults) {
// TODO: unregister broadcast so we do not have to check here
// If we shouldn't place a notification on available networks, then
// don't bother doing any of the following
- if (!mNotificationEnabled) return;
- if (mWifiState != WifiManager.WIFI_STATE_ENABLED) return;
- if (scanResults == null || scanResults.isEmpty()) return;
+ if (!mNotificationEnabled
+ || mWifiState != WifiManager.WIFI_STATE_ENABLED
+ || scanResults == null
+ || scanResults.isEmpty()) {
+ return;
+ }
NetworkInfo.State state = NetworkInfo.State.DISCONNECTED;
if (networkInfo != null) {
state = networkInfo.getState();
}
-
- if (state == NetworkInfo.State.DISCONNECTED
- || state == NetworkInfo.State.UNKNOWN) {
+ if (state == NetworkInfo.State.DISCONNECTED || state == NetworkInfo.State.UNKNOWN) {
+ maybeLogOpenNetworksAvailable();
RecommendationResult result = getOpenNetworkRecommendation(scanResults);
- if (result != null
- && result.getWifiConfiguration() != null) {
+ if (result != null && result.getWifiConfiguration() != null) {
mRecommendedNetwork = result.getWifiConfiguration();
- mNotificationBadgeBitmap = mWifiNotificationHelper.createNotificationBadgeBitmap(
- mRecommendedNetwork, scanResults);
+
+ mNotificationBadgeBitmap =
+ mWifiNotificationHelper.createNotificationBadgeBitmap(
+ mRecommendedNetwork, scanResults);
if (++mNumScansSinceNetworkStateChange >= NUM_SCANS_BEFORE_ACTUALLY_SCANNING
&& mNotificationBadgeBitmap != null) {
/*
@@ -291,9 +305,17 @@ public class WifiNotificationController {
removeNotification();
}
+ private void maybeLogOpenNetworksAvailable() {
+ long now = System.currentTimeMillis();
+ if (now < mOpenNetworksLoggingRepeatTime) {
+ return;
+ }
+ mOpenNetworksLoggingRepeatTime = now + mNotificationRepeatDelayMs;
+ }
+
/**
- * Uses {@link NetworkScoreManager} to choose a qualified network out of the list of
- * {@link ScanResult}s.
+ * Uses {@link NetworkScoreManager} to choose a qualified network out of the list of {@link
+ * ScanResult}s.
*
* @return returns the best qualified open networks, if any.
*/
@@ -302,26 +324,41 @@ public class WifiNotificationController {
if (scanResults == null || scanResults.isEmpty()) {
return null;
}
+
ArrayList<ScanResult> openNetworks = new ArrayList<>();
+ List<WifiConfiguration> configuredNetworks = mWifiManager.getConfiguredNetworks();
for (ScanResult scanResult : scanResults) {
//A capability of [ESS] represents an open access point
//that is available for an STA to connect
+ //TODO: potentially handle this within NetworkRecommendationProvider instead.
if ("[ESS]".equals(scanResult.capabilities)) {
+ if (isSavedNetwork(scanResult, configuredNetworks)) {
+ continue;
+ }
openNetworks.add(scanResult);
}
}
- RecommendationRequest request = new RecommendationRequest.Builder()
- .setScanResults(openNetworks.toArray(new ScanResult[openNetworks.size()]))
- .build();
+ RecommendationRequest request =
+ RoboCompatUtil.getInstance().createRecommendationRequest(openNetworks);
return mNetworkRecommendationProvider.requestRecommendation(request);
}
- /**
- * Display's a notification that there are open Wi-Fi networks.
- */
- private void displayNotification() {
+ /** Returns true if scanResult matches the list of saved networks */
+ private boolean isSavedNetwork(ScanResult scanResult, List<WifiConfiguration> savedNetworks) {
+ if (savedNetworks == null) {
+ return false;
+ }
+ for (int i = 0; i < savedNetworks.size(); i++) {
+ if (ScanResultUtil.doesScanResultMatchWithNetwork(scanResult, savedNetworks.get(i))) {
+ return true;
+ }
+ }
+ return false;
+ }
+ /** Display's a notification that there are open Wi-Fi networks. */
+ private void displayNotification() {
// Since we use auto cancel on the notification, when the
// mNetworksAvailableNotificationShown is true, the notification may
// have actually been canceled. However, when it is false we know
@@ -329,103 +366,129 @@ public class WifiNotificationController {
// place than here)
// Not enough time has passed to show the notification again
-
if (System.currentTimeMillis() < mNotificationRepeatTime) {
return;
}
- Notification notification = mWifiNotificationHelper.createMainNotification(
+ Notification notification =
+ mWifiNotificationHelper.createMainNotification(
mRecommendedNetwork, mNotificationBadgeBitmap);
mNotificationRepeatTime = System.currentTimeMillis() + mNotificationRepeatDelayMs;
-
postNotification(notification);
- mNotificationShown = true;
+ mNotificationState = State.SHOWING_CONNECT_ACTIONS;
}
+ /** Opens activity to allow the user to select a wifi network. */
+ private void openWifiPicker() {
+ mContext.startActivity(
+ new Intent(WifiManager.ACTION_PICK_WIFI_NETWORK)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+ }
/**
- * Attempts to connect to recommended network and updates the notification to
- * show Connecting state.
- * TODO(33668991): work with UX to polish notification UI and figure out failure states
+ * Attempts to connect to recommended network and updates the notification to show Connecting
+ * state. TODO(33668991): work with UX to polish notification UI and figure out failure states
*/
private void connectToRecommendedNetwork() {
if (mRecommendedNetwork == null) {
return;
}
+ mRecommendedNetwork.BSSID = null;
+
// Attempts to connect to recommended network.
- mWifiManager.connect(mRecommendedNetwork, null /* actionListener */);
+ RoboCompatUtil.getInstance().connectToWifi(mWifiManager, mRecommendedNetwork);
// Update notification to connecting status.
- Notification notification = mWifiNotificationHelper.createConnectingNotification(
+ Notification notification =
+ mWifiNotificationHelper.createConnectingNotification(
mRecommendedNetwork, mNotificationBadgeBitmap);
postNotification(notification);
- mHandler.postDelayed(mShowFailedToConnectNotificationRunnable,
+ mNotificationState = State.SHOWING_CONNECTING;
+ mHandler.postDelayed(
+ () -> {
+ if (mNotificationState == State.SHOWING_CONNECTING) {
+ showFailedToConnectNotification();
+ }
+ },
TIME_TO_SHOW_CONNECTING_MILLIS);
}
/**
- * When detailed state changes to CONNECTED, show connected notification or
- * reset notification.
+ * When detailed state changes to CONNECTED, show connected notification or reset notification.
* TODO: determine failure state where main notification shows but connected.
*/
private void updateNotificationOnConnect() {
- if (!mNotificationShown) {
+ if (mNotificationState != State.SHOWING_CONNECTING) {
return;
}
- Notification notification = mWifiNotificationHelper.createConnectedNotification(
- mRecommendedNetwork, mNotificationBadgeBitmap);
+ Notification notification =
+ mWifiNotificationHelper.createConnectedNotification(
+ mRecommendedNetwork, mNotificationBadgeBitmap);
postNotification(notification);
- // Remove any previous reset notification callbacks.
- mHandler.removeCallbacks(mShowFailedToConnectNotificationRunnable);
- mHandler.postDelayed(mDismissNotificationRunnable, TIME_TO_SHOW_CONNECTED_MILLIS);
+ mNotificationState = State.SHOWING_CONNECTED;
+ mHandler.postDelayed(
+ () -> {
+ if (mNotificationState == State.SHOWING_CONNECTED) {
+ removeNotification();
+ }
+ },
+ TIME_TO_SHOW_CONNECTED_MILLIS);
}
/**
- * Displays the Failed To Connect notification after the Connecting notification
- * is shown for {@link #TIME_TO_SHOW_CONNECTING_MILLIS} duration.
+ * Displays the Failed To Connect notification after the Connecting notification is shown for
+ * {@link #TIME_TO_SHOW_CONNECTING_MILLIS} duration.
*/
private void showFailedToConnectNotification() {
Notification notification =
mWifiNotificationHelper.createFailedToConnectNotification(mRecommendedNetwork);
postNotification(notification);
- mHandler.postDelayed(mDismissNotificationRunnable, TIME_TO_SHOW_FAILED_MILLIS);
+ mNotificationState = State.SHOWING_FAILURE;
+ mHandler.postDelayed(
+ () -> {
+ if (mNotificationState == State.SHOWING_FAILURE) {
+ removeNotification();
+ }
+ },
+ TIME_TO_SHOW_FAILED_MILLIS);
}
- /**
- * Handles behavior when notification is dismissed.
- */
+ /** Handles behavior when notification is dismissed. */
private void handleNotificationDeleted() {
- mNotificationShown = false;
+ mNotificationState = State.HIDDEN;
mRecommendedNetwork = null;
mNotificationBadgeBitmap = null;
}
private void postNotification(Notification notification) {
- mNotificationManager.notify(null /* tag */, ICON_NETWORKS_AVAILABLE, notification);
+ mNotificationManager.notify(NOTIFICATION_TAG, NOTIFICATION_ID, notification);
}
/**
- * Clears variables related to tracking whether a notification has been
- * shown recently and clears the current notification.
+ * Clears variables related to tracking whether a notification has been shown recently and
+ * clears the current notification.
*/
private void resetNotification() {
- mNotificationRepeatTime = 0;
- mNumScansSinceNetworkStateChange = 0;
- if (mNotificationShown) {
+ if (mNotificationState != State.HIDDEN) {
removeNotification();
}
+ mRecommendedNetwork = null;
+ mNotificationRepeatTime = 0;
+ mNumScansSinceNetworkStateChange = 0;
+ mOpenNetworksLoggingRepeatTime = 0;
}
private void removeNotification() {
- mNotificationManager.cancel(null /* tag */, ICON_NETWORKS_AVAILABLE);
- mNotificationShown = false;
+ mNotificationManager.cancel(NOTIFICATION_TAG, NOTIFICATION_ID);
+ mNotificationState = State.HIDDEN;
+ mRecommendedNetwork = null;
+ mNotificationBadgeBitmap = null;
}
- /** Dump debugging information. */
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("mNotificationEnabled " + mNotificationEnabled);
pw.println("mNotificationRepeatTime " + mNotificationRepeatTime);
- pw.println("mNotificationShown " + mNotificationShown);
+ pw.println("mNotificationState " + mNotificationState);
pw.println("mNumScansSinceNetworkStateChange " + mNumScansSinceNetworkStateChange);
}
@@ -435,8 +498,11 @@ public class WifiNotificationController {
}
public void register() {
- mContentResolver.registerContentObserver(Settings.Global.getUriFor(
- Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON), true, this);
+ mContentResolver.registerContentObserver(
+ Settings.Global.getUriFor(
+ Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON),
+ true,
+ this);
mNotificationEnabled = getValue();
}
@@ -454,8 +520,10 @@ public class WifiNotificationController {
private boolean getValue() {
return Settings.Global.getInt(
- mContentResolver,
- Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0) == 1;
+ mContentResolver,
+ Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
+ 0)
+ == 1;
}
}
}
diff --git a/src/com/android/networkrecommendation/notify/WifiNotificationHelper.java b/src/com/android/networkrecommendation/notify/WifiNotificationHelper.java
index 719e6b4..564bea8 100644
--- a/src/com/android/networkrecommendation/notify/WifiNotificationHelper.java
+++ b/src/com/android/networkrecommendation/notify/WifiNotificationHelper.java
@@ -13,10 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.android.networkrecommendation.notify;
import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
+import static com.android.networkrecommendation.Constants.TAG;
import android.app.Notification;
import android.app.Notification.Action;
@@ -27,30 +27,35 @@ import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LayerDrawable;
import android.net.NetworkKey;
import android.net.ScoredNetwork;
-import android.net.WifiKey;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Bundle;
+import android.provider.Settings;
import android.support.annotation.NonNull;
+import android.support.annotation.VisibleForTesting;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ForegroundColorSpan;
-
import com.android.networkrecommendation.R;
import com.android.networkrecommendation.SynchronousNetworkRecommendationProvider;
+import com.android.networkrecommendation.util.Blog;
import com.android.networkrecommendation.util.ImageUtil;
+import com.android.networkrecommendation.util.RoboCompatUtil;
+import com.android.networkrecommendation.util.ScanResultUtil;
import com.android.networkrecommendation.util.WifiConfigurationUtil;
-
import java.util.List;
+import javax.annotation.Nullable;
-/**
- * Helper class that creates notifications for {@link WifiNotificationController}.
- */
+/** Helper class that creates notifications for {@link WifiNotificationController}. */
public class WifiNotificationHelper {
+
+ /** This is in reference to the hidden Settings.Global.NETWORK_SCORING_UI_ENABLED */
+ @VisibleForTesting
+ static final String NETWORK_SCORING_UI_ENABLED = "network_scoring_ui_enabled";
+
private final Context mContext;
private final SynchronousNetworkRecommendationProvider mCachedScoredNetworkProvider;
@@ -61,28 +66,36 @@ public class WifiNotificationHelper {
}
/**
- * Creates the main open networks notification with two actions. "Options" link to the
- * Wi-Fi picker activity, and "Connect" prompts {@link WifiNotificationController}
- * to connect to the recommended network.
+ * Creates the main open networks notification with two actions. "Options" link to the Wi-Fi
+ * picker activity, and "Connect" prompts {@link WifiNotificationController} to connect to the
+ * recommended network.
*/
public Notification createMainNotification(WifiConfiguration config, Bitmap badge) {
- PendingIntent optionsIntent = PendingIntent.getActivity(
- mContext, 0, new Intent(WifiManager.ACTION_PICK_WIFI_NETWORK), FLAG_UPDATE_CURRENT);
- Action optionsAction = new Action.Builder(
- null /* icon */,
- mContext.getText(R.string.wifi_available_options),
- optionsIntent)
- .build();
- PendingIntent connectIntent = PendingIntent.getBroadcast(
- mContext,
- 0,
- new Intent(WifiNotificationController.ACTION_CONNECT_TO_RECOMMENDED_NETWORK),
- FLAG_UPDATE_CURRENT);
- Action connectAction = new Action.Builder(
- null /* icon */,
- mContext.getText(R.string.wifi_available_connect),
- connectIntent)
- .build();
+ PendingIntent optionsIntent =
+ PendingIntent.getBroadcast(
+ mContext,
+ 0,
+ new Intent(WifiNotificationController.ACTION_PICK_WIFI_NETWORK),
+ FLAG_UPDATE_CURRENT);
+ Action optionsAction =
+ new Action.Builder(
+ null /* icon */,
+ mContext.getText(R.string.wifi_available_options),
+ optionsIntent)
+ .build();
+ PendingIntent connectIntent =
+ PendingIntent.getBroadcast(
+ mContext,
+ 0,
+ new Intent(
+ WifiNotificationController.ACTION_CONNECT_TO_RECOMMENDED_NETWORK),
+ FLAG_UPDATE_CURRENT);
+ Action connectAction =
+ new Action.Builder(
+ null /* icon */,
+ mContext.getText(R.string.wifi_available_connect),
+ connectIntent)
+ .build();
return createNotificationBuilder(config, badge)
.addAction(connectAction)
.addAction(optionsAction)
@@ -90,15 +103,16 @@ public class WifiNotificationHelper {
}
/**
- * Creates the notification that indicates the controller is attempting to connect
- * to the recommended network.
+ * Creates the notification that indicates the controller is attempting to connect to the
+ * recommended network.
*/
public Notification createConnectingNotification(WifiConfiguration config, Bitmap badge) {
- Action connecting = new Action.Builder(
- null /* icon */,
- mContext.getText(R.string.wifi_available_connecting),
- null /* pendingIntent */)
- .build();
+ Action connecting =
+ new Action.Builder(
+ null /* icon */,
+ mContext.getText(R.string.common_connecting),
+ null /* pendingIntent */)
+ .build();
return createNotificationBuilder(config, badge)
.addAction(connecting)
.setProgress(0 /* max */, 0 /* progress */, true /* indeterminate */)
@@ -106,23 +120,22 @@ public class WifiNotificationHelper {
}
/**
- * Creates the notification that indicates the controller successfully connected
- * to the recommended network.
+ * Creates the notification that indicates the controller successfully connected to the
+ * recommended network.
*/
public Notification createConnectedNotification(WifiConfiguration config, Bitmap badge) {
- Action connected = new Action.Builder(
- null /* icon */,
- mContext.getText(R.string.wifi_available_connected),
- null /* pendingIntent */)
- .build();
- return createNotificationBuilder(config, badge)
- .addAction(connected)
- .build();
+ Action connected =
+ new Action.Builder(
+ null /* icon */,
+ mContext.getText(R.string.wifi_available_connected),
+ null /* pendingIntent */)
+ .build();
+ return createNotificationBuilder(config, badge).addAction(connected).build();
}
/**
- * Creates the notification that indicates the controller failed to connect to
- * the recommended network.
+ * Creates the notification that indicates the controller failed to connect to the recommended
+ * network.
*/
public Notification createFailedToConnectNotification(WifiConfiguration config) {
Spannable failedText =
@@ -130,83 +143,75 @@ public class WifiNotificationHelper {
Resources resources = mContext.getResources();
Drawable iconDrawable = mContext.getDrawable(R.drawable.ic_signal_wifi_no_network);
iconDrawable.setTint(mContext.getColor(R.color.color_tint));
- Bitmap icon = ImageUtil.buildScaledBitmap(
- iconDrawable,
- resources.getDimensionPixelSize(android.R.dimen.notification_large_icon_width),
- resources.getDimensionPixelSize(android.R.dimen.notification_large_icon_height));
- failedText.setSpan(new ForegroundColorSpan(
- Color.RED), 0, failedText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- return createNotificationBuilder(config, icon)
- .setContentText(failedText)
- .build();
+ Bitmap icon =
+ ImageUtil.buildScaledBitmap(
+ iconDrawable,
+ resources.getDimensionPixelSize(
+ android.R.dimen.notification_large_icon_width),
+ resources.getDimensionPixelSize(
+ android.R.dimen.notification_large_icon_height));
+ failedText.setSpan(
+ new ForegroundColorSpan(Color.RED),
+ 0,
+ failedText.length(),
+ Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ return createNotificationBuilder(config, icon).setContentText(failedText).build();
}
private Notification.Builder createNotificationBuilder(WifiConfiguration config, Bitmap badge) {
CharSequence title = mContext.getText(R.string.wifi_available);
- PendingIntent deleteIntent = PendingIntent.getBroadcast(
- mContext,
- 0,
- new Intent(WifiNotificationController.ACTION_NOTIFICATION_DELETED),
- FLAG_UPDATE_CURRENT);
+ PendingIntent deleteIntent =
+ PendingIntent.getBroadcast(
+ mContext,
+ 0,
+ new Intent(WifiNotificationController.ACTION_NOTIFICATION_DELETED),
+ FLAG_UPDATE_CURRENT);
return new Notification.Builder(mContext)
.setDeleteIntent(deleteIntent)
- .setSmallIcon(R.drawable.stat_notify_wifi_in_range)
+ .setSmallIcon(R.drawable.ic_signal_wifi_badged_4_bars)
.setLargeIcon(badge)
.setAutoCancel(true)
.setTicker(title)
.setContentTitle(title)
+ .setColor(mContext.getColor(R.color.color_tint))
.setContentText(WifiConfigurationUtil.getPrintableSsid(config))
.addExtras(getSystemLabelExtras());
}
private Bundle getSystemLabelExtras() {
Bundle extras = new Bundle();
- extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
+ extras.putString(
+ Notification.EXTRA_SUBSTITUTE_APP_NAME,
mContext.getString(R.string.android_system_label));
return extras;
}
- //TODO(34177812): Share this logic between systemUi and Settings.
- static final int[] WIFI_PIE_FOR_BADGING = {
- R.drawable.ic_signal_wifi_badged_0_bars,
- R.drawable.ic_signal_wifi_badged_1_bar,
- R.drawable.ic_signal_wifi_badged_2_bars,
- R.drawable.ic_signal_wifi_badged_3_bars,
- R.drawable.ic_signal_wifi_badged_4_bars
- };
-
- private int getWifiBadgeResourceForEnum(int badgeEnum) {
- switch (badgeEnum) {
- case ScoredNetwork.BADGING_NONE:
- return 0;
- case ScoredNetwork.BADGING_SD:
- return R.drawable.ic_signal_wifi_badged_sd;
- case ScoredNetwork.BADGING_HD:
- return R.drawable.ic_signal_wifi_badged_hd;
- case ScoredNetwork.BADGING_4K:
- return R.drawable.ic_signal_wifi_badged_4k;
- default:
- throw new IllegalArgumentException("No badge resource for enum :" + badgeEnum);
- }
- }
-
/**
- * Creates a Wi-Fi badge for the notification using matching {@link ScanResult}'s RSSI
- * and badging from {@link CachedScoredNetworkProvider}.
+ * Creates a Wi-Fi badge for the notification using matching {@link ScanResult}'s RSSI and
+ * badging from {@link CachedScoredNetworkProvider}.
*/
+ @Nullable
public Bitmap createNotificationBadgeBitmap(
- @NonNull WifiConfiguration config,
- @NonNull List<ScanResult> scanResults) {
+ @NonNull WifiConfiguration config, @NonNull List<ScanResult> scanResults) {
ScanResult matchingScanResult = findMatchingScanResult(scanResults, config);
if (matchingScanResult == null) {
return null;
}
int rssi = matchingScanResult.level;
- WifiKey wifiKey = new WifiKey(config.SSID, config.BSSID);
+
+ NetworkKey networkKey;
+ try {
+ networkKey = ScanResultUtil.createNetworkKey(matchingScanResult);
+ } catch (IllegalArgumentException e) {
+ Blog.e(TAG, e, "Error creating NetworkKey.");
+ return null;
+ }
+
ScoredNetwork scoredNetwork =
- mCachedScoredNetworkProvider.getCachedScoredNetwork(new NetworkKey(wifiKey));
+ mCachedScoredNetworkProvider.getCachedScoredNetwork(networkKey);
if (scoredNetwork != null) {
- return getBadgedWifiBitmap(scoredNetwork.calculateBadge(rssi), rssi);
+ return getBadgedWifiBitmap(
+ RoboCompatUtil.getInstance().calculateBadge(scoredNetwork, rssi), rssi);
}
return null;
}
@@ -215,23 +220,26 @@ public class WifiNotificationHelper {
if (badgeEnum == ScoredNetwork.BADGING_NONE) {
return null;
}
+ if (Settings.Global.getInt(mContext.getContentResolver(), NETWORK_SCORING_UI_ENABLED, 0)
+ == 0) {
+ badgeEnum = ScoredNetwork.BADGING_NONE;
+ }
int signalLevel = WifiManager.calculateSignalLevel(rssi, 5);
- LayerDrawable layerDrawable = new LayerDrawable(new Drawable[]{
- mContext.getDrawable(WIFI_PIE_FOR_BADGING[signalLevel]),
- mContext.getDrawable(getWifiBadgeResourceForEnum(badgeEnum))});
- layerDrawable.setTint(mContext.getColor(R.color.color_tint));
+ Drawable drawable =
+ RoboCompatUtil.getInstance()
+ .getWifiIcon(signalLevel, badgeEnum, mContext.getTheme());
+ drawable.setTint(mContext.getColor(R.color.color_tint));
Resources resources = mContext.getResources();
- return ImageUtil.buildScaledBitmap(layerDrawable,
+ return ImageUtil.buildScaledBitmap(
+ drawable,
resources.getDimensionPixelSize(android.R.dimen.notification_large_icon_width),
resources.getDimensionPixelSize(android.R.dimen.notification_large_icon_height));
}
- private ScanResult findMatchingScanResult(List<ScanResult> scanResults,
- WifiConfiguration wifiConfiguration) {
- String ssid = WifiConfigurationUtil.removeDoubleQuotes(wifiConfiguration);
- String bssid = wifiConfiguration.BSSID;
+ private static ScanResult findMatchingScanResult(
+ List<ScanResult> scanResults, WifiConfiguration wifiConfiguration) {
for (ScanResult scanResult : scanResults) {
- if (ssid.equals(scanResult.SSID) && bssid.equals(scanResult.BSSID)) {
+ if (ScanResultUtil.doesScanResultMatchWithNetwork(scanResult, wifiConfiguration)) {
return scanResult;
}
}
diff --git a/src/com/android/networkrecommendation/util/RoboCompatUtil.java b/src/com/android/networkrecommendation/util/RoboCompatUtil.java
index a6d3130..686c83a 100644
--- a/src/com/android/networkrecommendation/util/RoboCompatUtil.java
+++ b/src/com/android/networkrecommendation/util/RoboCompatUtil.java
@@ -26,7 +26,6 @@ import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.support.annotation.VisibleForTesting;
-
import java.util.List;
/**
@@ -65,11 +64,15 @@ public class RoboCompatUtil {
wifiManager.connect(wifiConfiguration, null /* actionListener */);
}
- /** Wraps WifiConfiguration.hasNoInternet and WifiConfiguration.isNoInternetAccessExpected. */
+ /** Wraps WifiConfiguration.hasNoInternetAccess. */
@SuppressWarnings("unchecked")
public boolean hasNoInternetAccess(WifiConfiguration wifiConfiguration) {
- return wifiConfiguration.hasNoInternetAccess()
- || wifiConfiguration.isNoInternetAccessExpected();
+ return wifiConfiguration.hasNoInternetAccess();
+ }
+
+ /** Wraps WifiConfiguration.isNoInternetAccessExpected. */
+ public boolean isNoInternetAccessExpected(WifiConfiguration wifiConfiguration) {
+ return wifiConfiguration.isNoInternetAccessExpected();
}
/** Wraps WifiConfiguration.useExternalScores. */
diff --git a/src/com/android/networkrecommendation/util/ScanResultUtil.java b/src/com/android/networkrecommendation/util/ScanResultUtil.java
index f5117df..4587e91 100644
--- a/src/com/android/networkrecommendation/util/ScanResultUtil.java
+++ b/src/com/android/networkrecommendation/util/ScanResultUtil.java
@@ -24,7 +24,6 @@ import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.support.annotation.Nullable;
import android.text.TextUtils;
-
import com.android.networkrecommendation.config.G;
/**
diff --git a/tests/src/com/android/networkrecommendation/notify/WifiNotificationControllerTest.java b/tests/src/com/android/networkrecommendation/notify/WifiNotificationControllerTest.java
deleted file mode 100644
index 26dd56b..0000000
--- a/tests/src/com/android/networkrecommendation/notify/WifiNotificationControllerTest.java
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Copyright (C) 2017 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.networkrecommendation.notify;
-
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.graphics.Bitmap;
-import android.net.NetworkInfo;
-import android.net.RecommendationRequest;
-import android.net.RecommendationResult;
-import android.net.wifi.ScanResult;
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiManager;
-import android.net.wifi.WifiManager.ActionListener;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
-
-import com.android.networkrecommendation.SynchronousNetworkRecommendationProvider;
-import com.android.networkrecommendation.TestUtil;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Unit tests for {@link WifiNotificationController}.
- */
-@RunWith(AndroidJUnit4.class)
-public class WifiNotificationControllerTest {
- @Mock private Context mContext;
- @Mock private WifiManager mWifiManager;
- @Mock private NotificationManager mNotificationManager;
- @Mock private WifiNotificationHelper mWifiNotificationHelper;
- @Mock private SynchronousNetworkRecommendationProvider mNetworkRecommendationProvider;
- private ContentResolver mContentResolver;
- private Handler mHandler;
- private WifiNotificationController mWifiNotificationController;
- private int mNotificationsEnabledOriginalValue;
-
- /**
- * Internal BroadcastReceiver that WifiNotificationController uses to listen for broadcasts
- * this is initialized by calling startServiceAndLoadDriver
- */
- private BroadcastReceiver mBroadcastReceiver;
-
- /** Initialize objects before each test run. */
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
-
- // Needed for the NotificationEnabledSettingObserver.
- mContentResolver = InstrumentationRegistry.getTargetContext().getContentResolver();
- mNotificationsEnabledOriginalValue =
- Settings.Global.getInt(mContentResolver,
- Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0);
- Settings.Global.putInt(mContentResolver,
- Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 1);
- mHandler = new Handler(Looper.getMainLooper());
-
- mWifiNotificationController = new WifiNotificationController(
- mContext, mContentResolver, mHandler, mNetworkRecommendationProvider,
- mWifiManager, mNotificationManager, mWifiNotificationHelper);
- mWifiNotificationController.start();
-
- ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
- ArgumentCaptor.forClass(BroadcastReceiver.class);
- verify(mContext)
- .registerReceiver(broadcastReceiverCaptor.capture(), any(IntentFilter.class),
- anyString(), any(Handler.class));
- mBroadcastReceiver = broadcastReceiverCaptor.getValue();
- }
-
- @After
- public void tearDown() throws Exception {
- Settings.Global.putInt(mContentResolver,
- Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
- mNotificationsEnabledOriginalValue);
- }
-
- private void setOpenAccessPoints(int numAccessPoints) {
- List<ScanResult> scanResults = new ArrayList<>();
- for (int i = 0; i < numAccessPoints; i++) {
- ScanResult scanResult = createScanResult("testSSID" + i, "00:00:00:00:00:00");
- scanResults.add(scanResult);
- }
- when(mWifiManager.getScanResults()).thenReturn(scanResults);
- }
-
- private ScanResult createScanResult(String ssid, String bssid) {
- ScanResult scanResult = new ScanResult();
- scanResult.capabilities = "[ESS]";
- scanResult.SSID = ssid;
- scanResult.BSSID = bssid;
- return scanResult;
- }
-
- private WifiConfiguration createFakeConfig() {
- WifiConfiguration config = new WifiConfiguration();
- config.SSID = "\"TestSsid\"";
- config.BSSID = "00:00:00:00:00:00";
- config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
- return config;
- }
-
- private void createFakeBitmap() {
- when(mWifiNotificationHelper.createNotificationBadgeBitmap(any(), any()))
- .thenReturn(Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888));
- }
-
- /** Verifies that a notification is displayed (and retracted) given system events. */
- @Test
- public void verifyNotificationDisplayedWhenNetworkRecommended() throws Exception {
- when(mWifiManager.getWifiState()).thenReturn(WifiManager.WIFI_STATE_ENABLED);
-
- TestUtil.sendWifiStateChanged(mBroadcastReceiver, mContext);
- TestUtil.sendNetworkStateChanged(mBroadcastReceiver, mContext,
- NetworkInfo.DetailedState.DISCONNECTED);
- setOpenAccessPoints(3);
- createFakeBitmap();
-
- when(mNetworkRecommendationProvider.requestRecommendation(any(RecommendationRequest.class)))
- .thenReturn(
- RecommendationResult.createConnectRecommendation(createFakeConfig()));
-
- // The notification should not be displayed after only two scan results.
- TestUtil.sendScanResultsAvailable(mBroadcastReceiver, mContext);
- TestUtil.sendScanResultsAvailable(mBroadcastReceiver, mContext);
- verify(mNotificationManager, never())
- .notify(any(String.class), anyInt(), any(Notification.class));
-
- // Changing to and from "SCANNING" state should not affect the counter.
- TestUtil.sendNetworkStateChanged(mBroadcastReceiver, mContext,
- NetworkInfo.DetailedState.SCANNING);
- TestUtil.sendNetworkStateChanged(mBroadcastReceiver, mContext,
- NetworkInfo.DetailedState.DISCONNECTED);
- verify(mNotificationManager, never())
- .notify(any(String.class), anyInt(), any(Notification.class));
- // The third scan result notification will trigger the notification.
- TestUtil.sendScanResultsAvailable(mBroadcastReceiver, mContext);
- verify(mWifiNotificationHelper).createMainNotification(any(WifiConfiguration.class),
- any(Bitmap.class));
- verify(mNotificationManager)
- .notify(any(String.class), anyInt(), any(Notification.class));
- verify(mNotificationManager, never())
- .cancelAsUser(any(String.class), anyInt(), any(UserHandle.class));
- }
-
- /** Verifies that a notification is not displayed for bad networks. */
- @Test
- public void verifyNotificationNotDisplayedWhenNoNetworkRecommended() throws Exception {
- when(mWifiManager.getWifiState()).thenReturn(WifiManager.WIFI_STATE_ENABLED);
-
- TestUtil.sendWifiStateChanged(mBroadcastReceiver, mContext);
- TestUtil.sendNetworkStateChanged(mBroadcastReceiver, mContext,
- NetworkInfo.DetailedState.DISCONNECTED);
- setOpenAccessPoints(3);
- createFakeBitmap();
-
- // Recommendation result with no WifiConfiguration returned.
- when(mNetworkRecommendationProvider.requestRecommendation(any(RecommendationRequest.class)))
- .thenReturn(RecommendationResult.createDoNotConnectRecommendation());
-
- TestUtil.sendScanResultsAvailable(mBroadcastReceiver, mContext);
- TestUtil.sendScanResultsAvailable(mBroadcastReceiver, mContext);
- TestUtil.sendScanResultsAvailable(mBroadcastReceiver, mContext);
- TestUtil.sendScanResultsAvailable(mBroadcastReceiver, mContext);
- verify(mNotificationManager, never())
- .notify(any(String.class), anyInt(), any(Notification.class));
-
- // DoNotConnect Recommendation result.
- when(mNetworkRecommendationProvider.requestRecommendation(any(RecommendationRequest.class)))
- .thenReturn(RecommendationResult.createDoNotConnectRecommendation());
- TestUtil.sendScanResultsAvailable(mBroadcastReceiver, mContext);
- verify(mNotificationManager, never())
- .notify(any(String.class), anyInt(), any(Notification.class));
- }
-
- /**
- * Verifies the notifications flow (Connect -> connecting -> connected) when user clicks
- * on Connect button.
- */
- @Test
- public void verifyNotificationsFlowOnConnectToNetwork() {
- when(mWifiManager.getWifiState()).thenReturn(WifiManager.WIFI_STATE_ENABLED);
-
- TestUtil.sendWifiStateChanged(mBroadcastReceiver, mContext);
- TestUtil.sendNetworkStateChanged(mBroadcastReceiver, mContext,
- NetworkInfo.DetailedState.DISCONNECTED);
- setOpenAccessPoints(3);
- createFakeBitmap();
- when(mNetworkRecommendationProvider.requestRecommendation(any(RecommendationRequest.class)))
- .thenReturn(
- RecommendationResult.createConnectRecommendation(createFakeConfig()));
-
- TestUtil.sendScanResultsAvailable(mBroadcastReceiver, mContext);
- TestUtil.sendScanResultsAvailable(mBroadcastReceiver, mContext);
- TestUtil.sendScanResultsAvailable(mBroadcastReceiver, mContext);
- verify(mWifiNotificationHelper).createMainNotification(any(WifiConfiguration.class),
- any(Bitmap.class));
- verify(mNotificationManager)
- .notify(any(String.class), anyInt(), any(Notification.class));
-
- // Send connect intent, should attempt to connect to Wi-Fi
- Intent intent = new Intent(
- WifiNotificationController.ACTION_CONNECT_TO_RECOMMENDED_NETWORK);
- mBroadcastReceiver.onReceive(mContext, intent);
- verify(mWifiManager).connect(any(WifiConfiguration.class), any(ActionListener.class));
- verify(mWifiNotificationHelper).createConnectingNotification(any(WifiConfiguration.class),
- any(Bitmap.class));
-
- // Show connecting notification.
- verify(mNotificationManager, times(2))
- .notify(any(String.class), anyInt(), any(Notification.class));
- // Verify callback to dismiss connecting notification exists.
- assertTrue(mHandler.hasCallbacks(
- mWifiNotificationController.mShowFailedToConnectNotificationRunnable));
-
- // Verify show connected notification.
- TestUtil.sendNetworkStateChanged(mBroadcastReceiver, mContext,
- NetworkInfo.DetailedState.CONNECTED);
- verify(mWifiNotificationHelper).createConnectedNotification(any(WifiConfiguration.class),
- any(Bitmap.class));
- verify(mNotificationManager, times(3))
- .notify(any(String.class), anyInt(), any(Notification.class));
-
- // Verify callback to dismiss connected notification exists.
- assertTrue(mHandler.hasCallbacks(
- mWifiNotificationController.mDismissNotificationRunnable));
- }
-}