WifiApConfigStore: convert 5GHZ to ANY for dual mode devices
am: ee38c65d57

Change-Id: Ia15396588b335191b80bac95a8902c3d22c3172c
diff --git a/service/java/com/android/server/wifi/WifiApConfigStore.java b/service/java/com/android/server/wifi/WifiApConfigStore.java
index e8ad748..109c0a7 100644
--- a/service/java/com/android/server/wifi/WifiApConfigStore.java
+++ b/service/java/com/android/server/wifi/WifiApConfigStore.java
@@ -63,6 +63,9 @@
     @VisibleForTesting
     static final int PSK_MAX_LEN = 63;
 
+    @VisibleForTesting
+    static final int AP_CHANNEL_DEFAULT = 0;
+
     private WifiConfiguration mWifiApConfig = null;
 
     private ArrayList<Integer> mAllowed2GChannel = null;
@@ -70,6 +73,7 @@
     private final Context mContext;
     private final String mApConfigFile;
     private final BackupManagerProxy mBackupManagerProxy;
+    private boolean mRequiresApBandConversion = false;
 
     WifiApConfigStore(Context context, BackupManagerProxy backupManagerProxy) {
         this(context, backupManagerProxy, DEFAULT_AP_CONFIG_FILE);
@@ -94,6 +98,9 @@
             }
         }
 
+        mRequiresApBandConversion = mContext.getResources().getBoolean(
+                R.bool.config_wifi_convert_apband_5ghz_to_any);
+
         /* Load AP configuration from persistent storage. */
         mWifiApConfig = loadApConfiguration(mApConfigFile);
         if (mWifiApConfig == null) {
@@ -110,6 +117,12 @@
      * Return the current soft access point configuration.
      */
     public synchronized WifiConfiguration getApConfiguration() {
+        WifiConfiguration config = apBandCheckConvert(mWifiApConfig);
+        if (mWifiApConfig != config) {
+            Log.d(TAG, "persisted config was converted, need to resave it");
+            mWifiApConfig = config;
+            persistConfigAndTriggerBackupManagerProxy(mWifiApConfig);
+        }
         return mWifiApConfig;
     }
 
@@ -123,18 +136,45 @@
         if (config == null) {
             mWifiApConfig = getDefaultApConfiguration();
         } else {
-            mWifiApConfig = config;
+            mWifiApConfig = apBandCheckConvert(config);
         }
-        writeApConfiguration(mApConfigFile, mWifiApConfig);
-
-        // Stage the backup of the SettingsProvider package which backs this up
-        mBackupManagerProxy.notifyDataChanged();
+        persistConfigAndTriggerBackupManagerProxy(mWifiApConfig);
     }
 
     public ArrayList<Integer> getAllowed2GChannel() {
         return mAllowed2GChannel;
     }
 
+    private WifiConfiguration apBandCheckConvert(WifiConfiguration config) {
+        if (mRequiresApBandConversion) {
+            // some devices are unable to support 5GHz only operation, check for 5GHz and
+            // move to ANY if apBand conversion is required.
+            if (config.apBand == WifiConfiguration.AP_BAND_5GHZ) {
+                Log.w(TAG, "Supplied ap config band was 5GHz only, converting to ANY");
+                WifiConfiguration convertedConfig = new WifiConfiguration(config);
+                convertedConfig.apBand = WifiConfiguration.AP_BAND_ANY;
+                convertedConfig.apChannel = AP_CHANNEL_DEFAULT;
+                return convertedConfig;
+            }
+        } else {
+            // this is a single mode device, we do not support ANY.  Convert all ANY to 5GHz
+            if (config.apBand == WifiConfiguration.AP_BAND_ANY) {
+                Log.w(TAG, "Supplied ap config band was ANY, converting to 5GHz");
+                WifiConfiguration convertedConfig = new WifiConfiguration(config);
+                convertedConfig.apBand = WifiConfiguration.AP_BAND_5GHZ;
+                convertedConfig.apChannel = AP_CHANNEL_DEFAULT;
+                return convertedConfig;
+            }
+        }
+        return config;
+    }
+
+    private void persistConfigAndTriggerBackupManagerProxy(WifiConfiguration config) {
+        writeApConfiguration(mApConfigFile, mWifiApConfig);
+        // Stage the backup of the SettingsProvider package which backs this up
+        mBackupManagerProxy.notifyDataChanged();
+    }
+
     /**
      * Load AP configuration from persistent storage.
      */
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiApConfigStoreTest.java b/tests/wifitests/src/com/android/server/wifi/WifiApConfigStoreTest.java
index 7e7edd4..1672dca 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiApConfigStoreTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiApConfigStoreTest.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -61,6 +62,7 @@
     @Mock BackupManagerProxy mBackupManagerProxy;
     File mApConfigFile;
     Random mRandom;
+    MockResources mResources;
 
     @Before
     public void setUp() throws Exception {
@@ -70,14 +72,16 @@
         mApConfigFile = File.createTempFile(TEST_AP_CONFIG_FILE_PREFIX, "");
 
         /* Setup expectations for Resources to return some default settings. */
-        MockResources resources = new MockResources();
-        resources.setString(R.string.config_wifi_framework_sap_2G_channel_list,
+        mResources = new MockResources();
+        mResources.setString(R.string.config_wifi_framework_sap_2G_channel_list,
                             TEST_DEFAULT_2G_CHANNEL_LIST);
-        resources.setString(R.string.wifi_tether_configure_ssid_default,
+        mResources.setString(R.string.wifi_tether_configure_ssid_default,
                             TEST_DEFAULT_AP_SSID);
-        resources.setString(R.string.wifi_localhotspot_configure_ssid_default,
+        mResources.setString(R.string.wifi_localhotspot_configure_ssid_default,
                             TEST_DEFAULT_HOTSPOT_SSID);
-        when(mContext.getResources()).thenReturn(resources);
+        /* Default to device that does not require ap band conversion */
+        mResources.setBoolean(R.bool.config_wifi_convert_apband_5ghz_to_any, false);
+        when(mContext.getResources()).thenReturn(mResources);
 
         mRandom = new Random();
     }
@@ -203,17 +207,231 @@
 
         /* Update with a valid configuration. */
         WifiConfiguration expectedConfig = setupApConfig(
-                "ConfiguredAP",    /* SSID */
-                "randomKey",       /* preshared key */
-                KeyMgmt.WPA_EAP,   /* key management */
-                1,                 /* AP band (5GHz) */
-                40                 /* AP channel */);
+                "ConfiguredAP",                   /* SSID */
+                "randomKey",                      /* preshared key */
+                KeyMgmt.WPA_EAP,                  /* key management */
+                WifiConfiguration.AP_BAND_2GHZ,   /* AP band */
+                40                                /* AP channel */);
         store.setApConfiguration(expectedConfig);
         verifyApConfig(expectedConfig, store.getApConfiguration());
         verify(mBackupManagerProxy).notifyDataChanged();
     }
 
     /**
+     * Due to different device hw capabilities, some bands are not available if a device is
+     * dual/single mode capable.  This test verifies that a single mode device will have apBand =
+     * ANY converted to 5GHZ.
+     */
+    @Test
+    public void convertSingleModeDeviceAnyTo5Ghz() throws Exception {
+        /* Initialize WifiApConfigStore with default configuration. */
+        WifiApConfigStore store = new WifiApConfigStore(
+                mContext, mBackupManagerProxy, mApConfigFile.getPath());
+        verifyDefaultApConfig(store.getApConfiguration(), TEST_DEFAULT_AP_SSID);
+
+        /* Update with a valid configuration. */
+        WifiConfiguration providedConfig = setupApConfig(
+                "ConfiguredAP",                /* SSID */
+                "randomKey",                   /* preshared key */
+                KeyMgmt.WPA_EAP,               /* key management */
+                WifiConfiguration.AP_BAND_ANY, /* AP band (ANY) */
+                40                             /* AP channel */);
+
+        WifiConfiguration expectedConfig = setupApConfig(
+                "ConfiguredAP",                       /* SSID */
+                "randomKey",                          /* preshared key */
+                KeyMgmt.WPA_EAP,                      /* key management */
+                WifiConfiguration.AP_BAND_5GHZ,       /* AP band (5GHz) */
+                WifiApConfigStore.AP_CHANNEL_DEFAULT  /* AP channel */);
+        store.setApConfiguration(providedConfig);
+        verifyApConfig(expectedConfig, store.getApConfiguration());
+        verify(mBackupManagerProxy).notifyDataChanged();
+    }
+
+    /**
+     * Due to different device hw capabilities, some bands are not available if a device is
+     * dual/single mode capable.  This test verifies that a single mode device does not convert
+     * apBand to ANY.
+     */
+    @Test
+    public void singleModeDevice5GhzNotConverted() throws Exception {
+        /* Initialize WifiApConfigStore with default configuration. */
+        WifiApConfigStore store = new WifiApConfigStore(
+                mContext, mBackupManagerProxy, mApConfigFile.getPath());
+        verifyDefaultApConfig(store.getApConfiguration(), TEST_DEFAULT_AP_SSID);
+
+        /* Update with a valid configuration. */
+        WifiConfiguration expectedConfig = setupApConfig(
+                "ConfiguredAP",                 /* SSID */
+                "randomKey",                    /* preshared key */
+                KeyMgmt.WPA_EAP,                /* key management */
+                WifiConfiguration.AP_BAND_5GHZ, /* AP band */
+                40                              /* AP channel */);
+        store.setApConfiguration(expectedConfig);
+        verifyApConfig(expectedConfig, store.getApConfiguration());
+    }
+
+    /**
+     * Due to different device hw capabilities, some bands are not available if a device is
+     * dual/single mode capable.  This test verifies that a dual mode device will have apBand =
+     * 5GHz converted to ANY.
+     */
+    @Test
+    public void convertDualModeDevice5GhzToAny() throws Exception {
+        mResources.setBoolean(R.bool.config_wifi_convert_apband_5ghz_to_any, true);
+
+        /* Initialize WifiApConfigStore with default configuration. */
+        WifiApConfigStore store = new WifiApConfigStore(
+                mContext, mBackupManagerProxy, mApConfigFile.getPath());
+        verifyDefaultApConfig(store.getApConfiguration(), TEST_DEFAULT_AP_SSID);
+
+        /* Update with a valid configuration. */
+        WifiConfiguration providedConfig = setupApConfig(
+                "ConfiguredAP",                 /* SSID */
+                "randomKey",                    /* preshared key */
+                KeyMgmt.WPA_EAP,                /* key management */
+                WifiConfiguration.AP_BAND_5GHZ, /* AP band */
+                40                              /* AP channel */);
+
+        WifiConfiguration expectedConfig = setupApConfig(
+                "ConfiguredAP",                       /* SSID */
+                "randomKey",                          /* preshared key */
+                KeyMgmt.WPA_EAP,                      /* key management */
+                WifiConfiguration.AP_BAND_ANY,        /* AP band */
+                WifiApConfigStore.AP_CHANNEL_DEFAULT  /* AP channel */);
+        store.setApConfiguration(providedConfig);
+        verifyApConfig(expectedConfig, store.getApConfiguration());
+        verify(mBackupManagerProxy).notifyDataChanged();
+    }
+
+    /**
+     * Due to different device hw capabilities, some bands are not available if a device is
+     * dual/single mode capable.  This test verifies that a dual mode device does not convert
+     * apBand to 5Ghz.
+     */
+    @Test
+    public void dualModeDeviceAnyNotConverted() throws Exception {
+        mResources.setBoolean(R.bool.config_wifi_convert_apband_5ghz_to_any, true);
+
+        /* Initialize WifiApConfigStore with default configuration. */
+        WifiApConfigStore store = new WifiApConfigStore(
+                mContext, mBackupManagerProxy, mApConfigFile.getPath());
+        verifyDefaultApConfig(store.getApConfiguration(), TEST_DEFAULT_AP_SSID);
+
+        /* Update with a valid configuration. */
+        WifiConfiguration expectedConfig = setupApConfig(
+                "ConfiguredAP",                 /* SSID */
+                "randomKey",                    /* preshared key */
+                KeyMgmt.WPA_EAP,                /* key management */
+                WifiConfiguration.AP_BAND_ANY,  /* AP band */
+                40                              /* AP channel */);
+        store.setApConfiguration(expectedConfig);
+        verify(mBackupManagerProxy).notifyDataChanged();
+        verifyApConfig(expectedConfig, store.getApConfiguration());
+    }
+
+    /**
+     * Due to different device hw capabilities, some bands are not available if a device is
+     * dual/single mode capable.  This test verifies that a single mode device converts a persisted
+     * ap config with ANY set for the apBand to 5GHz.
+     */
+    @Test
+    public void singleModeDeviceAnyConvertedTo5GhzAtRetrieval() throws Exception {
+
+        WifiConfiguration persistedConfig = setupApConfig(
+                "ConfiguredAP",                 /* SSID */
+                "randomKey",                    /* preshared key */
+                KeyMgmt.WPA_EAP,                /* key management */
+                WifiConfiguration.AP_BAND_ANY,  /* AP band */
+                40                              /* AP channel */);
+        WifiConfiguration expectedConfig = setupApConfig(
+                "ConfiguredAP",                        /* SSID */
+                "randomKey",                           /* preshared key */
+                KeyMgmt.WPA_EAP,                       /* key management */
+                WifiConfiguration.AP_BAND_5GHZ,        /* AP band */
+                WifiApConfigStore.AP_CHANNEL_DEFAULT   /* AP channel */);
+
+        writeApConfigFile(persistedConfig);
+        WifiApConfigStore store = new WifiApConfigStore(
+                mContext, mBackupManagerProxy, mApConfigFile.getPath());
+        verifyApConfig(expectedConfig, store.getApConfiguration());
+        verify(mBackupManagerProxy).notifyDataChanged();
+    }
+
+    /**
+     * Due to different device hw capabilities, some bands are not available if a device is
+     * dual/single mode capable.  This test verifies that a single mode device does not convert
+     * a persisted ap config with 5GHz set for the apBand.
+     */
+    @Test
+    public void singleModeDeviceNotConvertedAtRetrieval() throws Exception {
+        WifiConfiguration persistedConfig = setupApConfig(
+                "ConfiguredAP",                  /* SSID */
+                "randomKey",                     /* preshared key */
+                KeyMgmt.WPA_EAP,                 /* key management */
+                WifiConfiguration.AP_BAND_5GHZ,  /* AP band */
+                40                               /* AP channel */);
+
+        writeApConfigFile(persistedConfig);
+        WifiApConfigStore store = new WifiApConfigStore(
+                mContext, mBackupManagerProxy, mApConfigFile.getPath());
+        verifyApConfig(persistedConfig, store.getApConfiguration());
+        verify(mBackupManagerProxy, never()).notifyDataChanged();
+    }
+
+    /**
+     * Due to different device hw capabilities, some bands are not available if a device is
+     * dual/single mode capable.  This test verifies that a dual mode device converts a persisted ap
+     * config with 5GHz only set for the apBand to ANY.
+     */
+    @Test
+    public void dualModeDevice5GhzConvertedToAnyAtRetrieval() throws Exception {
+        mResources.setBoolean(R.bool.config_wifi_convert_apband_5ghz_to_any, true);
+
+        WifiConfiguration persistedConfig = setupApConfig(
+                "ConfiguredAP",                  /* SSID */
+                "randomKey",                     /* preshared key */
+                KeyMgmt.WPA_EAP,                 /* key management */
+                WifiConfiguration.AP_BAND_5GHZ,  /* AP band */
+                40                               /* AP channel */);
+        WifiConfiguration expectedConfig = setupApConfig(
+                "ConfiguredAP",                       /* SSID */
+                "randomKey",                          /* preshared key */
+                KeyMgmt.WPA_EAP,                      /* key management */
+                WifiConfiguration.AP_BAND_ANY,        /* AP band */
+                WifiApConfigStore.AP_CHANNEL_DEFAULT  /* AP channel */);
+
+        writeApConfigFile(persistedConfig);
+        WifiApConfigStore store = new WifiApConfigStore(
+                mContext, mBackupManagerProxy, mApConfigFile.getPath());
+        verifyApConfig(expectedConfig, store.getApConfiguration());
+        verify(mBackupManagerProxy).notifyDataChanged();
+    }
+
+    /**
+     * Due to different device hw capabilities, some bands are not available if a device is
+     * dual/single mode capable.  This test verifies that a dual mode device does not convert
+     * a persisted ap config with ANY set for the apBand.
+     */
+    @Test
+    public void dualModeDeviceNotConvertedAtRetrieval() throws Exception {
+        mResources.setBoolean(R.bool.config_wifi_convert_apband_5ghz_to_any, true);
+
+        WifiConfiguration persistedConfig = setupApConfig(
+                "ConfiguredAP",                 /* SSID */
+                "randomKey",                    /* preshared key */
+                KeyMgmt.WPA_EAP,                /* key management */
+                WifiConfiguration.AP_BAND_ANY,  /* AP band */
+                40                              /* AP channel */);
+
+        writeApConfigFile(persistedConfig);
+        WifiApConfigStore store = new WifiApConfigStore(
+                mContext, mBackupManagerProxy, mApConfigFile.getPath());
+        verifyApConfig(persistedConfig, store.getApConfiguration());
+        verify(mBackupManagerProxy, never()).notifyDataChanged();
+    }
+
+    /**
      * Verify a proper WifiConfiguration is generate by getDefaultApConfiguration().
      */
     @Test