• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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.ProgressDialog;
20 import android.content.Intent;
21 import android.net.wifi.ScanResult;
22 import android.net.wifi.WifiConfiguration;
23 import android.net.wifi.WifiInfo;
24 import android.net.wifi.WifiManager;
25 import android.net.wifi.WifiManager.NetworkRequestMatchCallback;
26 import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback;
27 import android.os.Bundle;
28 import android.os.Handler;
29 import android.os.HandlerExecutor;
30 import android.os.Message;
31 import android.widget.Toast;
32 
33 import androidx.annotation.Nullable;
34 import androidx.annotation.VisibleForTesting;
35 import androidx.fragment.app.FragmentActivity;
36 
37 import com.android.settings.R;
38 import com.android.settings.wifi.NetworkRequestErrorDialogFragment.ERROR_DIALOG_TYPE;
39 
40 import java.util.List;
41 
42 /**
43  * When other applications request to have a wifi connection, framework will bring up this activity
44  * to let user select which wifi ap wanna to connect. This activity contains
45  * {@code NetworkRequestDialogFragment}, {@code NetworkRequestSingleSsidDialogFragment} to show UI
46  * and handles framework callback.
47  */
48 public class NetworkRequestDialogActivity extends FragmentActivity implements
49         NetworkRequestMatchCallback {
50     private static String TAG = "NetworkRequestDialogActivity";
51 
52     /** Message sent to stop scanning wifi and pop up timeout dialog. */
53     private static final int MESSAGE_STOP_SCAN_WIFI_LIST = 0;
54 
55     /** Delayed time to stop scanning wifi. */
56     private static final int DELAY_TIME_STOP_SCAN_MS = 30 * 1000;
57 
58     final static String EXTRA_IS_SPECIFIED_SSID =
59         "com.android.settings.wifi.extra.REQUEST_IS_FOR_SINGLE_NETWORK";
60 
61     @VisibleForTesting
62     NetworkRequestDialogBaseFragment mDialogFragment;
63     @VisibleForTesting
64     boolean mIsSpecifiedSsid;
65     @VisibleForTesting
66     boolean mShowingErrorDialog;
67     @VisibleForTesting
68     ProgressDialog mProgressDialog;
69 
70     private NetworkRequestUserSelectionCallback mUserSelectionCallback;
71     private WifiConfiguration mMatchedConfig;
72 
73     @Override
onCreate(@ullable Bundle savedInstanceState)74     protected void onCreate(@Nullable Bundle savedInstanceState) {
75         super.onCreate(savedInstanceState);
76 
77         final Intent intent = getIntent();
78         if (intent != null) {
79             mIsSpecifiedSsid = intent.getBooleanExtra(EXTRA_IS_SPECIFIED_SSID, false);
80         }
81 
82         if (mIsSpecifiedSsid) {
83             showProgressDialog(getString(R.string.network_connection_searching_message));
84         } else {
85             mDialogFragment = NetworkRequestDialogFragment.newInstance();
86             mDialogFragment.show(getSupportFragmentManager(), TAG);
87         }
88     }
89 
showProgressDialog(String message)90     private void showProgressDialog(String message) {
91         dismissDialogs();
92 
93         mProgressDialog = new ProgressDialog(this);
94         mProgressDialog.setIndeterminate(true);
95         mProgressDialog.setCancelable(false);
96         mProgressDialog.setMessage(message);
97         mProgressDialog.show();
98     }
99 
showSingleSsidRequestDialog(String ssid, boolean isTryAgain)100     private void showSingleSsidRequestDialog(String ssid, boolean isTryAgain) {
101         dismissDialogs();
102 
103         mDialogFragment = new NetworkRequestSingleSsidDialogFragment();
104         final Bundle bundle = new Bundle();
105         bundle.putString(NetworkRequestSingleSsidDialogFragment.EXTRA_SSID, ssid);
106         bundle.putBoolean(NetworkRequestSingleSsidDialogFragment.EXTRA_TRYAGAIN, isTryAgain);
107         mDialogFragment.setArguments(bundle);
108         mDialogFragment.show(getSupportFragmentManager(), TAG);
109     }
110 
111     @VisibleForTesting
dismissDialogs()112     void dismissDialogs() {
113         if (mDialogFragment != null) {
114             mDialogFragment.dismiss();
115             mDialogFragment = null;
116         }
117         if (mProgressDialog != null) {
118             mProgressDialog.dismiss();
119             mProgressDialog = null;
120         }
121     }
122 
123     @Override
onResume()124     protected void onResume() {
125         super.onResume();
126 
127         final WifiManager wifiManager = getSystemService(WifiManager.class);
128         if (wifiManager != null) {
129             wifiManager.registerNetworkRequestMatchCallback(new HandlerExecutor(mHandler), this);
130         }
131         // Sets time-out to stop scanning.
132         mHandler.sendEmptyMessageDelayed(MESSAGE_STOP_SCAN_WIFI_LIST, DELAY_TIME_STOP_SCAN_MS);
133     }
134 
135     @Override
onPause()136     protected void onPause() {
137         mHandler.removeMessages(MESSAGE_STOP_SCAN_WIFI_LIST);
138         final WifiManager wifiManager = getSystemService(WifiManager.class);
139         if (wifiManager != null) {
140             wifiManager.unregisterNetworkRequestMatchCallback(this);
141         }
142 
143         super.onPause();
144     }
145 
146     private final Handler mHandler = new Handler() {
147         @Override
148         public void handleMessage(Message msg) {
149             switch (msg.what) {
150                 case MESSAGE_STOP_SCAN_WIFI_LIST:
151                     removeMessages(MESSAGE_STOP_SCAN_WIFI_LIST);
152                     stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE.TIME_OUT);
153                     break;
154                 default:
155                     // Do nothing.
156                     break;
157             }
158         }
159     };
160 
stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE type)161     protected void stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE type) {
162         dismissDialogs();
163 
164         // Throws error dialog.
165         final NetworkRequestErrorDialogFragment dialogFragment =
166                 NetworkRequestErrorDialogFragment.newInstance();
167         dialogFragment.setRejectCallback(mUserSelectionCallback);
168         final Bundle bundle = new Bundle();
169         bundle.putSerializable(NetworkRequestErrorDialogFragment.DIALOG_TYPE, type);
170         dialogFragment.setArguments(bundle);
171         dialogFragment.show(getSupportFragmentManager(), TAG);
172         mShowingErrorDialog = true;
173     }
174 
175     @Override
onUserSelectionCallbackRegistration( NetworkRequestUserSelectionCallback userSelectionCallback)176     public void onUserSelectionCallbackRegistration(
177         NetworkRequestUserSelectionCallback userSelectionCallback) {
178         if (mIsSpecifiedSsid) {
179             mUserSelectionCallback = userSelectionCallback;
180             return;
181         }
182 
183         if (mDialogFragment != null) {
184             mDialogFragment.onUserSelectionCallbackRegistration(userSelectionCallback);
185         }
186     }
187 
188     @Override
onAbort()189     public void onAbort() {
190         stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE.ABORT);
191     }
192 
193     @Override
onMatch(List<ScanResult> scanResults)194     public void onMatch(List<ScanResult> scanResults) {
195         if (mShowingErrorDialog) {
196             // Don't do anything since error dialog shows.
197             return;
198         }
199 
200         mHandler.removeMessages(MESSAGE_STOP_SCAN_WIFI_LIST);
201 
202         if (mIsSpecifiedSsid) {
203             // Prevent from throwing same dialog, because onMatch() will be called many times.
204             if (mMatchedConfig == null) {
205                 mMatchedConfig = WifiUtils.getWifiConfig(null /* wifiEntry */, scanResults.get(0));
206                 showSingleSsidRequestDialog(
207                         WifiInfo.sanitizeSsid(mMatchedConfig.SSID), false /* isTryAgain */);
208             }
209             return;
210         }
211 
212         if (mDialogFragment != null) {
213             mDialogFragment.onMatch(scanResults);
214         }
215     }
216 
217     @Override
onUserSelectionConnectSuccess(WifiConfiguration wificonfiguration)218     public void onUserSelectionConnectSuccess(WifiConfiguration wificonfiguration) {
219         if (!isFinishing()) {
220             Toast.makeText(this, R.string.network_connection_connect_successful, Toast.LENGTH_SHORT)
221                     .show();
222             setResult(RESULT_OK);
223             finish();
224         }
225     }
226 
227     @Override
onUserSelectionConnectFailure(WifiConfiguration wificonfiguration)228     public void onUserSelectionConnectFailure(WifiConfiguration wificonfiguration) {
229         if (!isFinishing()) {
230             Toast.makeText(this, R.string.network_connection_connect_failure, Toast.LENGTH_SHORT)
231                     .show();
232             setResult(RESULT_OK);
233             finish();
234         }
235     }
236 
237     // Called when user click "Connect" button. Called by
238     // {@code NetworkRequestSingleSsidDialogFragment}.
onClickConnectButton()239     public void onClickConnectButton() {
240         if (mUserSelectionCallback != null) {
241             mUserSelectionCallback.select(mMatchedConfig);
242             showProgressDialog(getString(R.string.network_connection_connecting_message));
243         }
244     }
245 
246     // Called when user click retry button. Called by {@link NetworkRequestErrorDialogFragment}.
onClickRescanButton()247     public void onClickRescanButton() {
248         // Sets time-out to stop scanning.
249         mHandler.sendEmptyMessageDelayed(MESSAGE_STOP_SCAN_WIFI_LIST, DELAY_TIME_STOP_SCAN_MS);
250 
251         mShowingErrorDialog = false;
252 
253         if (mIsSpecifiedSsid) {
254             mMatchedConfig = null;
255             showProgressDialog(getString(R.string.network_connection_searching_message));
256         } else {
257             mDialogFragment = NetworkRequestDialogFragment.newInstance();
258             mDialogFragment.show(getSupportFragmentManager(), TAG);
259         }
260     }
261 
262     // Called when user click cancel button.
onCancel()263     public void onCancel() {
264         dismissDialogs();
265 
266         if (mUserSelectionCallback != null) {
267             mUserSelectionCallback.reject();
268         }
269         finish();
270     }
271 }
272