2 * Copyright (C) 2018 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.android.settings.wifi.dpp;
19 import android.app.ActionBar;
20 import android.app.Activity;
21 import android.app.settings.SettingsEnums;
22 import android.content.Intent;
23 import android.os.Bundle;
24 import android.provider.Settings;
25 import android.util.Log;
27 import androidx.annotation.VisibleForTesting;
28 import androidx.fragment.app.Fragment;
29 import androidx.fragment.app.FragmentManager;
30 import androidx.fragment.app.FragmentTransaction;
32 import com.android.settings.R;
33 import com.android.settings.core.InstrumentedActivity;
36 * To provision "other" device with specified Wi-Fi network.
38 * Uses different intents to specify different provisioning ways.
40 * For intent action {@code ACTION_CONFIGURATOR_QR_CODE_SCANNER} and
41 * {@code android.settings.WIFI_DPP_CONFIGURATOR_QR_CODE_GENERATOR}, specify the Wi-Fi network to be
44 * {@code WifiDppUtils.EXTRA_WIFI_SECURITY}
45 * {@code WifiDppUtils.EXTRA_WIFI_SSID}
46 * {@code WifiDppUtils.EXTRA_WIFI_PRE_SHARED_KEY}
47 * {@code WifiDppUtils.EXTRA_WIFI_HIDDEN_SSID}
49 * For intent action {@link Settings#ACTION_PROCESS_WIFI_EASY_CONNECT_QR_CODE}, specify Wi-Fi (DPP)
50 * QR code in {@code WifiDppUtils.EXTRA_QR_CODE}
52 public class WifiDppConfiguratorActivity extends InstrumentedActivity implements
53 WifiNetworkConfig.Retriever,
54 WifiDppQrCodeGeneratorFragment.OnQrCodeGeneratorFragmentAddButtonClickedListener,
55 WifiDppQrCodeScannerFragment.OnScanWifiDppSuccessListener,
56 WifiDppQrCodeScannerFragment.OnScanZxingWifiFormatSuccessListener,
57 WifiDppAddDeviceFragment.OnClickChooseDifferentNetworkListener,
58 WifiNetworkListFragment.OnChooseNetworkListener {
60 private static final String TAG = "WifiDppConfiguratorActivity";
62 public static final String ACTION_CONFIGURATOR_QR_CODE_SCANNER =
63 "android.settings.WIFI_DPP_CONFIGURATOR_QR_CODE_SCANNER";
64 public static final String ACTION_CONFIGURATOR_QR_CODE_GENERATOR =
65 "android.settings.WIFI_DPP_CONFIGURATOR_QR_CODE_GENERATOR";
67 // Key for Bundle usage
68 private static final String KEY_QR_CODE = "key_qr_code";
69 private static final String KEY_WIFI_SECURITY = "key_wifi_security";
70 private static final String KEY_WIFI_SSID = "key_wifi_ssid";
71 private static final String KEY_WIFI_PRESHARED_KEY = "key_wifi_preshared_key";
72 private static final String KEY_WIFI_HIDDEN_SSID = "key_wifi_hidden_ssid";
73 private static final String KEY_WIFI_NETWORK_ID = "key_wifi_network_id";
75 private FragmentManager mFragmentManager;
77 /** The Wi-Fi network which will be configured */
78 private WifiNetworkConfig mWifiNetworkConfig;
80 /** The Wi-Fi DPP QR code from intent ACTION_PROCESS_WIFI_EASY_CONNECT_QR_CODE */
81 private WifiQrCode mWifiDppQrCode;
82 /** Secret extra that allows fake networks to show in UI for testing purposes */
83 private boolean mIsTest;
86 public int getMetricsCategory() {
87 return SettingsEnums.SETTINGS_WIFI_DPP_CONFIGURATOR;
91 protected void onCreate(Bundle savedInstanceState) {
92 super.onCreate(savedInstanceState);
94 if (savedInstanceState != null) {
95 String qrCode = savedInstanceState.getString(KEY_QR_CODE);
97 mWifiDppQrCode = getValidWifiDppQrCodeOrNull(qrCode);
99 String security = savedInstanceState.getString(KEY_WIFI_SECURITY);
100 String ssid = savedInstanceState.getString(KEY_WIFI_SSID);
101 String preSharedKey = savedInstanceState.getString(KEY_WIFI_PRESHARED_KEY);
102 boolean hiddenSsid = savedInstanceState.getBoolean(KEY_WIFI_HIDDEN_SSID);
103 int networkId = savedInstanceState.getInt(KEY_WIFI_NETWORK_ID);
105 mWifiNetworkConfig = WifiNetworkConfig.getValidConfigOrNull(security, ssid,
106 preSharedKey, hiddenSsid, networkId);
109 setContentView(R.layout.wifi_dpp_activity);
110 mFragmentManager = getSupportFragmentManager();
112 handleIntent(getIntent());
114 ActionBar actionBar = getActionBar();
115 if (actionBar != null) {
116 actionBar.setElevation(0);
117 actionBar.setDisplayShowTitleEnabled(false);
121 private void handleIntent(Intent intent) {
122 boolean cancelActivity = false;
123 WifiNetworkConfig config;
124 switch (intent.getAction()) {
125 case ACTION_CONFIGURATOR_QR_CODE_SCANNER:
126 config = WifiNetworkConfig.getValidConfigOrNull(intent);
127 if (config == null) {
128 cancelActivity = true;
130 mWifiNetworkConfig = config;
131 showQrCodeScannerFragment(/* addToBackStack= */ false);
134 case ACTION_CONFIGURATOR_QR_CODE_GENERATOR:
135 config = WifiNetworkConfig.getValidConfigOrNull(intent);
136 if (config == null) {
137 cancelActivity = true;
139 mWifiNetworkConfig = config;
140 showQrCodeGeneratorFragment();
143 case Settings.ACTION_PROCESS_WIFI_EASY_CONNECT_QR_CODE:
144 String qrCode = intent.getStringExtra(Settings.EXTRA_QR_CODE);
145 mIsTest = intent.getBooleanExtra(WifiDppUtils.EXTRA_TEST, false);
146 mWifiDppQrCode = getValidWifiDppQrCodeOrNull(qrCode);
147 final boolean isDppSupported = WifiDppUtils.isWifiDppEnabled(this);
148 if (!isDppSupported) {
149 Log.d(TAG, "Device doesn't support Wifi DPP");
151 if (mWifiDppQrCode == null || !isDppSupported) {
152 cancelActivity = true;
154 showChooseSavedWifiNetworkFragment(/* addToBackStack */ false);
158 cancelActivity = true;
159 Log.e(TAG, "Launch with an invalid action");
162 if (cancelActivity) {
163 setResult(Activity.RESULT_CANCELED);
168 private void showQrCodeScannerFragment(boolean addToBackStack) {
169 WifiDppQrCodeScannerFragment fragment =
170 (WifiDppQrCodeScannerFragment) mFragmentManager.findFragmentByTag(
171 WifiDppUtils.TAG_FRAGMENT_QR_CODE_SCANNER);
172 // Avoid to replace the same fragment during configuration change
173 if (fragment != null && fragment.isVisible()) {
177 if (fragment == null) {
178 fragment = new WifiDppQrCodeScannerFragment();
180 final FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
182 fragmentTransaction.replace(R.id.fragment_container, fragment,
183 WifiDppUtils.TAG_FRAGMENT_QR_CODE_SCANNER);
184 if (addToBackStack) {
185 fragmentTransaction.addToBackStack(/* name */ null);
187 fragmentTransaction.commit();
190 private void showQrCodeGeneratorFragment() {
191 WifiDppQrCodeGeneratorFragment fragment =
192 (WifiDppQrCodeGeneratorFragment) mFragmentManager.findFragmentByTag(
193 WifiDppUtils.TAG_FRAGMENT_QR_CODE_GENERATOR);
194 // Avoid to replace the same fragment during configuration change
195 if (fragment != null && fragment.isVisible()) {
199 fragment = new WifiDppQrCodeGeneratorFragment();
200 final FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
202 fragmentTransaction.replace(R.id.fragment_container, fragment,
203 WifiDppUtils.TAG_FRAGMENT_QR_CODE_GENERATOR);
204 fragmentTransaction.commit();
207 private void showChooseSavedWifiNetworkFragment(boolean addToBackStack) {
208 WifiDppChooseSavedWifiNetworkFragment fragment =
209 (WifiDppChooseSavedWifiNetworkFragment) mFragmentManager.findFragmentByTag(
210 WifiDppUtils.TAG_FRAGMENT_CHOOSE_SAVED_WIFI_NETWORK);
211 // Avoid to replace the same fragment during configuration change
212 if (fragment != null && fragment.isVisible()) {
216 if (fragment == null) {
217 fragment = new WifiDppChooseSavedWifiNetworkFragment();
219 Bundle bundle = new Bundle();
220 bundle.putBoolean(WifiDppUtils.EXTRA_TEST, true);
221 fragment.setArguments(bundle);
224 final FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
226 fragmentTransaction.replace(R.id.fragment_container, fragment,
227 WifiDppUtils.TAG_FRAGMENT_CHOOSE_SAVED_WIFI_NETWORK);
228 if (addToBackStack) {
229 fragmentTransaction.addToBackStack(/* name */ null);
231 fragmentTransaction.commit();
234 private void showAddDeviceFragment(boolean addToBackStack) {
235 WifiDppAddDeviceFragment fragment =
236 (WifiDppAddDeviceFragment) mFragmentManager.findFragmentByTag(
237 WifiDppUtils.TAG_FRAGMENT_ADD_DEVICE);
239 // Avoid to replace the same fragment during configuration change
240 if (mFragmentManager.findFragmentByTag(
241 WifiDppUtils.TAG_FRAGMENT_ADD_DEVICE) != null) {
245 if (fragment == null) {
246 fragment = new WifiDppAddDeviceFragment();
248 final FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
250 fragmentTransaction.replace(R.id.fragment_container, fragment,
251 WifiDppUtils.TAG_FRAGMENT_ADD_DEVICE);
252 if (addToBackStack) {
253 fragmentTransaction.addToBackStack(/* name */ null);
255 fragmentTransaction.commit();
258 private WifiQrCode getValidWifiDppQrCodeOrNull(String qrCode) {
259 WifiQrCode wifiQrCode;
261 wifiQrCode = new WifiQrCode(qrCode);
262 } catch(IllegalArgumentException e) {
266 if (WifiQrCode.SCHEME_DPP.equals(wifiQrCode.getScheme())) {
274 public WifiNetworkConfig getWifiNetworkConfig() {
275 return mWifiNetworkConfig;
278 public WifiQrCode getWifiDppQrCode() {
279 return mWifiDppQrCode;
282 @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
283 protected boolean setWifiNetworkConfig(WifiNetworkConfig config) {
284 if(!WifiNetworkConfig.isValidConfig(config)) {
287 mWifiNetworkConfig = new WifiNetworkConfig(config);
292 @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
293 protected boolean setWifiDppQrCode(WifiQrCode wifiQrCode) {
294 if (wifiQrCode == null) {
298 if (!WifiQrCode.SCHEME_DPP.equals(wifiQrCode.getScheme())) {
302 mWifiDppQrCode = new WifiQrCode(wifiQrCode.getQrCode());
307 public boolean onNavigateUp() {
308 Fragment fragment = mFragmentManager.findFragmentById(R.id.fragment_container);
309 if (fragment instanceof WifiDppQrCodeGeneratorFragment) {
310 setResult(Activity.RESULT_CANCELED);
313 } else if (fragment instanceof WifiDppQrCodeScannerFragment) {
314 mFragmentManager.popBackStackImmediate();
321 public void onQrCodeGeneratorFragmentAddButtonClicked() {
322 showQrCodeScannerFragment(/* addToBackStack */ true);
326 public void onScanWifiDppSuccess(WifiQrCode wifiQrCode) {
327 mWifiDppQrCode = wifiQrCode;
329 showAddDeviceFragment(/* addToBackStack */ true);
333 public void onScanZxingWifiFormatSuccess(WifiNetworkConfig wifiNetworkConfig) {
334 // Do nothing, it's impossible to be a configurator without a Wi-Fi DPP QR code
338 public void onClickChooseDifferentNetwork() {
339 showChooseSavedWifiNetworkFragment(/* addToBackStack */ true);
343 public void onSaveInstanceState(Bundle outState) {
344 if (mWifiDppQrCode != null) {
345 outState.putString(KEY_QR_CODE, mWifiDppQrCode.getQrCode());
348 if (mWifiNetworkConfig != null) {
349 outState.putString(KEY_WIFI_SECURITY, mWifiNetworkConfig.getSecurity());
350 outState.putString(KEY_WIFI_SSID, mWifiNetworkConfig.getSsid());
351 outState.putString(KEY_WIFI_PRESHARED_KEY, mWifiNetworkConfig.getPreSharedKey());
352 outState.putBoolean(KEY_WIFI_HIDDEN_SSID, mWifiNetworkConfig.getHiddenSsid());
353 outState.putInt(KEY_WIFI_NETWORK_ID, mWifiNetworkConfig.getNetworkId());
356 super.onSaveInstanceState(outState);
360 public void onChooseNetwork(WifiNetworkConfig wifiNetworkConfig) {
361 mWifiNetworkConfig = new WifiNetworkConfig(wifiNetworkConfig);
363 showAddDeviceFragment(/* addToBackStack */ true);