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