1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 
17 package com.android.settings.wifi;
18 
19 import android.app.Activity;
20 import android.content.DialogInterface;
21 import android.content.Intent;
22 import android.net.NetworkInfo;
23 import android.net.wifi.WifiConfiguration;
24 import android.net.wifi.WifiManager;
25 import android.net.wifi.WifiManager.ActionListener;
26 import android.os.Bundle;
27 import android.util.Log;
28 
29 import androidx.annotation.VisibleForTesting;
30 
31 import com.android.settings.R;
32 import com.android.settings.SetupWizardUtils;
33 import com.android.settings.wifi.dpp.WifiDppUtils;
34 import com.android.settingslib.wifi.AccessPoint;
35 
36 import com.google.android.setupcompat.util.WizardManagerHelper;
37 
38 public class WifiDialogActivity extends Activity implements WifiDialog.WifiDialogListener,
39         DialogInterface.OnDismissListener {
40 
41     private static final String TAG = "WifiDialogActivity";
42 
43     public static final String KEY_ACCESS_POINT_STATE = "access_point_state";
44 
45     /**
46      * Boolean extra indicating whether this activity should connect to an access point on the
47      * caller's behalf. If this is set to false, the caller should check
48      * {@link #KEY_WIFI_CONFIGURATION} in the result data and save that using
49      * {@link WifiManager#connect(WifiConfiguration, ActionListener)}. Default is true.
50      */
51     @VisibleForTesting
52     static final String KEY_CONNECT_FOR_CALLER = "connect_for_caller";
53 
54     public static final String KEY_WIFI_CONFIGURATION = "wifi_configuration";
55 
56     private static final int RESULT_CONNECTED = RESULT_FIRST_USER;
57     private static final int RESULT_FORGET = RESULT_FIRST_USER + 1;
58 
59     private static final int REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER = 0;
60 
61     private WifiDialog mDialog;
62 
63     private Intent mIntent;
64 
65     @Override
onCreate(Bundle savedInstanceState)66     protected void onCreate(Bundle savedInstanceState) {
67         mIntent = getIntent();
68         if (WizardManagerHelper.isSetupWizardIntent(mIntent)) {
69             setTheme(SetupWizardUtils.getTransparentTheme(mIntent));
70         }
71 
72         super.onCreate(savedInstanceState);
73 
74         final Bundle accessPointState = mIntent.getBundleExtra(KEY_ACCESS_POINT_STATE);
75         AccessPoint accessPoint = null;
76         if (accessPointState != null) {
77             accessPoint = new AccessPoint(this, accessPointState);
78         }
79 
80         if (WizardManagerHelper.isAnySetupWizard(getIntent())) {
81             mDialog = WifiDialog.createModal(this, this, accessPoint,
82                     WifiConfigUiBase.MODE_CONNECT, R.style.SuwAlertDialogThemeCompat_Light);
83         } else {
84             mDialog = WifiDialog.createModal(
85                     this, this, accessPoint, WifiConfigUiBase.MODE_CONNECT);
86         }
87         mDialog.show();
88         mDialog.setOnDismissListener(this);
89     }
90 
91     @Override
finish()92     public void finish() {
93         super.finish();
94         overridePendingTransition(0, 0);
95     }
96 
97     @Override
onDestroy()98     public void onDestroy() {
99         super.onDestroy();
100         if (mDialog != null && mDialog.isShowing()) {
101             mDialog.dismiss();
102             mDialog = null;
103         }
104     }
105 
106     @Override
onForget(WifiDialog dialog)107     public void onForget(WifiDialog dialog) {
108         final WifiManager wifiManager = getSystemService(WifiManager.class);
109         final AccessPoint accessPoint = dialog.getController().getAccessPoint();
110         if (accessPoint != null) {
111             if (!accessPoint.isSaved()) {
112                 if (accessPoint.getNetworkInfo() != null &&
113                         accessPoint.getNetworkInfo().getState() != NetworkInfo.State.DISCONNECTED) {
114                     // Network is active but has no network ID - must be ephemeral.
115                     wifiManager.disableEphemeralNetwork(
116                             AccessPoint.convertToQuotedString(accessPoint.getSsidStr()));
117                 } else {
118                     // Should not happen, but a monkey seems to trigger it
119                     Log.e(TAG, "Failed to forget invalid network " + accessPoint.getConfig());
120                 }
121             } else {
122                 wifiManager.forget(accessPoint.getConfig().networkId, null /* listener */);
123             }
124         }
125 
126         Intent resultData = new Intent();
127         if (accessPoint != null) {
128             Bundle accessPointState = new Bundle();
129             accessPoint.saveWifiState(accessPointState);
130             resultData.putExtra(KEY_ACCESS_POINT_STATE, accessPointState);
131         }
132         setResult(RESULT_FORGET);
133         finish();
134     }
135 
136     @Override
onSubmit(WifiDialog dialog)137     public void onSubmit(WifiDialog dialog) {
138         final WifiConfiguration config = dialog.getController().getConfig();
139         final AccessPoint accessPoint = dialog.getController().getAccessPoint();
140         final WifiManager wifiManager = getSystemService(WifiManager.class);
141 
142         if (getIntent().getBooleanExtra(KEY_CONNECT_FOR_CALLER, true)) {
143             if (config == null) {
144                 if (accessPoint != null && accessPoint.isSaved()) {
145                     wifiManager.connect(accessPoint.getConfig(), null /* listener */);
146                 }
147             } else {
148                 wifiManager.save(config, null /* listener */);
149                 if (accessPoint != null) {
150                     // accessPoint is null for "Add network"
151                     NetworkInfo networkInfo = accessPoint.getNetworkInfo();
152                     if (networkInfo == null || !networkInfo.isConnected()) {
153                         wifiManager.connect(config, null /* listener */);
154                     }
155                 }
156             }
157         }
158 
159         Intent resultData = new Intent();
160         if (accessPoint != null) {
161             Bundle accessPointState = new Bundle();
162             accessPoint.saveWifiState(accessPointState);
163             resultData.putExtra(KEY_ACCESS_POINT_STATE, accessPointState);
164         }
165         if (config != null) {
166             resultData.putExtra(KEY_WIFI_CONFIGURATION, config);
167         }
168         setResult(RESULT_CONNECTED, resultData);
169         finish();
170     }
171 
172     @Override
onDismiss(DialogInterface dialogInterface)173     public void onDismiss(DialogInterface dialogInterface) {
174         mDialog = null;
175         finish();
176     }
177 
178     @Override
onScan(WifiDialog dialog, String ssid)179     public void onScan(WifiDialog dialog, String ssid) {
180         Intent intent = WifiDppUtils.getEnrolleeQrCodeScannerIntent(ssid);
181         WizardManagerHelper.copyWizardManagerExtras(mIntent, intent);
182 
183         // Launch QR code scanner to join a network.
184         startActivityForResult(intent, REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER);
185     }
186 
187     @Override
onActivityResult(int requestCode, int resultCode, Intent data)188     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
189         super.onActivityResult(requestCode, resultCode, data);
190 
191         if (requestCode == REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER) {
192             if (resultCode != RESULT_OK) {
193                 return;
194             }
195 
196             setResult(RESULT_CONNECTED, data);
197             finish();
198         }
199     }
200 }
201