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