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