WifiServiceImpl.java revision 86c849795d49fd407f6b68443c246550a0efd62c
13883e66cfd55de70d89831cf26f9ae53931d11d3Eric Christopher/* 23883e66cfd55de70d89831cf26f9ae53931d11d3Eric Christopher * Copyright (C) 2010 The Android Open Source Project 33883e66cfd55de70d89831cf26f9ae53931d11d3Eric Christopher * 43883e66cfd55de70d89831cf26f9ae53931d11d3Eric Christopher * Licensed under the Apache License, Version 2.0 (the "License"); 53883e66cfd55de70d89831cf26f9ae53931d11d3Eric Christopher * you may not use this file except in compliance with the License. 63883e66cfd55de70d89831cf26f9ae53931d11d3Eric Christopher * You may obtain a copy of the License at 73883e66cfd55de70d89831cf26f9ae53931d11d3Eric Christopher * 83883e66cfd55de70d89831cf26f9ae53931d11d3Eric Christopher * http://www.apache.org/licenses/LICENSE-2.0 93883e66cfd55de70d89831cf26f9ae53931d11d3Eric Christopher * 103883e66cfd55de70d89831cf26f9ae53931d11d3Eric Christopher * Unless required by applicable law or agreed to in writing, software 113883e66cfd55de70d89831cf26f9ae53931d11d3Eric Christopher * distributed under the License is distributed on an "AS IS" BASIS, 123883e66cfd55de70d89831cf26f9ae53931d11d3Eric Christopher * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133883e66cfd55de70d89831cf26f9ae53931d11d3Eric Christopher * See the License for the specific language governing permissions and 143883e66cfd55de70d89831cf26f9ae53931d11d3Eric Christopher * limitations under the License. 153883e66cfd55de70d89831cf26f9ae53931d11d3Eric Christopher */ 163883e66cfd55de70d89831cf26f9ae53931d11d3Eric Christopher 173883e66cfd55de70d89831cf26f9ae53931d11d3Eric Christopherpackage com.android.server.wifi; 183883e66cfd55de70d89831cf26f9ae53931d11d3Eric Christopher 193883e66cfd55de70d89831cf26f9ae53931d11d3Eric Christopherimport static com.android.server.wifi.WifiController.CMD_AIRPLANE_TOGGLED; 203883e66cfd55de70d89831cf26f9ae53931d11d3Eric Christopherimport static com.android.server.wifi.WifiController.CMD_BATTERY_CHANGED; 213883e66cfd55de70d89831cf26f9ae53931d11d3Eric Christopherimport static com.android.server.wifi.WifiController.CMD_EMERGENCY_CALL_STATE_CHANGED; 223883e66cfd55de70d89831cf26f9ae53931d11d3Eric Christopherimport static com.android.server.wifi.WifiController.CMD_EMERGENCY_MODE_CHANGED; 233883e66cfd55de70d89831cf26f9ae53931d11d3Eric Christopherimport static com.android.server.wifi.WifiController.CMD_LOCKS_CHANGED; 24import static com.android.server.wifi.WifiController.CMD_SCAN_ALWAYS_MODE_CHANGED; 25import static com.android.server.wifi.WifiController.CMD_SCREEN_OFF; 26import static com.android.server.wifi.WifiController.CMD_SCREEN_ON; 27import static com.android.server.wifi.WifiController.CMD_SET_AP; 28import static com.android.server.wifi.WifiController.CMD_USER_PRESENT; 29import static com.android.server.wifi.WifiController.CMD_WIFI_TOGGLED; 30 31import android.Manifest; 32import android.app.ActivityManager; 33import android.app.AppOpsManager; 34import android.bluetooth.BluetoothAdapter; 35import android.content.BroadcastReceiver; 36import android.content.Context; 37import android.content.Intent; 38import android.content.IntentFilter; 39import android.content.pm.ApplicationInfo; 40import android.content.pm.PackageManager; 41import android.content.pm.UserInfo; 42import android.database.ContentObserver; 43import android.net.ConnectivityManager; 44import android.net.DhcpInfo; 45import android.net.DhcpResults; 46import android.net.Network; 47import android.net.NetworkScorerAppManager; 48import android.net.NetworkUtils; 49import android.net.Uri; 50import android.net.ip.IpManager; 51import android.net.wifi.IWifiManager; 52import android.net.wifi.PasspointManagementObjectDefinition; 53import android.net.wifi.ScanResult; 54import android.net.wifi.ScanSettings; 55import android.net.wifi.WifiActivityEnergyInfo; 56import android.net.wifi.WifiConfiguration; 57import android.net.wifi.WifiConnectionStatistics; 58import android.net.wifi.WifiEnterpriseConfig; 59import android.net.wifi.WifiInfo; 60import android.net.wifi.WifiLinkLayerStats; 61import android.net.wifi.WifiManager; 62import android.net.wifi.WifiScanner; 63import android.os.AsyncTask; 64import android.os.BatteryStats; 65import android.os.Binder; 66import android.os.Build; 67import android.os.Bundle; 68import android.os.Handler; 69import android.os.HandlerThread; 70import android.os.IBinder; 71import android.os.Looper; 72import android.os.Message; 73import android.os.Messenger; 74import android.os.PowerManager; 75import android.os.Process; 76import android.os.RemoteException; 77import android.os.ResultReceiver; 78import android.os.SystemClock; 79import android.os.UserHandle; 80import android.os.UserManager; 81import android.os.WorkSource; 82import android.provider.Settings; 83import android.text.TextUtils; 84import android.util.Log; 85import android.util.Slog; 86 87import com.android.internal.telephony.IccCardConstants; 88import com.android.internal.telephony.PhoneConstants; 89import com.android.internal.telephony.TelephonyIntents; 90import com.android.internal.util.AsyncChannel; 91import com.android.server.wifi.configparse.ConfigBuilder; 92 93import org.xml.sax.SAXException; 94 95import java.io.BufferedReader; 96import java.io.FileDescriptor; 97import java.io.FileNotFoundException; 98import java.io.FileReader; 99import java.io.IOException; 100import java.io.PrintWriter; 101import java.net.Inet4Address; 102import java.net.InetAddress; 103import java.security.GeneralSecurityException; 104import java.security.KeyStore; 105import java.security.cert.CertPath; 106import java.security.cert.CertPathValidator; 107import java.security.cert.CertPathValidatorException; 108import java.security.cert.CertificateFactory; 109import java.security.cert.PKIXParameters; 110import java.security.cert.X509Certificate; 111import java.util.ArrayList; 112import java.util.Arrays; 113import java.util.List; 114 115/** 116 * WifiService handles remote WiFi operation requests by implementing 117 * the IWifiManager interface. 118 * 119 * @hide 120 */ 121public class WifiServiceImpl extends IWifiManager.Stub { 122 private static final String TAG = "WifiService"; 123 private static final boolean DBG = true; 124 private static final boolean VDBG = false; 125 126 final WifiStateMachine mWifiStateMachine; 127 128 private final Context mContext; 129 private final FrameworkFacade mFacade; 130 131 private final PowerManager mPowerManager; 132 private final AppOpsManager mAppOps; 133 private final UserManager mUserManager; 134 private final WifiCountryCode mCountryCode; 135 // Debug counter tracking scan requests sent by WifiManager 136 private int scanRequestCounter = 0; 137 138 /* Tracks the open wi-fi network notification */ 139 private WifiNotificationController mNotificationController; 140 /* Polls traffic stats and notifies clients */ 141 private WifiTrafficPoller mTrafficPoller; 142 /* Tracks the persisted states for wi-fi & airplane mode */ 143 final WifiSettingsStore mSettingsStore; 144 /* Logs connection events and some general router and scan stats */ 145 private final WifiMetrics mWifiMetrics; 146 /* Manages affiliated certificates for current user */ 147 private final WifiCertManager mCertManager; 148 149 private final WifiInjector mWifiInjector; 150 /* Backup/Restore Module */ 151 private final WifiBackupRestore mWifiBackupRestore; 152 153 private WifiScanner mWifiScanner; 154 155 /** 156 * Asynchronous channel to WifiStateMachine 157 */ 158 private AsyncChannel mWifiStateMachineChannel; 159 160 private final boolean mPermissionReviewRequired; 161 162 /** 163 * Handles client connections 164 */ 165 private class ClientHandler extends Handler { 166 167 ClientHandler(Looper looper) { 168 super(looper); 169 } 170 171 @Override 172 public void handleMessage(Message msg) { 173 switch (msg.what) { 174 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: { 175 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 176 if (DBG) Slog.d(TAG, "New client listening to asynchronous messages"); 177 // We track the clients by the Messenger 178 // since it is expected to be always available 179 mTrafficPoller.addClient(msg.replyTo); 180 } else { 181 Slog.e(TAG, "Client connection failure, error=" + msg.arg1); 182 } 183 break; 184 } 185 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { 186 if (msg.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) { 187 if (DBG) Slog.d(TAG, "Send failed, client connection lost"); 188 } else { 189 if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1); 190 } 191 mTrafficPoller.removeClient(msg.replyTo); 192 break; 193 } 194 case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: { 195 AsyncChannel ac = new AsyncChannel(); 196 ac.connect(mContext, this, msg.replyTo); 197 break; 198 } 199 /* Client commands are forwarded to state machine */ 200 case WifiManager.CONNECT_NETWORK: 201 case WifiManager.SAVE_NETWORK: { 202 WifiConfiguration config = (WifiConfiguration) msg.obj; 203 int networkId = msg.arg1; 204 if (msg.what == WifiManager.SAVE_NETWORK) { 205 Slog.d("WiFiServiceImpl ", "SAVE" 206 + " nid=" + Integer.toString(networkId) 207 + " uid=" + msg.sendingUid 208 + " name=" 209 + mContext.getPackageManager().getNameForUid(msg.sendingUid)); 210 } 211 if (msg.what == WifiManager.CONNECT_NETWORK) { 212 Slog.d("WiFiServiceImpl ", "CONNECT " 213 + " nid=" + Integer.toString(networkId) 214 + " uid=" + msg.sendingUid 215 + " name=" 216 + mContext.getPackageManager().getNameForUid(msg.sendingUid)); 217 } 218 219 if (config != null && isValid(config)) { 220 if (DBG) Slog.d(TAG, "Connect with config" + config); 221 mWifiStateMachine.sendMessage(Message.obtain(msg)); 222 } else if (config == null 223 && networkId != WifiConfiguration.INVALID_NETWORK_ID) { 224 if (DBG) Slog.d(TAG, "Connect with networkId" + networkId); 225 mWifiStateMachine.sendMessage(Message.obtain(msg)); 226 } else { 227 Slog.e(TAG, "ClientHandler.handleMessage ignoring invalid msg=" + msg); 228 if (msg.what == WifiManager.CONNECT_NETWORK) { 229 replyFailed(msg, WifiManager.CONNECT_NETWORK_FAILED, 230 WifiManager.INVALID_ARGS); 231 } else { 232 replyFailed(msg, WifiManager.SAVE_NETWORK_FAILED, 233 WifiManager.INVALID_ARGS); 234 } 235 } 236 break; 237 } 238 case WifiManager.FORGET_NETWORK: 239 mWifiStateMachine.sendMessage(Message.obtain(msg)); 240 break; 241 case WifiManager.START_WPS: 242 case WifiManager.CANCEL_WPS: 243 case WifiManager.DISABLE_NETWORK: 244 case WifiManager.RSSI_PKTCNT_FETCH: { 245 mWifiStateMachine.sendMessage(Message.obtain(msg)); 246 break; 247 } 248 default: { 249 Slog.d(TAG, "ClientHandler.handleMessage ignoring msg=" + msg); 250 break; 251 } 252 } 253 } 254 255 private void replyFailed(Message msg, int what, int why) { 256 Message reply = Message.obtain(); 257 reply.what = what; 258 reply.arg1 = why; 259 try { 260 msg.replyTo.send(reply); 261 } catch (RemoteException e) { 262 // There's not much we can do if reply can't be sent! 263 } 264 } 265 } 266 private ClientHandler mClientHandler; 267 268 /** 269 * Handles interaction with WifiStateMachine 270 */ 271 private class WifiStateMachineHandler extends Handler { 272 private AsyncChannel mWsmChannel; 273 274 WifiStateMachineHandler(Looper looper) { 275 super(looper); 276 mWsmChannel = new AsyncChannel(); 277 mWsmChannel.connect(mContext, this, mWifiStateMachine.getHandler()); 278 } 279 280 @Override 281 public void handleMessage(Message msg) { 282 switch (msg.what) { 283 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: { 284 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 285 mWifiStateMachineChannel = mWsmChannel; 286 } else { 287 Slog.e(TAG, "WifiStateMachine connection failure, error=" + msg.arg1); 288 mWifiStateMachineChannel = null; 289 } 290 break; 291 } 292 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { 293 Slog.e(TAG, "WifiStateMachine channel lost, msg.arg1 =" + msg.arg1); 294 mWifiStateMachineChannel = null; 295 //Re-establish connection to state machine 296 mWsmChannel.connect(mContext, this, mWifiStateMachine.getHandler()); 297 break; 298 } 299 default: { 300 Slog.d(TAG, "WifiStateMachineHandler.handleMessage ignoring msg=" + msg); 301 break; 302 } 303 } 304 } 305 } 306 307 WifiStateMachineHandler mWifiStateMachineHandler; 308 private WifiController mWifiController; 309 private final WifiLockManager mWifiLockManager; 310 private final WifiMulticastLockManager mWifiMulticastLockManager; 311 312 public WifiServiceImpl(Context context) { 313 mContext = context; 314 mWifiInjector = new WifiInjector(context); 315 316 mFacade = mWifiInjector.getFrameworkFacade(); 317 mWifiMetrics = mWifiInjector.getWifiMetrics(); 318 mTrafficPoller = mWifiInjector.getWifiTrafficPoller(); 319 mUserManager = UserManager.get(mContext); 320 mCountryCode = mWifiInjector.getWifiCountryCode(); 321 mWifiStateMachine = mWifiInjector.getWifiStateMachine(); 322 mWifiStateMachine.enableRssiPolling(true); 323 mSettingsStore = mWifiInjector.getWifiSettingsStore(); 324 mPowerManager = mContext.getSystemService(PowerManager.class); 325 mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 326 mCertManager = mWifiInjector.getWifiCertManager(); 327 328 mNotificationController = mWifiInjector.getWifiNotificationController(); 329 330 mWifiLockManager = mWifiInjector.getWifiLockManager(); 331 mWifiMulticastLockManager = mWifiInjector.getWifiMulticastLockManager(); 332 HandlerThread wifiServiceHandlerThread = mWifiInjector.getWifiServiceHandlerThread(); 333 mClientHandler = new ClientHandler(wifiServiceHandlerThread.getLooper()); 334 mWifiStateMachineHandler = 335 new WifiStateMachineHandler(wifiServiceHandlerThread.getLooper()); 336 mWifiController = mWifiInjector.getWifiController(); 337 mWifiBackupRestore = mWifiInjector.getWifiBackupRestore(); 338 339 mPermissionReviewRequired = Build.PERMISSIONS_REVIEW_REQUIRED 340 || context.getResources().getBoolean( 341 com.android.internal.R.bool.config_permissionReviewRequired); 342 343 enableVerboseLoggingInternal(getVerboseLoggingLevel()); 344 } 345 346 347 /** 348 * Check if Wi-Fi needs to be enabled and start 349 * if needed 350 * 351 * This function is used only at boot time 352 */ 353 public void checkAndStartWifi() { 354 /* Check if wi-fi needs to be enabled */ 355 boolean wifiEnabled = mSettingsStore.isWifiToggleEnabled(); 356 Slog.i(TAG, "WifiService starting up with Wi-Fi " + 357 (wifiEnabled ? "enabled" : "disabled")); 358 359 registerForScanModeChange(); 360 mContext.registerReceiver( 361 new BroadcastReceiver() { 362 @Override 363 public void onReceive(Context context, Intent intent) { 364 if (mSettingsStore.handleAirplaneModeToggled()) { 365 mWifiController.sendMessage(CMD_AIRPLANE_TOGGLED); 366 } 367 if (mSettingsStore.isAirplaneModeOn()) { 368 Log.d(TAG, "resetting country code because Airplane mode is ON"); 369 mCountryCode.airplaneModeEnabled(); 370 } 371 } 372 }, 373 new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED)); 374 375 mContext.registerReceiver( 376 new BroadcastReceiver() { 377 @Override 378 public void onReceive(Context context, Intent intent) { 379 String state = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE); 380 if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(state)) { 381 Log.d(TAG, "resetting networks because SIM was removed"); 382 mWifiStateMachine.resetSimAuthNetworks(false); 383 Log.d(TAG, "resetting country code because SIM is removed"); 384 mCountryCode.simCardRemoved(); 385 } else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(state)) { 386 Log.d(TAG, "resetting networks because SIM was loaded"); 387 mWifiStateMachine.resetSimAuthNetworks(true); 388 } 389 } 390 }, 391 new IntentFilter(TelephonyIntents.ACTION_SIM_STATE_CHANGED)); 392 393 // Adding optimizations of only receiving broadcasts when wifi is enabled 394 // can result in race conditions when apps toggle wifi in the background 395 // without active user involvement. Always receive broadcasts. 396 registerForBroadcasts(); 397 registerForPackageOrUserRemoval(); 398 mInIdleMode = mPowerManager.isDeviceIdleMode(); 399 400 mWifiController.start(); 401 402 // If we are already disabled (could be due to airplane mode), avoid changing persist 403 // state here 404 if (wifiEnabled) { 405 try { 406 setWifiEnabled(mContext.getPackageName(), wifiEnabled); 407 } catch (RemoteException e) { 408 /* ignore - local call */ 409 } 410 } 411 } 412 413 public void handleUserSwitch(int userId) { 414 mWifiStateMachine.handleUserSwitch(userId); 415 } 416 417 public void handleUserUnlock(int userId) { 418 mWifiStateMachine.handleUserUnlock(userId); 419 } 420 421 public void handleUserStop(int userId) { 422 mWifiStateMachine.handleUserStop(userId); 423 } 424 425 /** 426 * see {@link android.net.wifi.WifiManager#pingSupplicant()} 427 * @return {@code true} if the operation succeeds, {@code false} otherwise 428 */ 429 @Override 430 public boolean pingSupplicant() { 431 enforceAccessPermission(); 432 if (mWifiStateMachineChannel != null) { 433 return mWifiStateMachine.syncPingSupplicant(mWifiStateMachineChannel); 434 } else { 435 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 436 return false; 437 } 438 } 439 440 /** 441 * see {@link android.net.wifi.WifiManager#startScan} 442 * and {@link android.net.wifi.WifiManager#startCustomizedScan} 443 * 444 * @param settings If null, use default parameter, i.e. full scan. 445 * @param workSource If null, all blame is given to the calling uid. 446 */ 447 @Override 448 public void startScan(ScanSettings settings, WorkSource workSource) { 449 enforceChangePermission(); 450 synchronized (this) { 451 if (mWifiScanner == null) { 452 mWifiScanner = mWifiInjector.getWifiScanner(); 453 } 454 if (mInIdleMode) { 455 // Need to send an immediate scan result broadcast in case the 456 // caller is waiting for a result .. 457 458 // clear calling identity to send broadcast 459 long callingIdentity = Binder.clearCallingIdentity(); 460 try { 461 // TODO: investigate if the logic to cancel scans when idle can move to 462 // WifiScanningServiceImpl. This will 1 - clean up WifiServiceImpl and 2 - 463 // avoid plumbing an awkward path to report a cancelled/failed scan. This will 464 // be sent directly until b/31398592 is fixed. 465 Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); 466 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 467 intent.putExtra(WifiManager.EXTRA_RESULTS_UPDATED, false); 468 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 469 } finally { 470 // restore calling identity 471 Binder.restoreCallingIdentity(callingIdentity); 472 } 473 mScanPending = true; 474 return; 475 } 476 } 477 if (settings != null) { 478 settings = new ScanSettings(settings); 479 if (!settings.isValid()) { 480 Slog.e(TAG, "invalid scan setting"); 481 return; 482 } 483 } 484 if (workSource != null) { 485 enforceWorkSourcePermission(); 486 // WifiManager currently doesn't use names, so need to clear names out of the 487 // supplied WorkSource to allow future WorkSource combining. 488 workSource.clearNames(); 489 } 490 if (workSource == null && Binder.getCallingUid() >= 0) { 491 workSource = new WorkSource(Binder.getCallingUid()); 492 } 493 mWifiStateMachine.startScan(Binder.getCallingUid(), scanRequestCounter++, 494 settings, workSource); 495 } 496 497 @Override 498 public String getWpsNfcConfigurationToken(int netId) { 499 enforceConnectivityInternalPermission(); 500 return mWifiStateMachine.syncGetWpsNfcConfigurationToken(netId); 501 } 502 503 boolean mInIdleMode; 504 boolean mScanPending; 505 506 void handleIdleModeChanged() { 507 boolean doScan = false; 508 synchronized (this) { 509 boolean idle = mPowerManager.isDeviceIdleMode(); 510 if (mInIdleMode != idle) { 511 mInIdleMode = idle; 512 if (!idle) { 513 if (mScanPending) { 514 mScanPending = false; 515 doScan = true; 516 } 517 } 518 } 519 } 520 if (doScan) { 521 // Someone requested a scan while we were idle; do a full scan now. 522 startScan(null, null); 523 } 524 } 525 526 private void enforceAccessPermission() { 527 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE, 528 "WifiService"); 529 } 530 531 private void enforceChangePermission() { 532 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE, 533 "WifiService"); 534 } 535 536 private void enforceLocationHardwarePermission() { 537 mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, 538 "LocationHardware"); 539 } 540 541 private void enforceReadCredentialPermission() { 542 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.READ_WIFI_CREDENTIAL, 543 "WifiService"); 544 } 545 546 private void enforceWorkSourcePermission() { 547 mContext.enforceCallingPermission(android.Manifest.permission.UPDATE_DEVICE_STATS, 548 "WifiService"); 549 550 } 551 552 private void enforceMulticastChangePermission() { 553 mContext.enforceCallingOrSelfPermission( 554 android.Manifest.permission.CHANGE_WIFI_MULTICAST_STATE, 555 "WifiService"); 556 } 557 558 private void enforceConnectivityInternalPermission() { 559 mContext.enforceCallingOrSelfPermission( 560 android.Manifest.permission.CONNECTIVITY_INTERNAL, 561 "ConnectivityService"); 562 } 563 564 /** 565 * see {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)} 566 * @param enable {@code true} to enable, {@code false} to disable. 567 * @return {@code true} if the enable/disable operation was 568 * started or is already in the queue. 569 */ 570 @Override 571 public synchronized boolean setWifiEnabled(String packageName, boolean enable) 572 throws RemoteException { 573 enforceChangePermission(); 574 Slog.d(TAG, "setWifiEnabled: " + enable + " pid=" + Binder.getCallingPid() 575 + ", uid=" + Binder.getCallingUid()); 576 577 /* 578 * Caller might not have WRITE_SECURE_SETTINGS, 579 * only CHANGE_WIFI_STATE is enforced 580 */ 581 long ident = Binder.clearCallingIdentity(); 582 try { 583 if (! mSettingsStore.handleWifiToggled(enable)) { 584 // Nothing to do if wifi cannot be toggled 585 return true; 586 } 587 } finally { 588 Binder.restoreCallingIdentity(ident); 589 } 590 591 592 if (mPermissionReviewRequired) { 593 final int wiFiEnabledState = getWifiEnabledState(); 594 if (enable) { 595 if (wiFiEnabledState == WifiManager.WIFI_STATE_DISABLING 596 || wiFiEnabledState == WifiManager.WIFI_STATE_DISABLED) { 597 if (startConsentUiIfNeeded(packageName, Binder.getCallingUid(), 598 WifiManager.ACTION_REQUEST_ENABLE)) { 599 return true; 600 } 601 } 602 } else if (wiFiEnabledState == WifiManager.WIFI_STATE_ENABLING 603 || wiFiEnabledState == WifiManager.WIFI_STATE_ENABLED) { 604 if (startConsentUiIfNeeded(packageName, Binder.getCallingUid(), 605 WifiManager.ACTION_REQUEST_DISABLE)) { 606 return true; 607 } 608 } 609 } 610 611 mWifiController.sendMessage(CMD_WIFI_TOGGLED); 612 return true; 613 } 614 615 /** 616 * see {@link WifiManager#getWifiState()} 617 * @return One of {@link WifiManager#WIFI_STATE_DISABLED}, 618 * {@link WifiManager#WIFI_STATE_DISABLING}, 619 * {@link WifiManager#WIFI_STATE_ENABLED}, 620 * {@link WifiManager#WIFI_STATE_ENABLING}, 621 * {@link WifiManager#WIFI_STATE_UNKNOWN} 622 */ 623 @Override 624 public int getWifiEnabledState() { 625 enforceAccessPermission(); 626 return mWifiStateMachine.syncGetWifiState(); 627 } 628 629 /** 630 * see {@link android.net.wifi.WifiManager#setWifiApEnabled(WifiConfiguration, boolean)} 631 * @param wifiConfig SSID, security and channel details as 632 * part of WifiConfiguration 633 * @param enabled true to enable and false to disable 634 */ 635 @Override 636 public void setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) { 637 enforceChangePermission(); 638 ConnectivityManager.enforceTetherChangePermission(mContext); 639 if (mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING)) { 640 throw new SecurityException("DISALLOW_CONFIG_TETHERING is enabled for this user."); 641 } 642 // null wifiConfig is a meaningful input for CMD_SET_AP 643 if (wifiConfig == null || isValid(wifiConfig)) { 644 mWifiController.obtainMessage(CMD_SET_AP, enabled ? 1 : 0, 0, wifiConfig).sendToTarget(); 645 } else { 646 Slog.e(TAG, "Invalid WifiConfiguration"); 647 } 648 } 649 650 /** 651 * see {@link WifiManager#getWifiApState()} 652 * @return One of {@link WifiManager#WIFI_AP_STATE_DISABLED}, 653 * {@link WifiManager#WIFI_AP_STATE_DISABLING}, 654 * {@link WifiManager#WIFI_AP_STATE_ENABLED}, 655 * {@link WifiManager#WIFI_AP_STATE_ENABLING}, 656 * {@link WifiManager#WIFI_AP_STATE_FAILED} 657 */ 658 @Override 659 public int getWifiApEnabledState() { 660 enforceAccessPermission(); 661 return mWifiStateMachine.syncGetWifiApState(); 662 } 663 664 /** 665 * see {@link WifiManager#getWifiApConfiguration()} 666 * @return soft access point configuration 667 */ 668 @Override 669 public WifiConfiguration getWifiApConfiguration() { 670 enforceAccessPermission(); 671 return mWifiStateMachine.syncGetWifiApConfiguration(); 672 } 673 674 /** 675 * see {@link WifiManager#buildWifiConfig()} 676 * @return a WifiConfiguration. 677 */ 678 @Override 679 public WifiConfiguration buildWifiConfig(String uriString, String mimeType, byte[] data) { 680 if (mimeType.equals(ConfigBuilder.WifiConfigType)) { 681 try { 682 return ConfigBuilder.buildConfig(uriString, data, mContext); 683 } 684 catch (IOException | GeneralSecurityException | SAXException e) { 685 Log.e(TAG, "Failed to parse wi-fi configuration: " + e); 686 } 687 } 688 else { 689 Log.i(TAG, "Unknown wi-fi config type: " + mimeType); 690 } 691 return null; 692 } 693 694 /** 695 * see {@link WifiManager#setWifiApConfiguration(WifiConfiguration)} 696 * @param wifiConfig WifiConfiguration details for soft access point 697 */ 698 @Override 699 public void setWifiApConfiguration(WifiConfiguration wifiConfig) { 700 enforceChangePermission(); 701 if (wifiConfig == null) 702 return; 703 if (isValid(wifiConfig)) { 704 mWifiStateMachine.setWifiApConfiguration(wifiConfig); 705 } else { 706 Slog.e(TAG, "Invalid WifiConfiguration"); 707 } 708 } 709 710 /** 711 * see {@link android.net.wifi.WifiManager#isScanAlwaysAvailable()} 712 */ 713 @Override 714 public boolean isScanAlwaysAvailable() { 715 enforceAccessPermission(); 716 return mSettingsStore.isScanAlwaysAvailable(); 717 } 718 719 /** 720 * see {@link android.net.wifi.WifiManager#disconnect()} 721 */ 722 @Override 723 public void disconnect() { 724 enforceChangePermission(); 725 mWifiStateMachine.disconnectCommand(); 726 } 727 728 /** 729 * see {@link android.net.wifi.WifiManager#reconnect()} 730 */ 731 @Override 732 public void reconnect() { 733 enforceChangePermission(); 734 mWifiStateMachine.reconnectCommand(); 735 } 736 737 /** 738 * see {@link android.net.wifi.WifiManager#reassociate()} 739 */ 740 @Override 741 public void reassociate() { 742 enforceChangePermission(); 743 mWifiStateMachine.reassociateCommand(); 744 } 745 746 /** 747 * see {@link android.net.wifi.WifiManager#getSupportedFeatures} 748 */ 749 @Override 750 public int getSupportedFeatures() { 751 enforceAccessPermission(); 752 if (mWifiStateMachineChannel != null) { 753 return mWifiStateMachine.syncGetSupportedFeatures(mWifiStateMachineChannel); 754 } else { 755 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 756 return 0; 757 } 758 } 759 760 @Override 761 public void requestActivityInfo(ResultReceiver result) { 762 Bundle bundle = new Bundle(); 763 bundle.putParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY, reportActivityInfo()); 764 result.send(0, bundle); 765 } 766 767 /** 768 * see {@link android.net.wifi.WifiManager#getControllerActivityEnergyInfo(int)} 769 */ 770 @Override 771 public WifiActivityEnergyInfo reportActivityInfo() { 772 enforceAccessPermission(); 773 if ((getSupportedFeatures() & WifiManager.WIFI_FEATURE_LINK_LAYER_STATS) == 0) { 774 return null; 775 } 776 WifiLinkLayerStats stats; 777 WifiActivityEnergyInfo energyInfo = null; 778 if (mWifiStateMachineChannel != null) { 779 stats = mWifiStateMachine.syncGetLinkLayerStats(mWifiStateMachineChannel); 780 if (stats != null) { 781 final long rxIdleCurrent = mContext.getResources().getInteger( 782 com.android.internal.R.integer.config_wifi_idle_receive_cur_ma); 783 final long rxCurrent = mContext.getResources().getInteger( 784 com.android.internal.R.integer.config_wifi_active_rx_cur_ma); 785 final long txCurrent = mContext.getResources().getInteger( 786 com.android.internal.R.integer.config_wifi_tx_cur_ma); 787 final double voltage = mContext.getResources().getInteger( 788 com.android.internal.R.integer.config_wifi_operating_voltage_mv) 789 / 1000.0; 790 791 final long rxIdleTime = stats.on_time - stats.tx_time - stats.rx_time; 792 final long[] txTimePerLevel; 793 if (stats.tx_time_per_level != null) { 794 txTimePerLevel = new long[stats.tx_time_per_level.length]; 795 for (int i = 0; i < txTimePerLevel.length; i++) { 796 txTimePerLevel[i] = stats.tx_time_per_level[i]; 797 // TODO(b/27227497): Need to read the power consumed per level from config 798 } 799 } else { 800 // This will happen if the HAL get link layer API returned null. 801 txTimePerLevel = new long[0]; 802 } 803 final long energyUsed = (long)((stats.tx_time * txCurrent + 804 stats.rx_time * rxCurrent + 805 rxIdleTime * rxIdleCurrent) * voltage); 806 if (VDBG || rxIdleTime < 0 || stats.on_time < 0 || stats.tx_time < 0 || 807 stats.rx_time < 0 || energyUsed < 0) { 808 StringBuilder sb = new StringBuilder(); 809 sb.append(" rxIdleCur=" + rxIdleCurrent); 810 sb.append(" rxCur=" + rxCurrent); 811 sb.append(" txCur=" + txCurrent); 812 sb.append(" voltage=" + voltage); 813 sb.append(" on_time=" + stats.on_time); 814 sb.append(" tx_time=" + stats.tx_time); 815 sb.append(" tx_time_per_level=" + Arrays.toString(txTimePerLevel)); 816 sb.append(" rx_time=" + stats.rx_time); 817 sb.append(" rxIdleTime=" + rxIdleTime); 818 sb.append(" energy=" + energyUsed); 819 Log.d(TAG, " reportActivityInfo: " + sb.toString()); 820 } 821 822 // Convert the LinkLayerStats into EnergyActivity 823 energyInfo = new WifiActivityEnergyInfo(SystemClock.elapsedRealtime(), 824 WifiActivityEnergyInfo.STACK_STATE_STATE_IDLE, stats.tx_time, 825 txTimePerLevel, stats.rx_time, rxIdleTime, energyUsed); 826 } 827 if (energyInfo != null && energyInfo.isValid()) { 828 return energyInfo; 829 } else { 830 return null; 831 } 832 } else { 833 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 834 return null; 835 } 836 } 837 838 /** 839 * see {@link android.net.wifi.WifiManager#getConfiguredNetworks()} 840 * @return the list of configured networks 841 */ 842 @Override 843 public List<WifiConfiguration> getConfiguredNetworks() { 844 enforceAccessPermission(); 845 if (mWifiStateMachineChannel != null) { 846 return mWifiStateMachine.syncGetConfiguredNetworks(Binder.getCallingUid(), 847 mWifiStateMachineChannel); 848 } else { 849 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 850 return null; 851 } 852 } 853 854 /** 855 * see {@link android.net.wifi.WifiManager#getPrivilegedConfiguredNetworks()} 856 * @return the list of configured networks with real preSharedKey 857 */ 858 @Override 859 public List<WifiConfiguration> getPrivilegedConfiguredNetworks() { 860 enforceReadCredentialPermission(); 861 enforceAccessPermission(); 862 if (mWifiStateMachineChannel != null) { 863 return mWifiStateMachine.syncGetPrivilegedConfiguredNetwork(mWifiStateMachineChannel); 864 } else { 865 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 866 return null; 867 } 868 } 869 870 /** 871 * Returns a WifiConfiguration matching this ScanResult 872 * @param scanResult scanResult that represents the BSSID 873 * @return {@link WifiConfiguration} that matches this BSSID or null 874 */ 875 @Override 876 public WifiConfiguration getMatchingWifiConfig(ScanResult scanResult) { 877 enforceAccessPermission(); 878 return mWifiStateMachine.syncGetMatchingWifiConfig(scanResult, mWifiStateMachineChannel); 879 } 880 881 /** 882 * see {@link android.net.wifi.WifiManager#addOrUpdateNetwork(WifiConfiguration)} 883 * @return the supplicant-assigned identifier for the new or updated 884 * network if the operation succeeds, or {@code -1} if it fails 885 */ 886 @Override 887 public int addOrUpdateNetwork(WifiConfiguration config) { 888 enforceChangePermission(); 889 if (isValid(config) && isValidPasspoint(config)) { 890 891 WifiEnterpriseConfig enterpriseConfig = config.enterpriseConfig; 892 893 if (config.isPasspoint() && 894 (enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TLS || 895 enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TTLS)) { 896 if (config.updateIdentifier != null) { 897 enforceAccessPermission(); 898 } 899 else { 900 try { 901 verifyCert(enterpriseConfig.getCaCertificate()); 902 } catch (CertPathValidatorException cpve) { 903 Slog.e(TAG, "CA Cert " + 904 enterpriseConfig.getCaCertificate().getSubjectX500Principal() + 905 " untrusted: " + cpve.getMessage()); 906 return -1; 907 } catch (GeneralSecurityException | IOException e) { 908 Slog.e(TAG, "Failed to verify certificate" + 909 enterpriseConfig.getCaCertificate().getSubjectX500Principal() + 910 ": " + e); 911 return -1; 912 } 913 } 914 } 915 916 //TODO: pass the Uid the WifiStateMachine as a message parameter 917 Slog.i("addOrUpdateNetwork", " uid = " + Integer.toString(Binder.getCallingUid()) 918 + " SSID " + config.SSID 919 + " nid=" + Integer.toString(config.networkId)); 920 if (config.networkId == WifiConfiguration.INVALID_NETWORK_ID) { 921 config.creatorUid = Binder.getCallingUid(); 922 } else { 923 config.lastUpdateUid = Binder.getCallingUid(); 924 } 925 if (mWifiStateMachineChannel != null) { 926 return mWifiStateMachine.syncAddOrUpdateNetwork(mWifiStateMachineChannel, config); 927 } else { 928 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 929 return -1; 930 } 931 } else { 932 Slog.e(TAG, "bad network configuration"); 933 return -1; 934 } 935 } 936 937 public static void verifyCert(X509Certificate caCert) 938 throws GeneralSecurityException, IOException { 939 CertificateFactory factory = CertificateFactory.getInstance("X.509"); 940 CertPathValidator validator = 941 CertPathValidator.getInstance(CertPathValidator.getDefaultType()); 942 CertPath path = factory.generateCertPath( 943 Arrays.asList(caCert)); 944 KeyStore ks = KeyStore.getInstance("AndroidCAStore"); 945 ks.load(null, null); 946 PKIXParameters params = new PKIXParameters(ks); 947 params.setRevocationEnabled(false); 948 validator.validate(path, params); 949 } 950 951 /** 952 * See {@link android.net.wifi.WifiManager#removeNetwork(int)} 953 * @param netId the integer that identifies the network configuration 954 * to the supplicant 955 * @return {@code true} if the operation succeeded 956 */ 957 @Override 958 public boolean removeNetwork(int netId) { 959 enforceChangePermission(); 960 961 if (mWifiStateMachineChannel != null) { 962 return mWifiStateMachine.syncRemoveNetwork(mWifiStateMachineChannel, netId); 963 } else { 964 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 965 return false; 966 } 967 } 968 969 /** 970 * See {@link android.net.wifi.WifiManager#enableNetwork(int, boolean)} 971 * @param netId the integer that identifies the network configuration 972 * to the supplicant 973 * @param disableOthers if true, disable all other networks. 974 * @return {@code true} if the operation succeeded 975 */ 976 @Override 977 public boolean enableNetwork(int netId, boolean disableOthers) { 978 enforceChangePermission(); 979 if (mWifiStateMachineChannel != null) { 980 return mWifiStateMachine.syncEnableNetwork(mWifiStateMachineChannel, netId, 981 disableOthers); 982 } else { 983 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 984 return false; 985 } 986 } 987 988 /** 989 * See {@link android.net.wifi.WifiManager#disableNetwork(int)} 990 * @param netId the integer that identifies the network configuration 991 * to the supplicant 992 * @return {@code true} if the operation succeeded 993 */ 994 @Override 995 public boolean disableNetwork(int netId) { 996 enforceChangePermission(); 997 if (mWifiStateMachineChannel != null) { 998 return mWifiStateMachine.syncDisableNetwork(mWifiStateMachineChannel, netId); 999 } else { 1000 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1001 return false; 1002 } 1003 } 1004 1005 /** 1006 * See {@link android.net.wifi.WifiManager#getConnectionInfo()} 1007 * @return the Wi-Fi information, contained in {@link WifiInfo}. 1008 */ 1009 @Override 1010 public WifiInfo getConnectionInfo() { 1011 enforceAccessPermission(); 1012 /* 1013 * Make sure we have the latest information, by sending 1014 * a status request to the supplicant. 1015 */ 1016 return mWifiStateMachine.syncRequestConnectionInfo(); 1017 } 1018 1019 /** 1020 * Return the results of the most recent access point scan, in the form of 1021 * a list of {@link ScanResult} objects. 1022 * @return the list of results 1023 */ 1024 @Override 1025 public List<ScanResult> getScanResults(String callingPackage) { 1026 enforceAccessPermission(); 1027 int userId = UserHandle.getCallingUserId(); 1028 int uid = Binder.getCallingUid(); 1029 boolean canReadPeerMacAddresses = checkPeersMacAddress(); 1030 boolean isActiveNetworkScorer = 1031 NetworkScorerAppManager.isCallerActiveScorer(mContext, uid); 1032 boolean hasInteractUsersFull = checkInteractAcrossUsersFull(); 1033 long ident = Binder.clearCallingIdentity(); 1034 try { 1035 if (!canReadPeerMacAddresses && !isActiveNetworkScorer 1036 && !isLocationEnabled(callingPackage)) { 1037 return new ArrayList<ScanResult>(); 1038 } 1039 if (!canReadPeerMacAddresses && !isActiveNetworkScorer 1040 && !checkCallerCanAccessScanResults(callingPackage, uid)) { 1041 return new ArrayList<ScanResult>(); 1042 } 1043 if (mAppOps.noteOp(AppOpsManager.OP_WIFI_SCAN, uid, callingPackage) 1044 != AppOpsManager.MODE_ALLOWED) { 1045 return new ArrayList<ScanResult>(); 1046 } 1047 if (!isCurrentProfile(userId) && !hasInteractUsersFull) { 1048 return new ArrayList<ScanResult>(); 1049 } 1050 if (mWifiScanner == null) { 1051 mWifiScanner = mWifiInjector.getWifiScanner(); 1052 } 1053 return mWifiScanner.getSingleScanResults(); 1054 } finally { 1055 Binder.restoreCallingIdentity(ident); 1056 } 1057 } 1058 1059 /** 1060 * Add a Hotspot 2.0 release 2 Management Object 1061 * @param mo The MO in XML form 1062 * @return -1 for failure 1063 */ 1064 @Override 1065 public int addPasspointManagementObject(String mo) { 1066 return mWifiStateMachine.syncAddPasspointManagementObject(mWifiStateMachineChannel, mo); 1067 } 1068 1069 /** 1070 * Modify a Hotspot 2.0 release 2 Management Object 1071 * @param fqdn The FQDN of the service provider 1072 * @param mos A List of MO definitions to be updated 1073 * @return the number of nodes updated, or -1 for failure 1074 */ 1075 @Override 1076 public int modifyPasspointManagementObject(String fqdn, List<PasspointManagementObjectDefinition> mos) { 1077 return mWifiStateMachine.syncModifyPasspointManagementObject(mWifiStateMachineChannel, fqdn, mos); 1078 } 1079 1080 /** 1081 * Query for a Hotspot 2.0 release 2 OSU icon 1082 * @param bssid The BSSID of the AP 1083 * @param fileName Icon file name 1084 */ 1085 @Override 1086 public void queryPasspointIcon(long bssid, String fileName) { 1087 mWifiStateMachine.syncQueryPasspointIcon(mWifiStateMachineChannel, bssid, fileName); 1088 } 1089 1090 /** 1091 * Match the currently associated network against the SP matching the given FQDN 1092 * @param fqdn FQDN of the SP 1093 * @return ordinal [HomeProvider, RoamingProvider, Incomplete, None, Declined] 1094 */ 1095 @Override 1096 public int matchProviderWithCurrentNetwork(String fqdn) { 1097 return mWifiStateMachine.matchProviderWithCurrentNetwork(mWifiStateMachineChannel, fqdn); 1098 } 1099 1100 /** 1101 * Deauthenticate and set the re-authentication hold off time for the current network 1102 * @param holdoff hold off time in milliseconds 1103 * @param ess set if the hold off pertains to an ESS rather than a BSS 1104 */ 1105 @Override 1106 public void deauthenticateNetwork(long holdoff, boolean ess) { 1107 mWifiStateMachine.deauthenticateNetwork(mWifiStateMachineChannel, holdoff, ess); 1108 } 1109 1110 private boolean isLocationEnabled(String callingPackage) { 1111 boolean legacyForegroundApp = !isMApp(mContext, callingPackage) 1112 && isForegroundApp(callingPackage); 1113 return legacyForegroundApp || Settings.Secure.getInt(mContext.getContentResolver(), 1114 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF) 1115 != Settings.Secure.LOCATION_MODE_OFF; 1116 } 1117 1118 /** 1119 * Returns true if the caller holds INTERACT_ACROSS_USERS_FULL. 1120 */ 1121 private boolean checkInteractAcrossUsersFull() { 1122 return mContext.checkCallingOrSelfPermission( 1123 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) 1124 == PackageManager.PERMISSION_GRANTED; 1125 } 1126 1127 /** 1128 * Returns true if the caller holds PEERS_MAC_ADDRESS. 1129 */ 1130 private boolean checkPeersMacAddress() { 1131 return mContext.checkCallingOrSelfPermission( 1132 android.Manifest.permission.PEERS_MAC_ADDRESS) == PackageManager.PERMISSION_GRANTED; 1133 } 1134 1135 /** 1136 * Returns true if the calling user is the current one or a profile of the 1137 * current user.. 1138 */ 1139 private boolean isCurrentProfile(int userId) { 1140 int currentUser = ActivityManager.getCurrentUser(); 1141 if (userId == currentUser) { 1142 return true; 1143 } 1144 List<UserInfo> profiles = mUserManager.getProfiles(currentUser); 1145 for (UserInfo user : profiles) { 1146 if (userId == user.id) { 1147 return true; 1148 } 1149 } 1150 return false; 1151 } 1152 1153 /** 1154 * Tell the supplicant to persist the current list of configured networks. 1155 * @return {@code true} if the operation succeeded 1156 * 1157 * TODO: deprecate this 1158 */ 1159 @Override 1160 public boolean saveConfiguration() { 1161 enforceChangePermission(); 1162 if (mWifiStateMachineChannel != null) { 1163 return mWifiStateMachine.syncSaveConfig(mWifiStateMachineChannel); 1164 } else { 1165 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1166 return false; 1167 } 1168 } 1169 1170 /** 1171 * Set the country code 1172 * @param countryCode ISO 3166 country code. 1173 * @param persist {@code true} if the setting should be remembered. 1174 * 1175 * The persist behavior exists so that wifi can fall back to the last 1176 * persisted country code on a restart, when the locale information is 1177 * not available from telephony. 1178 */ 1179 @Override 1180 public void setCountryCode(String countryCode, boolean persist) { 1181 Slog.i(TAG, "WifiService trying to set country code to " + countryCode + 1182 " with persist set to " + persist); 1183 enforceConnectivityInternalPermission(); 1184 final long token = Binder.clearCallingIdentity(); 1185 try { 1186 if (mCountryCode.setCountryCode(countryCode, persist) && persist) { 1187 // Save this country code to persistent storage 1188 mFacade.setStringSetting(mContext, 1189 Settings.Global.WIFI_COUNTRY_CODE, 1190 countryCode); 1191 } 1192 } finally { 1193 Binder.restoreCallingIdentity(token); 1194 } 1195 } 1196 1197 /** 1198 * Get the country code 1199 * @return Get the best choice country code for wifi, regardless of if it was set or 1200 * not. 1201 * Returns null when there is no country code available. 1202 */ 1203 @Override 1204 public String getCountryCode() { 1205 enforceConnectivityInternalPermission(); 1206 String country = mCountryCode.getCountryCode(); 1207 return country; 1208 } 1209 1210 @Override 1211 public boolean isDualBandSupported() { 1212 //TODO: Should move towards adding a driver API that checks at runtime 1213 return mContext.getResources().getBoolean( 1214 com.android.internal.R.bool.config_wifi_dual_band_support); 1215 } 1216 1217 /** 1218 * Return the DHCP-assigned addresses from the last successful DHCP request, 1219 * if any. 1220 * @return the DHCP information 1221 * @deprecated 1222 */ 1223 @Override 1224 @Deprecated 1225 public DhcpInfo getDhcpInfo() { 1226 enforceAccessPermission(); 1227 DhcpResults dhcpResults = mWifiStateMachine.syncGetDhcpResults(); 1228 1229 DhcpInfo info = new DhcpInfo(); 1230 1231 if (dhcpResults.ipAddress != null && 1232 dhcpResults.ipAddress.getAddress() instanceof Inet4Address) { 1233 info.ipAddress = NetworkUtils.inetAddressToInt((Inet4Address) dhcpResults.ipAddress.getAddress()); 1234 } 1235 1236 if (dhcpResults.gateway != null) { 1237 info.gateway = NetworkUtils.inetAddressToInt((Inet4Address) dhcpResults.gateway); 1238 } 1239 1240 int dnsFound = 0; 1241 for (InetAddress dns : dhcpResults.dnsServers) { 1242 if (dns instanceof Inet4Address) { 1243 if (dnsFound == 0) { 1244 info.dns1 = NetworkUtils.inetAddressToInt((Inet4Address)dns); 1245 } else { 1246 info.dns2 = NetworkUtils.inetAddressToInt((Inet4Address)dns); 1247 } 1248 if (++dnsFound > 1) break; 1249 } 1250 } 1251 Inet4Address serverAddress = dhcpResults.serverAddress; 1252 if (serverAddress != null) { 1253 info.serverAddress = NetworkUtils.inetAddressToInt(serverAddress); 1254 } 1255 info.leaseDuration = dhcpResults.leaseDuration; 1256 1257 return info; 1258 } 1259 1260 /** 1261 * enable TDLS for the local NIC to remote NIC 1262 * The APPs don't know the remote MAC address to identify NIC though, 1263 * so we need to do additional work to find it from remote IP address 1264 */ 1265 1266 class TdlsTaskParams { 1267 public String remoteIpAddress; 1268 public boolean enable; 1269 } 1270 1271 class TdlsTask extends AsyncTask<TdlsTaskParams, Integer, Integer> { 1272 @Override 1273 protected Integer doInBackground(TdlsTaskParams... params) { 1274 1275 // Retrieve parameters for the call 1276 TdlsTaskParams param = params[0]; 1277 String remoteIpAddress = param.remoteIpAddress.trim(); 1278 boolean enable = param.enable; 1279 1280 // Get MAC address of Remote IP 1281 String macAddress = null; 1282 1283 BufferedReader reader = null; 1284 1285 try { 1286 reader = new BufferedReader(new FileReader("/proc/net/arp")); 1287 1288 // Skip over the line bearing colum titles 1289 String line = reader.readLine(); 1290 1291 while ((line = reader.readLine()) != null) { 1292 String[] tokens = line.split("[ ]+"); 1293 if (tokens.length < 6) { 1294 continue; 1295 } 1296 1297 // ARP column format is 1298 // Address HWType HWAddress Flags Mask IFace 1299 String ip = tokens[0]; 1300 String mac = tokens[3]; 1301 1302 if (remoteIpAddress.equals(ip)) { 1303 macAddress = mac; 1304 break; 1305 } 1306 } 1307 1308 if (macAddress == null) { 1309 Slog.w(TAG, "Did not find remoteAddress {" + remoteIpAddress + "} in " + 1310 "/proc/net/arp"); 1311 } else { 1312 enableTdlsWithMacAddress(macAddress, enable); 1313 } 1314 1315 } catch (FileNotFoundException e) { 1316 Slog.e(TAG, "Could not open /proc/net/arp to lookup mac address"); 1317 } catch (IOException e) { 1318 Slog.e(TAG, "Could not read /proc/net/arp to lookup mac address"); 1319 } finally { 1320 try { 1321 if (reader != null) { 1322 reader.close(); 1323 } 1324 } 1325 catch (IOException e) { 1326 // Do nothing 1327 } 1328 } 1329 1330 return 0; 1331 } 1332 } 1333 1334 @Override 1335 public void enableTdls(String remoteAddress, boolean enable) { 1336 if (remoteAddress == null) { 1337 throw new IllegalArgumentException("remoteAddress cannot be null"); 1338 } 1339 1340 TdlsTaskParams params = new TdlsTaskParams(); 1341 params.remoteIpAddress = remoteAddress; 1342 params.enable = enable; 1343 new TdlsTask().execute(params); 1344 } 1345 1346 1347 @Override 1348 public void enableTdlsWithMacAddress(String remoteMacAddress, boolean enable) { 1349 if (remoteMacAddress == null) { 1350 throw new IllegalArgumentException("remoteMacAddress cannot be null"); 1351 } 1352 1353 mWifiStateMachine.enableTdls(remoteMacAddress, enable); 1354 } 1355 1356 /** 1357 * Get a reference to handler. This is used by a client to establish 1358 * an AsyncChannel communication with WifiService 1359 */ 1360 @Override 1361 public Messenger getWifiServiceMessenger() { 1362 enforceAccessPermission(); 1363 enforceChangePermission(); 1364 return new Messenger(mClientHandler); 1365 } 1366 1367 /** 1368 * Disable an ephemeral network, i.e. network that is created thru a WiFi Scorer 1369 */ 1370 @Override 1371 public void disableEphemeralNetwork(String SSID) { 1372 enforceAccessPermission(); 1373 enforceChangePermission(); 1374 mWifiStateMachine.disableEphemeralNetwork(SSID); 1375 } 1376 1377 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 1378 @Override 1379 public void onReceive(Context context, Intent intent) { 1380 String action = intent.getAction(); 1381 if (action.equals(Intent.ACTION_SCREEN_ON)) { 1382 mWifiController.sendMessage(CMD_SCREEN_ON); 1383 } else if (action.equals(Intent.ACTION_USER_PRESENT)) { 1384 mWifiController.sendMessage(CMD_USER_PRESENT); 1385 } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { 1386 mWifiController.sendMessage(CMD_SCREEN_OFF); 1387 } else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { 1388 int pluggedType = intent.getIntExtra("plugged", 0); 1389 mWifiController.sendMessage(CMD_BATTERY_CHANGED, pluggedType, 0, null); 1390 } else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) { 1391 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, 1392 BluetoothAdapter.STATE_DISCONNECTED); 1393 mWifiStateMachine.sendBluetoothAdapterStateChange(state); 1394 } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) { 1395 boolean emergencyMode = intent.getBooleanExtra("phoneinECMState", false); 1396 mWifiController.sendMessage(CMD_EMERGENCY_MODE_CHANGED, emergencyMode ? 1 : 0, 0); 1397 } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED)) { 1398 boolean inCall = intent.getBooleanExtra(PhoneConstants.PHONE_IN_EMERGENCY_CALL, false); 1399 mWifiController.sendMessage(CMD_EMERGENCY_CALL_STATE_CHANGED, inCall ? 1 : 0, 0); 1400 } else if (action.equals(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED)) { 1401 handleIdleModeChanged(); 1402 } 1403 } 1404 }; 1405 1406 private boolean startConsentUiIfNeeded(String packageName, 1407 int callingUid, String intentAction) throws RemoteException { 1408 if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) { 1409 return false; 1410 } 1411 try { 1412 // Validate the package only if we are going to use it 1413 ApplicationInfo applicationInfo = mContext.getPackageManager() 1414 .getApplicationInfoAsUser(packageName, 1415 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, 1416 UserHandle.getUserId(callingUid)); 1417 if (applicationInfo.uid != callingUid) { 1418 throw new SecurityException("Package " + callingUid 1419 + " not in uid " + callingUid); 1420 } 1421 1422 // Legacy apps in permission review mode trigger a user prompt 1423 if (applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { 1424 Intent intent = new Intent(intentAction); 1425 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK 1426 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 1427 intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName); 1428 mContext.startActivity(intent); 1429 return true; 1430 } 1431 } catch (PackageManager.NameNotFoundException e) { 1432 throw new RemoteException(e.getMessage()); 1433 } 1434 return false; 1435 } 1436 1437 /** 1438 * Observes settings changes to scan always mode. 1439 */ 1440 private void registerForScanModeChange() { 1441 ContentObserver contentObserver = new ContentObserver(null) { 1442 @Override 1443 public void onChange(boolean selfChange) { 1444 mSettingsStore.handleWifiScanAlwaysAvailableToggled(); 1445 mWifiController.sendMessage(CMD_SCAN_ALWAYS_MODE_CHANGED); 1446 } 1447 }; 1448 1449 mContext.getContentResolver().registerContentObserver( 1450 Settings.Global.getUriFor(Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE), 1451 false, contentObserver); 1452 } 1453 1454 private void registerForBroadcasts() { 1455 IntentFilter intentFilter = new IntentFilter(); 1456 intentFilter.addAction(Intent.ACTION_SCREEN_ON); 1457 intentFilter.addAction(Intent.ACTION_USER_PRESENT); 1458 intentFilter.addAction(Intent.ACTION_SCREEN_OFF); 1459 intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); 1460 intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); 1461 intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); 1462 intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED); 1463 intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); 1464 1465 boolean trackEmergencyCallState = mContext.getResources().getBoolean( 1466 com.android.internal.R.bool.config_wifi_turn_off_during_emergency_call); 1467 if (trackEmergencyCallState) { 1468 intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED); 1469 } 1470 1471 mContext.registerReceiver(mReceiver, intentFilter); 1472 } 1473 1474 private void registerForPackageOrUserRemoval() { 1475 IntentFilter intentFilter = new IntentFilter(); 1476 intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 1477 intentFilter.addAction(Intent.ACTION_USER_REMOVED); 1478 mContext.registerReceiverAsUser(new BroadcastReceiver() { 1479 @Override 1480 public void onReceive(Context context, Intent intent) { 1481 switch (intent.getAction()) { 1482 case Intent.ACTION_PACKAGE_REMOVED: { 1483 if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { 1484 return; 1485 } 1486 int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); 1487 Uri uri = intent.getData(); 1488 if (uid == -1 || uri == null) { 1489 return; 1490 } 1491 String pkgName = uri.getSchemeSpecificPart(); 1492 mWifiStateMachine.removeAppConfigs(pkgName, uid); 1493 break; 1494 } 1495 case Intent.ACTION_USER_REMOVED: { 1496 int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); 1497 mWifiStateMachine.removeUserConfigs(userHandle); 1498 break; 1499 } 1500 } 1501 } 1502 }, UserHandle.ALL, intentFilter, null, null); 1503 } 1504 1505 @Override 1506 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1507 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1508 != PackageManager.PERMISSION_GRANTED) { 1509 pw.println("Permission Denial: can't dump WifiService from from pid=" 1510 + Binder.getCallingPid() 1511 + ", uid=" + Binder.getCallingUid()); 1512 return; 1513 } 1514 if (args.length > 0 && WifiMetrics.PROTO_DUMP_ARG.equals(args[0])) { 1515 // WifiMetrics proto bytes were requested. Dump only these. 1516 mWifiStateMachine.updateWifiMetrics(); 1517 mWifiMetrics.dump(fd, pw, args); 1518 } else if (args.length > 0 && IpManager.DUMP_ARG.equals(args[0])) { 1519 // IpManager dump was requested. Pass it along and take no further action. 1520 String[] ipManagerArgs = new String[args.length - 1]; 1521 System.arraycopy(args, 1, ipManagerArgs, 0, ipManagerArgs.length); 1522 mWifiStateMachine.dumpIpManager(fd, pw, ipManagerArgs); 1523 } else { 1524 pw.println("Wi-Fi is " + mWifiStateMachine.syncGetWifiStateByName()); 1525 pw.println("Stay-awake conditions: " + 1526 Settings.Global.getInt(mContext.getContentResolver(), 1527 Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0)); 1528 pw.println("mInIdleMode " + mInIdleMode); 1529 pw.println("mScanPending " + mScanPending); 1530 mWifiController.dump(fd, pw, args); 1531 mSettingsStore.dump(fd, pw, args); 1532 mNotificationController.dump(fd, pw, args); 1533 mTrafficPoller.dump(fd, pw, args); 1534 pw.println(); 1535 pw.println("Locks held:"); 1536 mWifiLockManager.dump(pw); 1537 pw.println(); 1538 mWifiMulticastLockManager.dump(pw); 1539 pw.println(); 1540 mWifiStateMachine.dump(fd, pw, args); 1541 pw.println(); 1542 mWifiBackupRestore.dump(fd, pw, args); 1543 pw.println(); 1544 } 1545 } 1546 1547 @Override 1548 public boolean acquireWifiLock(IBinder binder, int lockMode, String tag, WorkSource ws) { 1549 if (mWifiLockManager.acquireWifiLock(lockMode, tag, binder, ws)) { 1550 mWifiController.sendMessage(CMD_LOCKS_CHANGED); 1551 return true; 1552 } 1553 return false; 1554 } 1555 1556 @Override 1557 public void updateWifiLockWorkSource(IBinder binder, WorkSource ws) { 1558 mWifiLockManager.updateWifiLockWorkSource(binder, ws); 1559 } 1560 1561 @Override 1562 public boolean releaseWifiLock(IBinder binder) { 1563 if (mWifiLockManager.releaseWifiLock(binder)) { 1564 mWifiController.sendMessage(CMD_LOCKS_CHANGED); 1565 return true; 1566 } 1567 return false; 1568 } 1569 1570 @Override 1571 public void initializeMulticastFiltering() { 1572 enforceMulticastChangePermission(); 1573 mWifiMulticastLockManager.initializeFiltering(); 1574 } 1575 1576 @Override 1577 public void acquireMulticastLock(IBinder binder, String tag) { 1578 enforceMulticastChangePermission(); 1579 mWifiMulticastLockManager.acquireLock(binder, tag); 1580 } 1581 1582 @Override 1583 public void releaseMulticastLock() { 1584 enforceMulticastChangePermission(); 1585 mWifiMulticastLockManager.releaseLock(); 1586 } 1587 1588 @Override 1589 public boolean isMulticastEnabled() { 1590 enforceAccessPermission(); 1591 return mWifiMulticastLockManager.isMulticastEnabled(); 1592 } 1593 1594 @Override 1595 public void enableVerboseLogging(int verbose) { 1596 enforceAccessPermission(); 1597 mFacade.setIntegerSetting( 1598 mContext, Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED, verbose); 1599 enableVerboseLoggingInternal(verbose); 1600 } 1601 1602 private void enableVerboseLoggingInternal(int verbose) { 1603 mWifiStateMachine.enableVerboseLogging(verbose); 1604 mWifiLockManager.enableVerboseLogging(verbose); 1605 mWifiMulticastLockManager.enableVerboseLogging(verbose); 1606 mWifiInjector.getWifiLastResortWatchdog().enableVerboseLogging(verbose); 1607 mWifiInjector.getWifiBackupRestore().enableVerboseLogging(verbose); 1608 } 1609 1610 @Override 1611 public int getVerboseLoggingLevel() { 1612 enforceAccessPermission(); 1613 return mFacade.getIntegerSetting( 1614 mContext, Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED, 0); 1615 } 1616 1617 @Override 1618 public void enableAggressiveHandover(int enabled) { 1619 enforceAccessPermission(); 1620 mWifiStateMachine.enableAggressiveHandover(enabled); 1621 } 1622 1623 @Override 1624 public int getAggressiveHandover() { 1625 enforceAccessPermission(); 1626 return mWifiStateMachine.getAggressiveHandover(); 1627 } 1628 1629 @Override 1630 public void setAllowScansWithTraffic(int enabled) { 1631 enforceAccessPermission(); 1632 mWifiStateMachine.setAllowScansWithTraffic(enabled); 1633 } 1634 1635 @Override 1636 public int getAllowScansWithTraffic() { 1637 enforceAccessPermission(); 1638 return mWifiStateMachine.getAllowScansWithTraffic(); 1639 } 1640 1641 @Override 1642 public boolean setEnableAutoJoinWhenAssociated(boolean enabled) { 1643 enforceChangePermission(); 1644 return mWifiStateMachine.setEnableAutoJoinWhenAssociated(enabled); 1645 } 1646 1647 @Override 1648 public boolean getEnableAutoJoinWhenAssociated() { 1649 enforceAccessPermission(); 1650 return mWifiStateMachine.getEnableAutoJoinWhenAssociated(); 1651 } 1652 1653 /* Return the Wifi Connection statistics object */ 1654 @Override 1655 public WifiConnectionStatistics getConnectionStatistics() { 1656 enforceAccessPermission(); 1657 enforceReadCredentialPermission(); 1658 if (mWifiStateMachineChannel != null) { 1659 return mWifiStateMachine.syncGetConnectionStatistics(mWifiStateMachineChannel); 1660 } else { 1661 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1662 return null; 1663 } 1664 } 1665 1666 @Override 1667 public void factoryReset() { 1668 enforceConnectivityInternalPermission(); 1669 1670 if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) { 1671 return; 1672 } 1673 1674 if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING)) { 1675 // Turn mobile hotspot off 1676 setWifiApEnabled(null, false); 1677 } 1678 1679 if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_WIFI)) { 1680 // Enable wifi 1681 try { 1682 setWifiEnabled(mContext.getOpPackageName(), true); 1683 } catch (RemoteException e) { 1684 /* ignore - local call */ 1685 } 1686 // Delete all Wifi SSIDs 1687 List<WifiConfiguration> networks = getConfiguredNetworks(); 1688 if (networks != null) { 1689 for (WifiConfiguration config : networks) { 1690 removeNetwork(config.networkId); 1691 } 1692 saveConfiguration(); 1693 } 1694 } 1695 } 1696 1697 /* private methods */ 1698 static boolean logAndReturnFalse(String s) { 1699 Log.d(TAG, s); 1700 return false; 1701 } 1702 1703 public static boolean isValid(WifiConfiguration config) { 1704 String validity = checkValidity(config); 1705 return validity == null || logAndReturnFalse(validity); 1706 } 1707 1708 public static boolean isValidPasspoint(WifiConfiguration config) { 1709 String validity = checkPasspointValidity(config); 1710 return validity == null || logAndReturnFalse(validity); 1711 } 1712 1713 public static String checkValidity(WifiConfiguration config) { 1714 if (config.allowedKeyManagement == null) 1715 return "allowed kmgmt"; 1716 1717 if (config.allowedKeyManagement.cardinality() > 1) { 1718 if (config.allowedKeyManagement.cardinality() != 2) { 1719 return "cardinality != 2"; 1720 } 1721 if (!config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP)) { 1722 return "not WPA_EAP"; 1723 } 1724 if ((!config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X)) 1725 && (!config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK))) { 1726 return "not PSK or 8021X"; 1727 } 1728 } 1729 return null; 1730 } 1731 1732 public static String checkPasspointValidity(WifiConfiguration config) { 1733 if (!TextUtils.isEmpty(config.FQDN)) { 1734 /* this is passpoint configuration; it must not have an SSID */ 1735 if (!TextUtils.isEmpty(config.SSID)) { 1736 return "SSID not expected for Passpoint: '" + config.SSID + 1737 "' FQDN " + toHexString(config.FQDN); 1738 } 1739 /* this is passpoint configuration; it must have a providerFriendlyName */ 1740 if (TextUtils.isEmpty(config.providerFriendlyName)) { 1741 return "no provider friendly name"; 1742 } 1743 WifiEnterpriseConfig enterpriseConfig = config.enterpriseConfig; 1744 /* this is passpoint configuration; it must have enterprise config */ 1745 if (enterpriseConfig == null 1746 || enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.NONE ) { 1747 return "no enterprise config"; 1748 } 1749 if ((enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TLS || 1750 enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TTLS || 1751 enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.PEAP) && 1752 enterpriseConfig.getCaCertificate() == null) { 1753 return "no CA certificate"; 1754 } 1755 } 1756 return null; 1757 } 1758 1759 @Override 1760 public Network getCurrentNetwork() { 1761 enforceAccessPermission(); 1762 return mWifiStateMachine.getCurrentNetwork(); 1763 } 1764 1765 public static String toHexString(String s) { 1766 if (s == null) { 1767 return "null"; 1768 } 1769 StringBuilder sb = new StringBuilder(); 1770 sb.append('\'').append(s).append('\''); 1771 for (int n = 0; n < s.length(); n++) { 1772 sb.append(String.format(" %02x", s.charAt(n) & 0xffff)); 1773 } 1774 return sb.toString(); 1775 } 1776 1777 /** 1778 * Checks that calling process has android.Manifest.permission.ACCESS_COARSE_LOCATION or 1779 * android.Manifest.permission.ACCESS_FINE_LOCATION and a corresponding app op is allowed 1780 */ 1781 private boolean checkCallerCanAccessScanResults(String callingPackage, int uid) { 1782 if (ActivityManager.checkUidPermission(Manifest.permission.ACCESS_FINE_LOCATION, uid) 1783 == PackageManager.PERMISSION_GRANTED 1784 && checkAppOppAllowed(AppOpsManager.OP_FINE_LOCATION, callingPackage, uid)) { 1785 return true; 1786 } 1787 1788 if (ActivityManager.checkUidPermission(Manifest.permission.ACCESS_COARSE_LOCATION, uid) 1789 == PackageManager.PERMISSION_GRANTED 1790 && checkAppOppAllowed(AppOpsManager.OP_COARSE_LOCATION, callingPackage, uid)) { 1791 return true; 1792 } 1793 boolean apiLevel23App = isMApp(mContext, callingPackage); 1794 // Pre-M apps running in the foreground should continue getting scan results 1795 if (!apiLevel23App && isForegroundApp(callingPackage)) { 1796 return true; 1797 } 1798 Log.e(TAG, "Permission denial: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION " 1799 + "permission to get scan results"); 1800 return false; 1801 } 1802 1803 private boolean checkAppOppAllowed(int op, String callingPackage, int uid) { 1804 return mAppOps.noteOp(op, uid, callingPackage) == AppOpsManager.MODE_ALLOWED; 1805 } 1806 1807 private static boolean isMApp(Context context, String pkgName) { 1808 try { 1809 return context.getPackageManager().getApplicationInfo(pkgName, 0) 1810 .targetSdkVersion >= Build.VERSION_CODES.M; 1811 } catch (PackageManager.NameNotFoundException e) { 1812 // In case of exception, assume M app (more strict checking) 1813 } 1814 return true; 1815 } 1816 1817 public void hideCertFromUnaffiliatedUsers(String alias) { 1818 mCertManager.hideCertFromUnaffiliatedUsers(alias); 1819 } 1820 1821 public String[] listClientCertsForCurrentUser() { 1822 return mCertManager.listClientCertsForCurrentUser(); 1823 } 1824 1825 /** 1826 * Return true if the specified package name is a foreground app. 1827 * 1828 * @param pkgName application package name. 1829 */ 1830 private boolean isForegroundApp(String pkgName) { 1831 ActivityManager am = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE); 1832 List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1); 1833 return !tasks.isEmpty() && pkgName.equals(tasks.get(0).topActivity.getPackageName()); 1834 } 1835 1836 /** 1837 * Enable/disable WifiConnectivityManager at runtime 1838 * 1839 * @param enabled true-enable; false-disable 1840 */ 1841 @Override 1842 public void enableWifiConnectivityManager(boolean enabled) { 1843 enforceConnectivityInternalPermission(); 1844 mWifiStateMachine.enableWifiConnectivityManager(enabled); 1845 } 1846 1847 /** 1848 * Retrieve the data to be backed to save the current state. 1849 * 1850 * @return Raw byte stream of the data to be backed up. 1851 */ 1852 @Override 1853 public byte[] retrieveBackupData() { 1854 enforceReadCredentialPermission(); 1855 enforceAccessPermission(); 1856 if (mWifiStateMachineChannel == null) { 1857 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1858 return null; 1859 } 1860 1861 Slog.d(TAG, "Retrieving backup data"); 1862 List<WifiConfiguration> wifiConfigurations = 1863 mWifiStateMachine.syncGetPrivilegedConfiguredNetwork(mWifiStateMachineChannel); 1864 byte[] backupData = 1865 mWifiBackupRestore.retrieveBackupDataFromConfigurations(wifiConfigurations); 1866 Slog.d(TAG, "Retrieved backup data"); 1867 return backupData; 1868 } 1869 1870 /** 1871 * Helper method to restore networks retrieved from backup data. 1872 * 1873 * @param configurations list of WifiConfiguration objects parsed from the backup data. 1874 */ 1875 private void restoreNetworks(List<WifiConfiguration> configurations) { 1876 if (configurations == null) { 1877 Slog.e(TAG, "Backup data parse failed"); 1878 return; 1879 } 1880 for (WifiConfiguration configuration : configurations) { 1881 int networkId = mWifiStateMachine.syncAddOrUpdateNetwork( 1882 mWifiStateMachineChannel, configuration); 1883 if (networkId == WifiConfiguration.INVALID_NETWORK_ID) { 1884 Slog.e(TAG, "Restore network failed: " + configuration.configKey()); 1885 continue; 1886 } 1887 // Enable all networks restored. 1888 mWifiStateMachine.syncEnableNetwork(mWifiStateMachineChannel, networkId, false); 1889 } 1890 } 1891 1892 /** 1893 * Restore state from the backed up data. 1894 * 1895 * @param data Raw byte stream of the backed up data. 1896 */ 1897 @Override 1898 public void restoreBackupData(byte[] data) { 1899 enforceChangePermission(); 1900 if (mWifiStateMachineChannel == null) { 1901 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1902 return; 1903 } 1904 1905 Slog.d(TAG, "Restoring backup data"); 1906 List<WifiConfiguration> wifiConfigurations = 1907 mWifiBackupRestore.retrieveConfigurationsFromBackupData(data); 1908 restoreNetworks(wifiConfigurations); 1909 Slog.d(TAG, "Restored backup data"); 1910 } 1911 1912 /** 1913 * Restore state from the older supplicant back up data. 1914 * The old backup data was essentially a backup of wpa_supplicant.conf & ipconfig.txt file. 1915 * 1916 * @param supplicantData Raw byte stream of wpa_supplicant.conf 1917 * @param ipConfigData Raw byte stream of ipconfig.txt 1918 */ 1919 public void restoreSupplicantBackupData(byte[] supplicantData, byte[] ipConfigData) { 1920 enforceChangePermission(); 1921 if (mWifiStateMachineChannel == null) { 1922 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1923 return; 1924 } 1925 1926 Slog.d(TAG, "Restoring supplicant backup data"); 1927 List<WifiConfiguration> wifiConfigurations = 1928 mWifiBackupRestore.retrieveConfigurationsFromSupplicantBackupData( 1929 supplicantData, ipConfigData); 1930 restoreNetworks(wifiConfigurations); 1931 Slog.d(TAG, "Restored supplicant backup data"); 1932 } 1933} 1934