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