• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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.BroadcastReceiver;
21 import android.content.Context;
22 import android.content.DialogInterface;
23 import android.content.Intent;
24 import android.content.IntentFilter;
25 import android.content.pm.ApplicationInfo;
26 import android.content.pm.PackageItemInfo;
27 import android.content.pm.PackageManager;
28 import android.net.wifi.WifiManager;
29 import android.os.Bundle;
30 import android.text.TextUtils;
31 import android.util.Log;
32 import android.widget.Toast;
33 
34 import androidx.annotation.NonNull;
35 
36 import com.android.internal.app.AlertActivity;
37 import com.android.settings.R;
38 
39 /**
40  * This activity handles requests to toggle WiFi by collecting user
41  * consent and waiting until the state change is completed.
42  */
43 public class RequestToggleWiFiActivity extends AlertActivity
44         implements DialogInterface.OnClickListener {
45     private static final String LOG_TAG = "RequestToggleWiFiActivity";
46 
47     private static final long TOGGLE_TIMEOUT_MILLIS = 10000; // 10 sec
48 
49     private static final int STATE_UNKNOWN = -1;
50     private static final int STATE_ENABLE = 1;
51     private static final int STATE_ENABLING = 2;
52     private static final int STATE_DISABLE = 3;
53     private static final int STATE_DISABLING = 4;
54 
55     private final StateChangeReceiver mReceiver = new StateChangeReceiver();
56 
57     private final Runnable mTimeoutCommand = () -> {
58         if (!isFinishing() && !isDestroyed()) {
59             finish();
60         }
61     };
62 
63     private @NonNull WifiManager mWiFiManager;
64     private @NonNull CharSequence mAppLabel;
65 
66     private int mState = STATE_UNKNOWN;
67     private int mLastUpdateState = STATE_UNKNOWN;
68 
69     @Override
onCreate(Bundle savedInstanceState)70     protected void onCreate(Bundle savedInstanceState) {
71         super.onCreate(savedInstanceState);
72 
73         mWiFiManager = getSystemService(WifiManager.class);
74 
75         setResult(Activity.RESULT_CANCELED);
76 
77         String packageName = getIntent().getStringExtra(Intent.EXTRA_PACKAGE_NAME);
78         if (TextUtils.isEmpty(packageName)) {
79             finish();
80             return;
81         }
82 
83         try {
84             ApplicationInfo applicationInfo = getPackageManager().getApplicationInfo(
85                     packageName, 0);
86             mAppLabel = applicationInfo.loadSafeLabel(getPackageManager(),
87                     PackageItemInfo.DEFAULT_MAX_LABEL_SIZE_PX, PackageItemInfo.SAFE_LABEL_FLAG_TRIM
88                             | PackageItemInfo.SAFE_LABEL_FLAG_FIRST_LINE);
89         } catch (PackageManager.NameNotFoundException e) {
90             Log.e(LOG_TAG, "Couldn't find app with package name " + packageName);
91             finish();
92             return;
93         }
94 
95         String action = getIntent().getAction();
96         switch (action) {
97             case WifiManager.ACTION_REQUEST_ENABLE: {
98                 mState = STATE_ENABLE;
99             } break;
100 
101             case WifiManager.ACTION_REQUEST_DISABLE: {
102                 mState = STATE_DISABLE;
103             } break;
104 
105             default: {
106                 finish();
107             }
108         }
109     }
110 
111     @Override
onClick(DialogInterface dialog, int which)112     public void onClick(DialogInterface dialog, int which) {
113         switch (which) {
114             case DialogInterface.BUTTON_POSITIVE: {
115                 switch (mState) {
116                     case STATE_ENABLE: {
117                         mWiFiManager.setWifiEnabled(true);
118                         mState = STATE_ENABLING;
119                         scheduleToggleTimeout();
120                         updateUi();
121                     } break;
122 
123                     case STATE_DISABLE: {
124                         mWiFiManager.setWifiEnabled(false);
125                         mState = STATE_DISABLING;
126                         scheduleToggleTimeout();
127                         updateUi();
128                     } break;
129                 }
130             }
131             break;
132             case DialogInterface.BUTTON_NEGATIVE: {
133                 finish();
134             }
135             break;
136         }
137     }
138 
139     @Override
onStart()140     protected void onStart() {
141         super.onStart();
142 
143         mReceiver.register();
144 
145         final int wifiState = mWiFiManager.getWifiState();
146 
147         switch (mState) {
148             case STATE_ENABLE: {
149                 switch (wifiState) {
150                     case WifiManager.WIFI_STATE_ENABLED: {
151                         setResult(RESULT_OK);
152                         finish();
153                     } return;
154 
155                     case WifiManager.WIFI_STATE_ENABLING: {
156                         mState = STATE_ENABLING;
157                         scheduleToggleTimeout();
158                     } break;
159                 }
160             } break;
161 
162             case STATE_DISABLE: {
163                 switch (wifiState) {
164                     case WifiManager.WIFI_STATE_DISABLED: {
165                         setResult(RESULT_OK);
166                         finish();
167                     }
168                     return;
169 
170                     case WifiManager.WIFI_STATE_ENABLING: {
171                         mState = STATE_DISABLING;
172                         scheduleToggleTimeout();
173                     }
174                     break;
175                 }
176             } break;
177 
178             case STATE_ENABLING: {
179                 switch (wifiState) {
180                     case WifiManager.WIFI_STATE_ENABLED: {
181                         setResult(RESULT_OK);
182                         finish();
183                     } return;
184 
185                     case WifiManager.WIFI_STATE_ENABLING: {
186                         scheduleToggleTimeout();
187                     } break;
188 
189                     case WifiManager.WIFI_STATE_DISABLED:
190                     case WifiManager.WIFI_STATE_DISABLING: {
191                         mState = STATE_ENABLE;
192                     } break;
193                 }
194             } break;
195 
196             case STATE_DISABLING: {
197                 switch (wifiState) {
198                     case WifiManager.WIFI_STATE_DISABLED: {
199                         setResult(RESULT_OK);
200                         finish();
201                     } return;
202 
203                     case WifiManager.WIFI_STATE_DISABLING: {
204                         scheduleToggleTimeout();
205                     } break;
206 
207                     case WifiManager.WIFI_STATE_ENABLED:
208                     case WifiManager.WIFI_STATE_ENABLING: {
209                         mState = STATE_DISABLE;
210                     } break;
211                 }
212             } break;
213         }
214 
215         updateUi();
216     }
217 
218     @Override
onStop()219     protected void onStop() {
220         mReceiver.unregister();
221         unscheduleToggleTimeout();
222         super.onStop();
223     }
224 
updateUi()225     private void updateUi() {
226         if (mLastUpdateState == mState) {
227             return;
228         }
229         mLastUpdateState = mState;
230 
231         switch (mState) {
232             case STATE_ENABLE: {
233                 mAlertParams.mPositiveButtonText = getString(R.string.allow);
234                 mAlertParams.mPositiveButtonListener = this;
235                 mAlertParams.mNegativeButtonText = getString(R.string.deny);
236                 mAlertParams.mNegativeButtonListener = this;
237                 mAlertParams.mMessage = getString(R.string.wifi_ask_enable, mAppLabel);
238             } break;
239 
240             case STATE_ENABLING: {
241                 // Params set button text only if non-null, but we want a null
242                 // button text to hide the button, so reset the controller directly.
243                 mAlert.setButton(DialogInterface.BUTTON_POSITIVE, null, null, null);
244                 mAlert.setButton(DialogInterface.BUTTON_NEGATIVE, null, null, null);
245                 mAlertParams.mPositiveButtonText = null;
246                 mAlertParams.mPositiveButtonListener = null;
247                 mAlertParams.mNegativeButtonText = null;
248                 mAlertParams.mNegativeButtonListener = null;
249                 mAlertParams.mMessage = getString(R.string.wifi_starting);
250             } break;
251 
252             case STATE_DISABLE: {
253                 mAlertParams.mPositiveButtonText = getString(R.string.allow);
254                 mAlertParams.mPositiveButtonListener = this;
255                 mAlertParams.mNegativeButtonText = getString(R.string.deny);
256                 mAlertParams.mNegativeButtonListener = this;
257                 mAlertParams.mMessage = getString(R.string.wifi_ask_disable, mAppLabel);
258             } break;
259 
260             case STATE_DISABLING: {
261                 // Params set button text only if non-null, but we want a null
262                 // button text to hide the button, so reset the controller directly.
263                 mAlert.setButton(DialogInterface.BUTTON_POSITIVE, null, null, null);
264                 mAlert.setButton(DialogInterface.BUTTON_NEGATIVE, null, null, null);
265                 mAlertParams.mPositiveButtonText = null;
266                 mAlertParams.mPositiveButtonListener = null;
267                 mAlertParams.mNegativeButtonText = null;
268                 mAlertParams.mNegativeButtonListener = null;
269                 mAlertParams.mMessage = getString(R.string.wifi_stopping);
270             } break;
271         }
272 
273         setupAlert();
274     }
275 
276     @Override
dismiss()277     public void dismiss() {
278         // Clicking on the dialog buttons dismisses the dialog and finishes
279         // the activity but we want to finish after the WiFi state changed.
280     }
281 
scheduleToggleTimeout()282     private void scheduleToggleTimeout() {
283         getWindow().getDecorView().postDelayed(mTimeoutCommand, TOGGLE_TIMEOUT_MILLIS);
284     }
285 
unscheduleToggleTimeout()286     private void unscheduleToggleTimeout() {
287         getWindow().getDecorView().removeCallbacks(mTimeoutCommand);
288     }
289 
290     private final class StateChangeReceiver extends BroadcastReceiver {
291         private final IntentFilter mFilter = new IntentFilter(
292                 WifiManager.WIFI_STATE_CHANGED_ACTION);
293 
register()294         public void register() {
295             registerReceiver(this, mFilter);
296         }
297 
unregister()298         public void unregister() {
299             unregisterReceiver(this);
300         }
301 
onReceive(Context context, Intent intent)302         public void onReceive(Context context, Intent intent) {
303             Activity activity = RequestToggleWiFiActivity.this;
304             if (activity.isFinishing() || activity.isDestroyed()) {
305                 return;
306             }
307             final int currentState = mWiFiManager.getWifiState();
308             switch (currentState) {
309                 case WifiManager.WIFI_STATE_ENABLED:
310                 case WifiManager.WIFI_STATE_DISABLED: {
311                     if (mState == STATE_ENABLING || mState == STATE_DISABLING) {
312                         RequestToggleWiFiActivity.this.setResult(Activity.RESULT_OK);
313                         finish();
314                     }
315                 } break;
316 
317                 case WifiManager.ERROR: {
318                     Toast.makeText(activity, R.string.wifi_error, Toast.LENGTH_SHORT).show();
319                     finish();
320                 } break;
321             }
322         }
323     }
324 }
325