diff options
7 files changed, 300 insertions, 35 deletions
diff --git a/service/java/com/android/server/wifi/FrameworkFacade.java b/service/java/com/android/server/wifi/FrameworkFacade.java index 15b9cc738..26cb4ff7b 100644 --- a/service/java/com/android/server/wifi/FrameworkFacade.java +++ b/service/java/com/android/server/wifi/FrameworkFacade.java @@ -136,17 +136,6 @@ public class FrameworkFacade { return true; } - /** - * Create a new instance of WifiApConfigStore. - * @param context reference to a Context - * @param backupManagerProxy reference to a BackupManagerProxy - * @return an instance of WifiApConfigStore - */ - public WifiApConfigStore makeApConfigStore(Context context, - BackupManagerProxy backupManagerProxy) { - return new WifiApConfigStore(context, backupManagerProxy); - } - public long getTxPackets(String iface) { return TrafficStats.getTxPackets(iface); } diff --git a/service/java/com/android/server/wifi/WifiApConfigStore.java b/service/java/com/android/server/wifi/WifiApConfigStore.java index 109c0a7af..d21452c8c 100644 --- a/service/java/com/android/server/wifi/WifiApConfigStore.java +++ b/service/java/com/android/server/wifi/WifiApConfigStore.java @@ -17,15 +17,25 @@ package com.android.server.wifi; import android.annotation.NonNull; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiConfiguration.KeyMgmt; import android.os.Environment; +import android.os.Handler; +import android.os.Looper; import android.text.TextUtils; import android.util.Log; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; +import com.android.internal.notification.SystemNotificationChannels; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; @@ -44,6 +54,10 @@ import java.util.UUID; */ public class WifiApConfigStore { + // Intent when user has interacted with the softap settings change notification + public static final String ACTION_HOTSPOT_CONFIG_USER_TAPPED_CONTENT = + "com.android.server.wifi.WifiApConfigStoreUtil.HOTSPOT_CONFIG_USER_TAPPED_CONTENT"; + private static final String TAG = "WifiApConfigStore"; private static final String DEFAULT_AP_CONFIG_FILE = @@ -71,19 +85,26 @@ public class WifiApConfigStore { private ArrayList<Integer> mAllowed2GChannel = null; private final Context mContext; + private final Handler mHandler; private final String mApConfigFile; private final BackupManagerProxy mBackupManagerProxy; + private final FrameworkFacade mFrameworkFacade; private boolean mRequiresApBandConversion = false; - WifiApConfigStore(Context context, BackupManagerProxy backupManagerProxy) { - this(context, backupManagerProxy, DEFAULT_AP_CONFIG_FILE); + WifiApConfigStore(Context context, Looper looper, + BackupManagerProxy backupManagerProxy, FrameworkFacade frameworkFacade) { + this(context, looper, backupManagerProxy, frameworkFacade, DEFAULT_AP_CONFIG_FILE); } WifiApConfigStore(Context context, + Looper looper, BackupManagerProxy backupManagerProxy, + FrameworkFacade frameworkFacade, String apConfigFile) { mContext = context; + mHandler = new Handler(looper); mBackupManagerProxy = backupManagerProxy; + mFrameworkFacade = frameworkFacade; mApConfigFile = apConfigFile; String ap2GChannelListStr = mContext.getResources().getString( @@ -111,8 +132,30 @@ public class WifiApConfigStore { /* Save the default configuration to persistent storage. */ writeApConfiguration(mApConfigFile, mWifiApConfig); } + + IntentFilter filter = new IntentFilter(); + filter.addAction(ACTION_HOTSPOT_CONFIG_USER_TAPPED_CONTENT); + mContext.registerReceiver( + mBroadcastReceiver, filter, null /* broadcastPermission */, mHandler); } + private final BroadcastReceiver mBroadcastReceiver = + new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + // For now we only have one registered listener, but we easily could expand this + // to support multiple signals. Starting off with a switch to support trivial + // expansion. + switch(intent.getAction()) { + case ACTION_HOTSPOT_CONFIG_USER_TAPPED_CONTENT: + handleUserHotspotConfigTappedContent(); + break; + default: + Log.e(TAG, "Unknown action " + intent.getAction()); + } + } + }; + /** * Return the current soft access point configuration. */ @@ -145,6 +188,43 @@ public class WifiApConfigStore { return mAllowed2GChannel; } + /** + * Helper method to create and send notification to user of apBand conversion. + * + * @param packageName name of the calling app + */ + public void notifyUserOfApBandConversion(String packageName) { + Log.w(TAG, "ready to post notification - triggered by " + packageName); + Notification notification = createConversionNotification(); + NotificationManager notificationManager = (NotificationManager) + mContext.getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager.notify(SystemMessage.NOTE_SOFTAP_CONFIG_CHANGED, notification); + } + + private Notification createConversionNotification() { + CharSequence title = mContext.getText(R.string.wifi_softap_config_change); + CharSequence contentSummary = mContext.getText(R.string.wifi_softap_config_change_summary); + CharSequence content = mContext.getText(R.string.wifi_softap_config_change_detailed); + int color = mContext.getResources() + .getColor(R.color.system_notification_accent_color, mContext.getTheme()); + + return new Notification.Builder(mContext, SystemNotificationChannels.NETWORK_STATUS) + .setSmallIcon(R.drawable.ic_wifi_settings) + .setPriority(Notification.PRIORITY_HIGH) + .setCategory(Notification.CATEGORY_SYSTEM) + .setContentTitle(title) + .setContentText(contentSummary) + .setContentIntent(getPrivateBroadcast(ACTION_HOTSPOT_CONFIG_USER_TAPPED_CONTENT)) + .setTicker(title) + .setShowWhen(false) + .setLocalOnly(true) + .setColor(color) + .setStyle(new Notification.BigTextStyle().bigText(content) + .setBigContentTitle(title) + .setSummaryText(contentSummary)) + .build(); + } + private WifiConfiguration apBandCheckConvert(WifiConfiguration config) { if (mRequiresApBandConversion) { // some devices are unable to support 5GHz only operation, check for 5GHz and @@ -386,4 +466,29 @@ public class WifiApConfigStore { return true; } + + /** + * Helper method to start up settings on the softap config page. + */ + private void startSoftApSettings() { + mContext.startActivity( + new Intent("com.android.settings.WIFI_TETHER_SETTINGS") + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); + } + + /** + * Helper method to trigger settings to open the softap config page + */ + private void handleUserHotspotConfigTappedContent() { + startSoftApSettings(); + NotificationManager notificationManager = (NotificationManager) + mContext.getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager.cancel(SystemMessage.NOTE_SOFTAP_CONFIG_CHANGED); + } + + private PendingIntent getPrivateBroadcast(String action) { + Intent intent = new Intent(action).setPackage("android"); + return mFrameworkFacade.getBroadcast( + mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); + } } diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java index 199548090..dbf730a73 100644 --- a/service/java/com/android/server/wifi/WifiInjector.java +++ b/service/java/com/android/server/wifi/WifiInjector.java @@ -205,7 +205,8 @@ public class WifiInjector { SystemProperties.get(BOOT_DEFAULT_WIFI_COUNTRY_CODE), mContext.getResources() .getBoolean(R.bool.config_wifi_revert_country_code_on_cellular_loss)); - mWifiApConfigStore = new WifiApConfigStore(mContext, mBackupManagerProxy); + mWifiApConfigStore = new WifiApConfigStore( + mContext, wifiStateMachineLooper, mBackupManagerProxy, mFrameworkFacade); // WifiConfigManager/Store objects and their dependencies. // New config store diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java index a0bbded9d..cb16efd99 100644 --- a/service/java/com/android/server/wifi/WifiServiceImpl.java +++ b/service/java/com/android/server/wifi/WifiServiceImpl.java @@ -1583,6 +1583,21 @@ public class WifiServiceImpl extends IWifiManager.Stub { } /** + * Method used to inform user of Ap Configuration conversion due to hardware. + */ + @Override + public void notifyUserOfApBandConversion(String packageName) { + enforceNetworkSettingsPermission(); + + if (mVerboseLoggingEnabled) { + mLog.info("notifyUserOfApBandConversion uid=% packageName=%") + .c(Binder.getCallingUid()).c(packageName).flush(); + } + + mWifiApConfigStore.notifyUserOfApBandConversion(packageName); + } + + /** * see {@link android.net.wifi.WifiManager#isScanAlwaysAvailable()} */ @Override diff --git a/tests/wifitests/src/com/android/server/wifi/MockResources.java b/tests/wifitests/src/com/android/server/wifi/MockResources.java index ab40c6f8d..1a061e22a 100644 --- a/tests/wifitests/src/com/android/server/wifi/MockResources.java +++ b/tests/wifitests/src/com/android/server/wifi/MockResources.java @@ -23,11 +23,13 @@ public class MockResources extends android.test.mock.MockResources { private HashMap<Integer, Boolean> mBooleanValues; private HashMap<Integer, Integer> mIntegerValues; private HashMap<Integer, String> mStringValues; + private HashMap<Integer, CharSequence> mTextValues; public MockResources() { mBooleanValues = new HashMap<Integer, Boolean>(); mIntegerValues = new HashMap<Integer, Integer>(); mStringValues = new HashMap<Integer, String>(); + mTextValues = new HashMap<Integer, CharSequence>(); } @Override @@ -57,6 +59,15 @@ public class MockResources extends android.test.mock.MockResources { } } + @Override + public CharSequence getText(int id) { + if (mTextValues.containsKey(id)) { + return mTextValues.get(id); + } else { + return null; + } + } + public void setBoolean(int id, boolean value) { mBooleanValues.put(id, value); } @@ -68,4 +79,8 @@ public class MockResources extends android.test.mock.MockResources { public void setString(int id, String value) { mStringValues.put(id, value); } + + public void setText(int id, CharSequence value) { + mTextValues.put(id, value); + } } diff --git a/tests/wifitests/src/com/android/server/wifi/WifiApConfigStoreTest.java b/tests/wifitests/src/com/android/server/wifi/WifiApConfigStoreTest.java index 1672dca58..88312ce4c 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiApConfigStoreTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiApConfigStoreTest.java @@ -19,25 +19,38 @@ package com.android.server.wifi; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.eq; import static org.mockito.Mockito.never; 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.Context; +import android.content.Intent; +import android.content.pm.ApplicationInfo; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiConfiguration.KeyMgmt; +import android.os.Build; +import android.os.test.TestLooper; import android.support.test.filters.SmallTest; import com.android.internal.R; +import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.io.File; import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Random; /** @@ -54,19 +67,34 @@ public class WifiApConfigStoreTest { private static final String TEST_CONFIGURED_AP_SSID = "ConfiguredAP"; private static final String TEST_DEFAULT_HOTSPOT_SSID = "TestShare"; private static final String TEST_DEFAULT_HOTSPOT_PSK = "TestPassword"; + private static final String TEST_APCONFIG_CHANGE_NOTIFICATION_TITLE = "Notification title"; + private static final String TEST_APCONFIG_CHANGE_NOTIFICATION_SUMMARY = "Notification summary"; + private static final String TEST_APCONFIG_CHANGE_NOTIFICATION_DETAILED = + "Notification detailed"; private static final int RAND_SSID_INT_MIN = 1000; private static final int RAND_SSID_INT_MAX = 9999; private static final String TEST_CHAR_SET_AS_STRING = "abcdefghijklmnopqrstuvwxyz0123456789"; - @Mock Context mContext; - @Mock BackupManagerProxy mBackupManagerProxy; - File mApConfigFile; - Random mRandom; - MockResources mResources; + @Mock private Context mContext; + private TestLooper mLooper; + @Mock private BackupManagerProxy mBackupManagerProxy; + @Mock private FrameworkFacade mFrameworkFacade; + private File mApConfigFile; + private Random mRandom; + private MockResources mResources; + @Mock private ApplicationInfo mMockApplInfo; + private BroadcastReceiver mBroadcastReceiver; + @Mock private NotificationManager mNotificationManager; + private ArrayList<Integer> mKnownGood2GChannelList; @Before public void setUp() throws Exception { + mLooper = new TestLooper(); MockitoAnnotations.initMocks(this); + when(mContext.getSystemService(Context.NOTIFICATION_SERVICE)) + .thenReturn(mNotificationManager); + mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.P; + when(mContext.getApplicationInfo()).thenReturn(mMockApplInfo); /* Create a temporary file for AP config file storage. */ mApConfigFile = File.createTempFile(TEST_AP_CONFIG_FILE_PREFIX, ""); @@ -74,15 +102,24 @@ public class WifiApConfigStoreTest { /* Setup expectations for Resources to return some default settings. */ mResources = new MockResources(); mResources.setString(R.string.config_wifi_framework_sap_2G_channel_list, - TEST_DEFAULT_2G_CHANNEL_LIST); + TEST_DEFAULT_2G_CHANNEL_LIST); mResources.setString(R.string.wifi_tether_configure_ssid_default, - TEST_DEFAULT_AP_SSID); + TEST_DEFAULT_AP_SSID); mResources.setString(R.string.wifi_localhotspot_configure_ssid_default, - TEST_DEFAULT_HOTSPOT_SSID); + TEST_DEFAULT_HOTSPOT_SSID); /* Default to device that does not require ap band conversion */ mResources.setBoolean(R.bool.config_wifi_convert_apband_5ghz_to_any, false); + mResources.setText(R.string.wifi_softap_config_change, + TEST_APCONFIG_CHANGE_NOTIFICATION_TITLE); + mResources.setText(R.string.wifi_softap_config_change_summary, + TEST_APCONFIG_CHANGE_NOTIFICATION_SUMMARY); + mResources.setText(R.string.wifi_softap_config_change_detailed, + TEST_APCONFIG_CHANGE_NOTIFICATION_DETAILED); when(mContext.getResources()).thenReturn(mResources); + // build the known good 2G channel list: TEST_DEFAULT_2G_CHANNEL_LIST + mKnownGood2GChannelList = new ArrayList(Arrays.asList(1, 2, 3, 4, 5, 6)); + mRandom = new Random(); } @@ -93,6 +130,22 @@ public class WifiApConfigStoreTest { } /** + * Helper method to create and verify actions for the ApConfigStore used in the following tests. + */ + private WifiApConfigStore createWifiApConfigStore() { + WifiApConfigStore store = new WifiApConfigStore( + mContext, mLooper.getLooper(), mBackupManagerProxy, mFrameworkFacade, + mApConfigFile.getPath()); + + ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor = + ArgumentCaptor.forClass(BroadcastReceiver.class); + verify(mContext).registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any()); + mBroadcastReceiver = broadcastReceiverCaptor.getValue(); + + return store; + } + + /** * Generate a WifiConfiguration based on the specified parameters. */ private WifiConfiguration setupApConfig( @@ -149,7 +202,8 @@ public class WifiApConfigStoreTest { @Test public void initWithDefaultConfiguration() throws Exception { WifiApConfigStore store = new WifiApConfigStore( - mContext, mBackupManagerProxy, mApConfigFile.getPath()); + mContext, mLooper.getLooper(), mBackupManagerProxy, mFrameworkFacade, + mApConfigFile.getPath()); verifyDefaultApConfig(store.getApConfiguration(), TEST_DEFAULT_AP_SSID); } @@ -167,7 +221,8 @@ public class WifiApConfigStoreTest { 40 /* AP channel */); writeApConfigFile(expectedConfig); WifiApConfigStore store = new WifiApConfigStore( - mContext, mBackupManagerProxy, mApConfigFile.getPath()); + mContext, mLooper.getLooper(), mBackupManagerProxy, mFrameworkFacade, + mApConfigFile.getPath()); verifyApConfig(expectedConfig, store.getApConfiguration()); } @@ -187,7 +242,8 @@ public class WifiApConfigStoreTest { 40 /* AP channel */); writeApConfigFile(expectedConfig); WifiApConfigStore store = new WifiApConfigStore( - mContext, mBackupManagerProxy, mApConfigFile.getPath()); + mContext, mLooper.getLooper(), mBackupManagerProxy, mFrameworkFacade, + mApConfigFile.getPath()); verifyApConfig(expectedConfig, store.getApConfiguration()); store.setApConfiguration(null); @@ -202,7 +258,8 @@ public class WifiApConfigStoreTest { public void updateApConfiguration() throws Exception { /* Initialize WifiApConfigStore with default configuration. */ WifiApConfigStore store = new WifiApConfigStore( - mContext, mBackupManagerProxy, mApConfigFile.getPath()); + mContext, mLooper.getLooper(), mBackupManagerProxy, mFrameworkFacade, + mApConfigFile.getPath()); verifyDefaultApConfig(store.getApConfiguration(), TEST_DEFAULT_AP_SSID); /* Update with a valid configuration. */ @@ -226,7 +283,8 @@ public class WifiApConfigStoreTest { public void convertSingleModeDeviceAnyTo5Ghz() throws Exception { /* Initialize WifiApConfigStore with default configuration. */ WifiApConfigStore store = new WifiApConfigStore( - mContext, mBackupManagerProxy, mApConfigFile.getPath()); + mContext, mLooper.getLooper(), mBackupManagerProxy, mFrameworkFacade, + mApConfigFile.getPath()); verifyDefaultApConfig(store.getApConfiguration(), TEST_DEFAULT_AP_SSID); /* Update with a valid configuration. */ @@ -257,7 +315,8 @@ public class WifiApConfigStoreTest { public void singleModeDevice5GhzNotConverted() throws Exception { /* Initialize WifiApConfigStore with default configuration. */ WifiApConfigStore store = new WifiApConfigStore( - mContext, mBackupManagerProxy, mApConfigFile.getPath()); + mContext, mLooper.getLooper(), mBackupManagerProxy, mFrameworkFacade, + mApConfigFile.getPath()); verifyDefaultApConfig(store.getApConfiguration(), TEST_DEFAULT_AP_SSID); /* Update with a valid configuration. */ @@ -282,7 +341,8 @@ public class WifiApConfigStoreTest { /* Initialize WifiApConfigStore with default configuration. */ WifiApConfigStore store = new WifiApConfigStore( - mContext, mBackupManagerProxy, mApConfigFile.getPath()); + mContext, mLooper.getLooper(), mBackupManagerProxy, mFrameworkFacade, + mApConfigFile.getPath()); verifyDefaultApConfig(store.getApConfiguration(), TEST_DEFAULT_AP_SSID); /* Update with a valid configuration. */ @@ -315,7 +375,8 @@ public class WifiApConfigStoreTest { /* Initialize WifiApConfigStore with default configuration. */ WifiApConfigStore store = new WifiApConfigStore( - mContext, mBackupManagerProxy, mApConfigFile.getPath()); + mContext, mLooper.getLooper(), mBackupManagerProxy, mFrameworkFacade, + mApConfigFile.getPath()); verifyDefaultApConfig(store.getApConfiguration(), TEST_DEFAULT_AP_SSID); /* Update with a valid configuration. */ @@ -353,7 +414,8 @@ public class WifiApConfigStoreTest { writeApConfigFile(persistedConfig); WifiApConfigStore store = new WifiApConfigStore( - mContext, mBackupManagerProxy, mApConfigFile.getPath()); + mContext, mLooper.getLooper(), mBackupManagerProxy, mFrameworkFacade, + mApConfigFile.getPath()); verifyApConfig(expectedConfig, store.getApConfiguration()); verify(mBackupManagerProxy).notifyDataChanged(); } @@ -374,7 +436,8 @@ public class WifiApConfigStoreTest { writeApConfigFile(persistedConfig); WifiApConfigStore store = new WifiApConfigStore( - mContext, mBackupManagerProxy, mApConfigFile.getPath()); + mContext, mLooper.getLooper(), mBackupManagerProxy, mFrameworkFacade, + mApConfigFile.getPath()); verifyApConfig(persistedConfig, store.getApConfiguration()); verify(mBackupManagerProxy, never()).notifyDataChanged(); } @@ -403,7 +466,8 @@ public class WifiApConfigStoreTest { writeApConfigFile(persistedConfig); WifiApConfigStore store = new WifiApConfigStore( - mContext, mBackupManagerProxy, mApConfigFile.getPath()); + mContext, mLooper.getLooper(), mBackupManagerProxy, mFrameworkFacade, + mApConfigFile.getPath()); verifyApConfig(expectedConfig, store.getApConfiguration()); verify(mBackupManagerProxy).notifyDataChanged(); } @@ -426,7 +490,8 @@ public class WifiApConfigStoreTest { writeApConfigFile(persistedConfig); WifiApConfigStore store = new WifiApConfigStore( - mContext, mBackupManagerProxy, mApConfigFile.getPath()); + mContext, mLooper.getLooper(), mBackupManagerProxy, mFrameworkFacade, + mApConfigFile.getPath()); verifyApConfig(persistedConfig, store.getApConfiguration()); verify(mBackupManagerProxy, never()).notifyDataChanged(); } @@ -437,7 +502,8 @@ public class WifiApConfigStoreTest { @Test public void getDefaultApConfigurationIsValid() { WifiApConfigStore store = new WifiApConfigStore( - mContext, mBackupManagerProxy, mApConfigFile.getPath()); + mContext, mLooper.getLooper(), mBackupManagerProxy, mFrameworkFacade, + mApConfigFile.getPath()); WifiConfiguration config = store.getApConfiguration(); assertTrue(WifiApConfigStore.validateApWifiConfiguration(config)); } @@ -597,4 +663,51 @@ public class WifiApConfigStoreTest { config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); assertFalse(WifiApConfigStore.validateApWifiConfiguration(config)); } + + /** + * Verify the default 2GHz channel list is properly returned. + */ + @Test + public void testDefault2GHzChannelListReturned() { + // first build known good list + WifiApConfigStore store = createWifiApConfigStore(); + ArrayList<Integer> channels = store.getAllowed2GChannel(); + + assertEquals(mKnownGood2GChannelList.size(), channels.size()); + for (int channel : channels) { + assertTrue(mKnownGood2GChannelList.contains(channel)); + } + } + + /** + * Verify a notification is posted when triggered when the ap config was converted. + */ + @Test + public void testNotifyUserOfApBandConversion() throws Exception { + WifiApConfigStore store = createWifiApConfigStore(); + store.notifyUserOfApBandConversion(TAG); + // verify the notification is posted + ArgumentCaptor<Notification> notificationCaptor = + ArgumentCaptor.forClass(Notification.class); + verify(mNotificationManager).notify(eq(SystemMessage.NOTE_SOFTAP_CONFIG_CHANGED), + notificationCaptor.capture()); + Notification notification = notificationCaptor.getValue(); + assertEquals(TEST_APCONFIG_CHANGE_NOTIFICATION_TITLE, + notification.extras.getCharSequence(Notification.EXTRA_TITLE)); + assertEquals(TEST_APCONFIG_CHANGE_NOTIFICATION_DETAILED, + notification.extras.getCharSequence(Notification.EXTRA_BIG_TEXT)); + assertEquals(TEST_APCONFIG_CHANGE_NOTIFICATION_SUMMARY, + notification.extras.getCharSequence(Notification.EXTRA_SUMMARY_TEXT)); + } + + /** + * Verify the posted notification is cleared when the user interacts with it. + */ + @Test + public void testNotificationClearedWhenContentIsTapped() throws Exception { + WifiApConfigStore store = createWifiApConfigStore(); + Intent intent = new Intent(WifiApConfigStore.ACTION_HOTSPOT_CONFIG_USER_TAPPED_CONTENT); + mBroadcastReceiver.onReceive(mContext, intent); + verify(mNotificationManager).cancel(eq(SystemMessage.NOTE_SOFTAP_CONFIG_CHANGED)); + } } diff --git a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java index 6a248161c..f04f53130 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java @@ -2838,4 +2838,31 @@ public class WifiServiceImplTest { mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent); verifyNoMoreInteractions(mWifiCountryCode); } + + /** + * Verify calls to notify users of a softap config change check the NETWORK_SETTINGS permission. + */ + @Test + public void testNotifyUserOfApBandConversionChecksNetworkSettingsPermission() { + mWifiServiceImpl.notifyUserOfApBandConversion(TEST_PACKAGE_NAME); + verify(mContext).enforceCallingOrSelfPermission( + eq(android.Manifest.permission.NETWORK_SETTINGS), + eq("WifiService")); + verify(mWifiApConfigStore).notifyUserOfApBandConversion(eq(TEST_PACKAGE_NAME)); + } + + /** + * Verify calls to notify users do not trigger a notification when NETWORK_SETTINGS is not held + * by the caller. + */ + @Test + public void testNotifyUserOfApBandConversionThrowsExceptionWithoutNetworkSettingsPermission() { + doThrow(new SecurityException()).when(mContext) + .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), + eq("WifiService")); + try { + mWifiServiceImpl.notifyUserOfApBandConversion(TEST_PACKAGE_NAME); + fail("Expected Security exception"); + } catch (SecurityException e) { } + } } |