WifiServiceImpl.java revision 6c11cd5d6ff04afdf1bbbc99a850025d46c7bdc9
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.ActivityManager; 33import android.app.AppOpsManager; 34import android.bluetooth.BluetoothAdapter; 35import android.content.BroadcastReceiver; 36import android.content.Context; 37import android.content.Intent; 38import android.content.IntentFilter; 39import android.content.pm.PackageManager; 40import android.content.pm.UserInfo; 41import android.database.ContentObserver; 42import android.net.ConnectivityManager; 43import android.net.DhcpInfo; 44import android.net.DhcpResults; 45import android.net.Network; 46import android.net.NetworkScorerAppManager; 47import android.net.NetworkUtils; 48import android.net.Uri; 49import android.net.ip.IpManager; 50import android.net.wifi.IWifiManager; 51import android.net.wifi.PasspointManagementObjectDefinition; 52import android.net.wifi.ScanResult; 53import android.net.wifi.ScanSettings; 54import android.net.wifi.WifiActivityEnergyInfo; 55import android.net.wifi.WifiConfiguration; 56import android.net.wifi.WifiConnectionStatistics; 57import android.net.wifi.WifiEnterpriseConfig; 58import android.net.wifi.WifiInfo; 59import android.net.wifi.WifiLinkLayerStats; 60import android.net.wifi.WifiManager; 61import android.net.wifi.WifiScanner; 62import android.os.AsyncTask; 63import android.os.BatteryStats; 64import android.os.Binder; 65import android.os.Build; 66import android.os.Bundle; 67import android.os.Handler; 68import android.os.HandlerThread; 69import android.os.IBinder; 70import android.os.Looper; 71import android.os.Message; 72import android.os.Messenger; 73import android.os.PowerManager; 74import android.os.RemoteException; 75import android.os.ResultReceiver; 76import android.os.SystemClock; 77import android.os.UserHandle; 78import android.os.UserManager; 79import android.os.WorkSource; 80import android.provider.Settings; 81import android.text.TextUtils; 82import android.util.Log; 83import android.util.Slog; 84 85import com.android.internal.telephony.IccCardConstants; 86import com.android.internal.telephony.PhoneConstants; 87import com.android.internal.telephony.TelephonyIntents; 88import com.android.internal.util.AsyncChannel; 89import com.android.server.wifi.configparse.ConfigBuilder; 90 91import org.xml.sax.SAXException; 92 93import java.io.BufferedReader; 94import java.io.FileDescriptor; 95import java.io.FileNotFoundException; 96import java.io.FileReader; 97import java.io.IOException; 98import java.io.PrintWriter; 99import java.net.Inet4Address; 100import java.net.InetAddress; 101import java.security.GeneralSecurityException; 102import java.security.KeyStore; 103import java.security.cert.CertPath; 104import java.security.cert.CertPathValidator; 105import java.security.cert.CertPathValidatorException; 106import java.security.cert.CertificateFactory; 107import java.security.cert.PKIXParameters; 108import java.security.cert.X509Certificate; 109import java.util.ArrayList; 110import java.util.Arrays; 111import java.util.List; 112 113/** 114 * WifiService handles remote WiFi operation requests by implementing 115 * the IWifiManager interface. 116 * 117 * @hide 118 */ 119public class WifiServiceImpl extends IWifiManager.Stub { 120 private static final String TAG = "WifiService"; 121 private static final boolean DBG = true; 122 private static final boolean VDBG = false; 123 124 final WifiStateMachine mWifiStateMachine; 125 126 private final Context mContext; 127 private final FrameworkFacade mFacade; 128 129 private final PowerManager mPowerManager; 130 private final AppOpsManager mAppOps; 131 private final UserManager mUserManager; 132 private final WifiCountryCode mCountryCode; 133 // Debug counter tracking scan requests sent by WifiManager 134 private int scanRequestCounter = 0; 135 136 /* Tracks the open wi-fi network notification */ 137 private WifiNotificationController mNotificationController; 138 /* Polls traffic stats and notifies clients */ 139 private WifiTrafficPoller mTrafficPoller; 140 /* Tracks the persisted states for wi-fi & airplane mode */ 141 final WifiSettingsStore mSettingsStore; 142 /* Logs connection events and some general router and scan stats */ 143 private final WifiMetrics mWifiMetrics; 144 /* Manages affiliated certificates for current user */ 145 private final WifiCertManager mCertManager; 146 147 private final WifiInjector mWifiInjector; 148 /* Backup/Restore Module */ 149 private final WifiBackupRestore mWifiBackupRestore; 150 151 private WifiScanner mWifiScanner; 152 153 /** 154 * Asynchronous channel to WifiStateMachine 155 */ 156 private AsyncChannel mWifiStateMachineChannel; 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 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 userId = UserHandle.getCallingUserId(); 994 int uid = Binder.getCallingUid(); 995 boolean canReadPeerMacAddresses = checkPeersMacAddress(); 996 boolean isActiveNetworkScorer = 997 NetworkScorerAppManager.isCallerActiveScorer(mContext, uid); 998 boolean hasInteractUsersFull = checkInteractAcrossUsersFull(); 999 long ident = Binder.clearCallingIdentity(); 1000 try { 1001 if (!canReadPeerMacAddresses && !isActiveNetworkScorer 1002 && !isLocationEnabled(callingPackage)) { 1003 return new ArrayList<ScanResult>(); 1004 } 1005 if (!canReadPeerMacAddresses && !isActiveNetworkScorer 1006 && !checkCallerCanAccessScanResults(callingPackage, uid)) { 1007 return new ArrayList<ScanResult>(); 1008 } 1009 if (mAppOps.noteOp(AppOpsManager.OP_WIFI_SCAN, uid, callingPackage) 1010 != AppOpsManager.MODE_ALLOWED) { 1011 return new ArrayList<ScanResult>(); 1012 } 1013 if (!isCurrentProfile(userId) && !hasInteractUsersFull) { 1014 return new ArrayList<ScanResult>(); 1015 } 1016 return mWifiStateMachine.syncGetScanResultsList(); 1017 } finally { 1018 Binder.restoreCallingIdentity(ident); 1019 } 1020 } 1021 1022 /** 1023 * Add a Hotspot 2.0 release 2 Management Object 1024 * @param mo The MO in XML form 1025 * @return -1 for failure 1026 */ 1027 @Override 1028 public int addPasspointManagementObject(String mo) { 1029 return mWifiStateMachine.syncAddPasspointManagementObject(mWifiStateMachineChannel, mo); 1030 } 1031 1032 /** 1033 * Modify a Hotspot 2.0 release 2 Management Object 1034 * @param fqdn The FQDN of the service provider 1035 * @param mos A List of MO definitions to be updated 1036 * @return the number of nodes updated, or -1 for failure 1037 */ 1038 @Override 1039 public int modifyPasspointManagementObject(String fqdn, List<PasspointManagementObjectDefinition> mos) { 1040 return mWifiStateMachine.syncModifyPasspointManagementObject(mWifiStateMachineChannel, fqdn, mos); 1041 } 1042 1043 /** 1044 * Query for a Hotspot 2.0 release 2 OSU icon 1045 * @param bssid The BSSID of the AP 1046 * @param fileName Icon file name 1047 */ 1048 @Override 1049 public void queryPasspointIcon(long bssid, String fileName) { 1050 mWifiStateMachine.syncQueryPasspointIcon(mWifiStateMachineChannel, bssid, fileName); 1051 } 1052 1053 /** 1054 * Match the currently associated network against the SP matching the given FQDN 1055 * @param fqdn FQDN of the SP 1056 * @return ordinal [HomeProvider, RoamingProvider, Incomplete, None, Declined] 1057 */ 1058 @Override 1059 public int matchProviderWithCurrentNetwork(String fqdn) { 1060 return mWifiStateMachine.matchProviderWithCurrentNetwork(mWifiStateMachineChannel, fqdn); 1061 } 1062 1063 /** 1064 * Deauthenticate and set the re-authentication hold off time for the current network 1065 * @param holdoff hold off time in milliseconds 1066 * @param ess set if the hold off pertains to an ESS rather than a BSS 1067 */ 1068 @Override 1069 public void deauthenticateNetwork(long holdoff, boolean ess) { 1070 mWifiStateMachine.deauthenticateNetwork(mWifiStateMachineChannel, holdoff, ess); 1071 } 1072 1073 private boolean isLocationEnabled(String callingPackage) { 1074 boolean legacyForegroundApp = !isMApp(mContext, callingPackage) 1075 && isForegroundApp(callingPackage); 1076 return legacyForegroundApp || Settings.Secure.getInt(mContext.getContentResolver(), 1077 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF) 1078 != Settings.Secure.LOCATION_MODE_OFF; 1079 } 1080 1081 /** 1082 * Returns true if the caller holds INTERACT_ACROSS_USERS_FULL. 1083 */ 1084 private boolean checkInteractAcrossUsersFull() { 1085 return mContext.checkCallingOrSelfPermission( 1086 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) 1087 == PackageManager.PERMISSION_GRANTED; 1088 } 1089 1090 /** 1091 * Returns true if the caller holds PEERS_MAC_ADDRESS. 1092 */ 1093 private boolean checkPeersMacAddress() { 1094 return mContext.checkCallingOrSelfPermission( 1095 android.Manifest.permission.PEERS_MAC_ADDRESS) == PackageManager.PERMISSION_GRANTED; 1096 } 1097 1098 /** 1099 * Returns true if the calling user is the current one or a profile of the 1100 * current user.. 1101 */ 1102 private boolean isCurrentProfile(int userId) { 1103 int currentUser = ActivityManager.getCurrentUser(); 1104 if (userId == currentUser) { 1105 return true; 1106 } 1107 List<UserInfo> profiles = mUserManager.getProfiles(currentUser); 1108 for (UserInfo user : profiles) { 1109 if (userId == user.id) { 1110 return true; 1111 } 1112 } 1113 return false; 1114 } 1115 1116 /** 1117 * Tell the supplicant to persist the current list of configured networks. 1118 * @return {@code true} if the operation succeeded 1119 * 1120 * TODO: deprecate this 1121 */ 1122 @Override 1123 public boolean saveConfiguration() { 1124 enforceChangePermission(); 1125 if (mWifiStateMachineChannel != null) { 1126 return mWifiStateMachine.syncSaveConfig(mWifiStateMachineChannel); 1127 } else { 1128 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1129 return false; 1130 } 1131 } 1132 1133 /** 1134 * Set the country code 1135 * @param countryCode ISO 3166 country code. 1136 * @param persist {@code true} if the setting should be remembered. 1137 * 1138 * The persist behavior exists so that wifi can fall back to the last 1139 * persisted country code on a restart, when the locale information is 1140 * not available from telephony. 1141 */ 1142 @Override 1143 public void setCountryCode(String countryCode, boolean persist) { 1144 Slog.i(TAG, "WifiService trying to set country code to " + countryCode + 1145 " with persist set to " + persist); 1146 enforceConnectivityInternalPermission(); 1147 final long token = Binder.clearCallingIdentity(); 1148 try { 1149 if (mCountryCode.setCountryCode(countryCode, persist) && persist) { 1150 // Save this country code to persistent storage 1151 mFacade.setStringSetting(mContext, 1152 Settings.Global.WIFI_COUNTRY_CODE, 1153 countryCode); 1154 } 1155 } finally { 1156 Binder.restoreCallingIdentity(token); 1157 } 1158 } 1159 1160 /** 1161 * Get the country code 1162 * @return Get the best choice country code for wifi, regardless of if it was set or 1163 * not. 1164 * Returns null when there is no country code available. 1165 */ 1166 @Override 1167 public String getCountryCode() { 1168 enforceConnectivityInternalPermission(); 1169 String country = mCountryCode.getCountryCode(); 1170 return country; 1171 } 1172 /** 1173 * Set the operational frequency band 1174 * @param band One of 1175 * {@link WifiManager#WIFI_FREQUENCY_BAND_AUTO}, 1176 * {@link WifiManager#WIFI_FREQUENCY_BAND_5GHZ}, 1177 * {@link WifiManager#WIFI_FREQUENCY_BAND_2GHZ}, 1178 * @param persist {@code true} if the setting should be remembered. 1179 * 1180 */ 1181 @Override 1182 public void setFrequencyBand(int band, boolean persist) { 1183 enforceChangePermission(); 1184 if (!isDualBandSupported()) return; 1185 Slog.i(TAG, "WifiService trying to set frequency band to " + band + 1186 " with persist set to " + persist); 1187 final long token = Binder.clearCallingIdentity(); 1188 try { 1189 mWifiStateMachine.setFrequencyBand(band, persist); 1190 } finally { 1191 Binder.restoreCallingIdentity(token); 1192 } 1193 } 1194 1195 1196 /** 1197 * Get the operational frequency band 1198 */ 1199 @Override 1200 public int getFrequencyBand() { 1201 enforceAccessPermission(); 1202 return mWifiStateMachine.getFrequencyBand(); 1203 } 1204 1205 @Override 1206 public boolean isDualBandSupported() { 1207 //TODO: Should move towards adding a driver API that checks at runtime 1208 return mContext.getResources().getBoolean( 1209 com.android.internal.R.bool.config_wifi_dual_band_support); 1210 } 1211 1212 /** 1213 * Return the DHCP-assigned addresses from the last successful DHCP request, 1214 * if any. 1215 * @return the DHCP information 1216 * @deprecated 1217 */ 1218 @Override 1219 @Deprecated 1220 public DhcpInfo getDhcpInfo() { 1221 enforceAccessPermission(); 1222 DhcpResults dhcpResults = mWifiStateMachine.syncGetDhcpResults(); 1223 1224 DhcpInfo info = new DhcpInfo(); 1225 1226 if (dhcpResults.ipAddress != null && 1227 dhcpResults.ipAddress.getAddress() instanceof Inet4Address) { 1228 info.ipAddress = NetworkUtils.inetAddressToInt((Inet4Address) dhcpResults.ipAddress.getAddress()); 1229 } 1230 1231 if (dhcpResults.gateway != null) { 1232 info.gateway = NetworkUtils.inetAddressToInt((Inet4Address) dhcpResults.gateway); 1233 } 1234 1235 int dnsFound = 0; 1236 for (InetAddress dns : dhcpResults.dnsServers) { 1237 if (dns instanceof Inet4Address) { 1238 if (dnsFound == 0) { 1239 info.dns1 = NetworkUtils.inetAddressToInt((Inet4Address)dns); 1240 } else { 1241 info.dns2 = NetworkUtils.inetAddressToInt((Inet4Address)dns); 1242 } 1243 if (++dnsFound > 1) break; 1244 } 1245 } 1246 Inet4Address serverAddress = dhcpResults.serverAddress; 1247 if (serverAddress != null) { 1248 info.serverAddress = NetworkUtils.inetAddressToInt(serverAddress); 1249 } 1250 info.leaseDuration = dhcpResults.leaseDuration; 1251 1252 return info; 1253 } 1254 1255 /** 1256 * enable TDLS for the local NIC to remote NIC 1257 * The APPs don't know the remote MAC address to identify NIC though, 1258 * so we need to do additional work to find it from remote IP address 1259 */ 1260 1261 class TdlsTaskParams { 1262 public String remoteIpAddress; 1263 public boolean enable; 1264 } 1265 1266 class TdlsTask extends AsyncTask<TdlsTaskParams, Integer, Integer> { 1267 @Override 1268 protected Integer doInBackground(TdlsTaskParams... params) { 1269 1270 // Retrieve parameters for the call 1271 TdlsTaskParams param = params[0]; 1272 String remoteIpAddress = param.remoteIpAddress.trim(); 1273 boolean enable = param.enable; 1274 1275 // Get MAC address of Remote IP 1276 String macAddress = null; 1277 1278 BufferedReader reader = null; 1279 1280 try { 1281 reader = new BufferedReader(new FileReader("/proc/net/arp")); 1282 1283 // Skip over the line bearing colum titles 1284 String line = reader.readLine(); 1285 1286 while ((line = reader.readLine()) != null) { 1287 String[] tokens = line.split("[ ]+"); 1288 if (tokens.length < 6) { 1289 continue; 1290 } 1291 1292 // ARP column format is 1293 // Address HWType HWAddress Flags Mask IFace 1294 String ip = tokens[0]; 1295 String mac = tokens[3]; 1296 1297 if (remoteIpAddress.equals(ip)) { 1298 macAddress = mac; 1299 break; 1300 } 1301 } 1302 1303 if (macAddress == null) { 1304 Slog.w(TAG, "Did not find remoteAddress {" + remoteIpAddress + "} in " + 1305 "/proc/net/arp"); 1306 } else { 1307 enableTdlsWithMacAddress(macAddress, enable); 1308 } 1309 1310 } catch (FileNotFoundException e) { 1311 Slog.e(TAG, "Could not open /proc/net/arp to lookup mac address"); 1312 } catch (IOException e) { 1313 Slog.e(TAG, "Could not read /proc/net/arp to lookup mac address"); 1314 } finally { 1315 try { 1316 if (reader != null) { 1317 reader.close(); 1318 } 1319 } 1320 catch (IOException e) { 1321 // Do nothing 1322 } 1323 } 1324 1325 return 0; 1326 } 1327 } 1328 1329 @Override 1330 public void enableTdls(String remoteAddress, boolean enable) { 1331 if (remoteAddress == null) { 1332 throw new IllegalArgumentException("remoteAddress cannot be null"); 1333 } 1334 1335 TdlsTaskParams params = new TdlsTaskParams(); 1336 params.remoteIpAddress = remoteAddress; 1337 params.enable = enable; 1338 new TdlsTask().execute(params); 1339 } 1340 1341 1342 @Override 1343 public void enableTdlsWithMacAddress(String remoteMacAddress, boolean enable) { 1344 if (remoteMacAddress == null) { 1345 throw new IllegalArgumentException("remoteMacAddress cannot be null"); 1346 } 1347 1348 mWifiStateMachine.enableTdls(remoteMacAddress, enable); 1349 } 1350 1351 /** 1352 * Get a reference to handler. This is used by a client to establish 1353 * an AsyncChannel communication with WifiService 1354 */ 1355 @Override 1356 public Messenger getWifiServiceMessenger() { 1357 enforceAccessPermission(); 1358 enforceChangePermission(); 1359 return new Messenger(mClientHandler); 1360 } 1361 1362 /** 1363 * Disable an ephemeral network, i.e. network that is created thru a WiFi Scorer 1364 */ 1365 @Override 1366 public void disableEphemeralNetwork(String SSID) { 1367 enforceAccessPermission(); 1368 enforceChangePermission(); 1369 mWifiStateMachine.disableEphemeralNetwork(SSID); 1370 } 1371 1372 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 1373 @Override 1374 public void onReceive(Context context, Intent intent) { 1375 String action = intent.getAction(); 1376 if (action.equals(Intent.ACTION_SCREEN_ON)) { 1377 mWifiController.sendMessage(CMD_SCREEN_ON); 1378 } else if (action.equals(Intent.ACTION_USER_PRESENT)) { 1379 mWifiController.sendMessage(CMD_USER_PRESENT); 1380 } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { 1381 mWifiController.sendMessage(CMD_SCREEN_OFF); 1382 } else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { 1383 int pluggedType = intent.getIntExtra("plugged", 0); 1384 mWifiController.sendMessage(CMD_BATTERY_CHANGED, pluggedType, 0, null); 1385 } else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) { 1386 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, 1387 BluetoothAdapter.STATE_DISCONNECTED); 1388 mWifiStateMachine.sendBluetoothAdapterStateChange(state); 1389 } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) { 1390 boolean emergencyMode = intent.getBooleanExtra("phoneinECMState", false); 1391 mWifiController.sendMessage(CMD_EMERGENCY_MODE_CHANGED, emergencyMode ? 1 : 0, 0); 1392 } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED)) { 1393 boolean inCall = intent.getBooleanExtra(PhoneConstants.PHONE_IN_EMERGENCY_CALL, false); 1394 mWifiController.sendMessage(CMD_EMERGENCY_CALL_STATE_CHANGED, inCall ? 1 : 0, 0); 1395 } else if (action.equals(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED)) { 1396 handleIdleModeChanged(); 1397 } 1398 } 1399 }; 1400 1401 /** 1402 * Observes settings changes to scan always mode. 1403 */ 1404 private void registerForScanModeChange() { 1405 ContentObserver contentObserver = new ContentObserver(null) { 1406 @Override 1407 public void onChange(boolean selfChange) { 1408 mSettingsStore.handleWifiScanAlwaysAvailableToggled(); 1409 mWifiController.sendMessage(CMD_SCAN_ALWAYS_MODE_CHANGED); 1410 } 1411 }; 1412 1413 mContext.getContentResolver().registerContentObserver( 1414 Settings.Global.getUriFor(Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE), 1415 false, contentObserver); 1416 } 1417 1418 private void registerForBroadcasts() { 1419 IntentFilter intentFilter = new IntentFilter(); 1420 intentFilter.addAction(Intent.ACTION_SCREEN_ON); 1421 intentFilter.addAction(Intent.ACTION_USER_PRESENT); 1422 intentFilter.addAction(Intent.ACTION_SCREEN_OFF); 1423 intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); 1424 intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); 1425 intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); 1426 intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED); 1427 intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); 1428 1429 boolean trackEmergencyCallState = mContext.getResources().getBoolean( 1430 com.android.internal.R.bool.config_wifi_turn_off_during_emergency_call); 1431 if (trackEmergencyCallState) { 1432 intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED); 1433 } 1434 1435 mContext.registerReceiver(mReceiver, intentFilter); 1436 } 1437 1438 private void registerForPackageOrUserRemoval() { 1439 IntentFilter intentFilter = new IntentFilter(); 1440 intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 1441 intentFilter.addAction(Intent.ACTION_USER_REMOVED); 1442 mContext.registerReceiverAsUser(new BroadcastReceiver() { 1443 @Override 1444 public void onReceive(Context context, Intent intent) { 1445 switch (intent.getAction()) { 1446 case Intent.ACTION_PACKAGE_REMOVED: { 1447 if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { 1448 return; 1449 } 1450 int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); 1451 Uri uri = intent.getData(); 1452 if (uid == -1 || uri == null) { 1453 return; 1454 } 1455 String pkgName = uri.getSchemeSpecificPart(); 1456 mWifiStateMachine.removeAppConfigs(pkgName, uid); 1457 break; 1458 } 1459 case Intent.ACTION_USER_REMOVED: { 1460 int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); 1461 mWifiStateMachine.removeUserConfigs(userHandle); 1462 break; 1463 } 1464 } 1465 } 1466 }, UserHandle.ALL, intentFilter, null, null); 1467 } 1468 1469 @Override 1470 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1471 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1472 != PackageManager.PERMISSION_GRANTED) { 1473 pw.println("Permission Denial: can't dump WifiService from from pid=" 1474 + Binder.getCallingPid() 1475 + ", uid=" + Binder.getCallingUid()); 1476 return; 1477 } 1478 if (args.length > 0 && WifiMetrics.PROTO_DUMP_ARG.equals(args[0])) { 1479 // WifiMetrics proto bytes were requested. Dump only these. 1480 mWifiStateMachine.updateWifiMetrics(); 1481 mWifiMetrics.dump(fd, pw, args); 1482 } else if (args.length > 0 && IpManager.DUMP_ARG.equals(args[0])) { 1483 // IpManager dump was requested. Pass it along and take no further action. 1484 String[] ipManagerArgs = new String[args.length - 1]; 1485 System.arraycopy(args, 1, ipManagerArgs, 0, ipManagerArgs.length); 1486 mWifiStateMachine.dumpIpManager(fd, pw, ipManagerArgs); 1487 } else { 1488 pw.println("Wi-Fi is " + mWifiStateMachine.syncGetWifiStateByName()); 1489 pw.println("Stay-awake conditions: " + 1490 Settings.Global.getInt(mContext.getContentResolver(), 1491 Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0)); 1492 pw.println("mInIdleMode " + mInIdleMode); 1493 pw.println("mScanPending " + mScanPending); 1494 mWifiController.dump(fd, pw, args); 1495 mSettingsStore.dump(fd, pw, args); 1496 mNotificationController.dump(fd, pw, args); 1497 mTrafficPoller.dump(fd, pw, args); 1498 1499 pw.println("Latest scan results:"); 1500 List<ScanResult> scanResults = mWifiStateMachine.syncGetScanResultsList(); 1501 long nowMs = System.currentTimeMillis(); 1502 if (scanResults != null && scanResults.size() != 0) { 1503 pw.println(" BSSID Frequency RSSI Age SSID " + 1504 " Flags"); 1505 for (ScanResult r : scanResults) { 1506 long ageSec = 0; 1507 long ageMilli = 0; 1508 if (nowMs > r.seen && r.seen > 0) { 1509 ageSec = (nowMs - r.seen) / 1000; 1510 ageMilli = (nowMs - r.seen) % 1000; 1511 } 1512 String candidate = " "; 1513 if (r.isAutoJoinCandidate > 0) candidate = "+"; 1514 pw.printf(" %17s %9d %5d %3d.%03d%s %-32s %s\n", 1515 r.BSSID, 1516 r.frequency, 1517 r.level, 1518 ageSec, ageMilli, 1519 candidate, 1520 r.SSID == null ? "" : r.SSID, 1521 r.capabilities); 1522 } 1523 } 1524 pw.println(); 1525 pw.println("Locks held:"); 1526 mWifiLockManager.dump(pw); 1527 pw.println(); 1528 mWifiMulticastLockManager.dump(pw); 1529 pw.println(); 1530 mWifiStateMachine.dump(fd, pw, args); 1531 pw.println(); 1532 mWifiBackupRestore.dump(fd, pw, args); 1533 pw.println(); 1534 } 1535 } 1536 1537 @Override 1538 public boolean acquireWifiLock(IBinder binder, int lockMode, String tag, WorkSource ws) { 1539 if (mWifiLockManager.acquireWifiLock(lockMode, tag, binder, ws)) { 1540 mWifiController.sendMessage(CMD_LOCKS_CHANGED); 1541 return true; 1542 } 1543 return false; 1544 } 1545 1546 @Override 1547 public void updateWifiLockWorkSource(IBinder binder, WorkSource ws) { 1548 mWifiLockManager.updateWifiLockWorkSource(binder, ws); 1549 } 1550 1551 @Override 1552 public boolean releaseWifiLock(IBinder binder) { 1553 if (mWifiLockManager.releaseWifiLock(binder)) { 1554 mWifiController.sendMessage(CMD_LOCKS_CHANGED); 1555 return true; 1556 } 1557 return false; 1558 } 1559 1560 @Override 1561 public void initializeMulticastFiltering() { 1562 enforceMulticastChangePermission(); 1563 mWifiMulticastLockManager.initializeFiltering(); 1564 } 1565 1566 @Override 1567 public void acquireMulticastLock(IBinder binder, String tag) { 1568 enforceMulticastChangePermission(); 1569 mWifiMulticastLockManager.acquireLock(binder, tag); 1570 } 1571 1572 @Override 1573 public void releaseMulticastLock() { 1574 enforceMulticastChangePermission(); 1575 mWifiMulticastLockManager.releaseLock(); 1576 } 1577 1578 @Override 1579 public boolean isMulticastEnabled() { 1580 enforceAccessPermission(); 1581 return mWifiMulticastLockManager.isMulticastEnabled(); 1582 } 1583 1584 @Override 1585 public void enableVerboseLogging(int verbose) { 1586 enforceAccessPermission(); 1587 mFacade.setIntegerSetting( 1588 mContext, Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED, verbose); 1589 enableVerboseLoggingInternal(verbose); 1590 } 1591 1592 private void enableVerboseLoggingInternal(int verbose) { 1593 mWifiStateMachine.enableVerboseLogging(verbose); 1594 mWifiLockManager.enableVerboseLogging(verbose); 1595 mWifiMulticastLockManager.enableVerboseLogging(verbose); 1596 mWifiInjector.getWifiLastResortWatchdog().enableVerboseLogging(verbose); 1597 mWifiInjector.getWifiBackupRestore().enableVerboseLogging(verbose); 1598 } 1599 1600 @Override 1601 public int getVerboseLoggingLevel() { 1602 enforceAccessPermission(); 1603 return mFacade.getIntegerSetting( 1604 mContext, Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED, 0); 1605 } 1606 1607 @Override 1608 public void enableAggressiveHandover(int enabled) { 1609 enforceAccessPermission(); 1610 mWifiStateMachine.enableAggressiveHandover(enabled); 1611 } 1612 1613 @Override 1614 public int getAggressiveHandover() { 1615 enforceAccessPermission(); 1616 return mWifiStateMachine.getAggressiveHandover(); 1617 } 1618 1619 @Override 1620 public void setAllowScansWithTraffic(int enabled) { 1621 enforceAccessPermission(); 1622 mWifiStateMachine.setAllowScansWithTraffic(enabled); 1623 } 1624 1625 @Override 1626 public int getAllowScansWithTraffic() { 1627 enforceAccessPermission(); 1628 return mWifiStateMachine.getAllowScansWithTraffic(); 1629 } 1630 1631 @Override 1632 public boolean setEnableAutoJoinWhenAssociated(boolean enabled) { 1633 enforceChangePermission(); 1634 return mWifiStateMachine.setEnableAutoJoinWhenAssociated(enabled); 1635 } 1636 1637 @Override 1638 public boolean getEnableAutoJoinWhenAssociated() { 1639 enforceAccessPermission(); 1640 return mWifiStateMachine.getEnableAutoJoinWhenAssociated(); 1641 } 1642 1643 /* Return the Wifi Connection statistics object */ 1644 @Override 1645 public WifiConnectionStatistics getConnectionStatistics() { 1646 enforceAccessPermission(); 1647 enforceReadCredentialPermission(); 1648 if (mWifiStateMachineChannel != null) { 1649 return mWifiStateMachine.syncGetConnectionStatistics(mWifiStateMachineChannel); 1650 } else { 1651 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1652 return null; 1653 } 1654 } 1655 1656 @Override 1657 public void factoryReset() { 1658 enforceConnectivityInternalPermission(); 1659 1660 if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) { 1661 return; 1662 } 1663 1664 if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING)) { 1665 // Turn mobile hotspot off 1666 setWifiApEnabled(null, false); 1667 } 1668 1669 if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_WIFI)) { 1670 // Enable wifi 1671 setWifiEnabled(true); 1672 // Delete all Wifi SSIDs 1673 List<WifiConfiguration> networks = getConfiguredNetworks(); 1674 if (networks != null) { 1675 for (WifiConfiguration config : networks) { 1676 removeNetwork(config.networkId); 1677 } 1678 saveConfiguration(); 1679 } 1680 } 1681 } 1682 1683 /* private methods */ 1684 static boolean logAndReturnFalse(String s) { 1685 Log.d(TAG, s); 1686 return false; 1687 } 1688 1689 public static boolean isValid(WifiConfiguration config) { 1690 String validity = checkValidity(config); 1691 return validity == null || logAndReturnFalse(validity); 1692 } 1693 1694 public static boolean isValidPasspoint(WifiConfiguration config) { 1695 String validity = checkPasspointValidity(config); 1696 return validity == null || logAndReturnFalse(validity); 1697 } 1698 1699 public static String checkValidity(WifiConfiguration config) { 1700 if (config.allowedKeyManagement == null) 1701 return "allowed kmgmt"; 1702 1703 if (config.allowedKeyManagement.cardinality() > 1) { 1704 if (config.allowedKeyManagement.cardinality() != 2) { 1705 return "cardinality != 2"; 1706 } 1707 if (!config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP)) { 1708 return "not WPA_EAP"; 1709 } 1710 if ((!config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X)) 1711 && (!config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK))) { 1712 return "not PSK or 8021X"; 1713 } 1714 } 1715 return null; 1716 } 1717 1718 public static String checkPasspointValidity(WifiConfiguration config) { 1719 if (!TextUtils.isEmpty(config.FQDN)) { 1720 /* this is passpoint configuration; it must not have an SSID */ 1721 if (!TextUtils.isEmpty(config.SSID)) { 1722 return "SSID not expected for Passpoint: '" + config.SSID + 1723 "' FQDN " + toHexString(config.FQDN); 1724 } 1725 /* this is passpoint configuration; it must have a providerFriendlyName */ 1726 if (TextUtils.isEmpty(config.providerFriendlyName)) { 1727 return "no provider friendly name"; 1728 } 1729 WifiEnterpriseConfig enterpriseConfig = config.enterpriseConfig; 1730 /* this is passpoint configuration; it must have enterprise config */ 1731 if (enterpriseConfig == null 1732 || enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.NONE ) { 1733 return "no enterprise config"; 1734 } 1735 if ((enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TLS || 1736 enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TTLS || 1737 enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.PEAP) && 1738 enterpriseConfig.getCaCertificate() == null) { 1739 return "no CA certificate"; 1740 } 1741 } 1742 return null; 1743 } 1744 1745 @Override 1746 public Network getCurrentNetwork() { 1747 enforceAccessPermission(); 1748 return mWifiStateMachine.getCurrentNetwork(); 1749 } 1750 1751 public static String toHexString(String s) { 1752 if (s == null) { 1753 return "null"; 1754 } 1755 StringBuilder sb = new StringBuilder(); 1756 sb.append('\'').append(s).append('\''); 1757 for (int n = 0; n < s.length(); n++) { 1758 sb.append(String.format(" %02x", s.charAt(n) & 0xffff)); 1759 } 1760 return sb.toString(); 1761 } 1762 1763 /** 1764 * Checks that calling process has android.Manifest.permission.ACCESS_COARSE_LOCATION or 1765 * android.Manifest.permission.ACCESS_FINE_LOCATION and a corresponding app op is allowed 1766 */ 1767 private boolean checkCallerCanAccessScanResults(String callingPackage, int uid) { 1768 if (ActivityManager.checkUidPermission(Manifest.permission.ACCESS_FINE_LOCATION, uid) 1769 == PackageManager.PERMISSION_GRANTED 1770 && checkAppOppAllowed(AppOpsManager.OP_FINE_LOCATION, callingPackage, uid)) { 1771 return true; 1772 } 1773 1774 if (ActivityManager.checkUidPermission(Manifest.permission.ACCESS_COARSE_LOCATION, uid) 1775 == PackageManager.PERMISSION_GRANTED 1776 && checkAppOppAllowed(AppOpsManager.OP_COARSE_LOCATION, callingPackage, uid)) { 1777 return true; 1778 } 1779 boolean apiLevel23App = isMApp(mContext, callingPackage); 1780 // Pre-M apps running in the foreground should continue getting scan results 1781 if (!apiLevel23App && isForegroundApp(callingPackage)) { 1782 return true; 1783 } 1784 Log.e(TAG, "Permission denial: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION " 1785 + "permission to get scan results"); 1786 return false; 1787 } 1788 1789 private boolean checkAppOppAllowed(int op, String callingPackage, int uid) { 1790 return mAppOps.noteOp(op, uid, callingPackage) == AppOpsManager.MODE_ALLOWED; 1791 } 1792 1793 private static boolean isMApp(Context context, String pkgName) { 1794 try { 1795 return context.getPackageManager().getApplicationInfo(pkgName, 0) 1796 .targetSdkVersion >= Build.VERSION_CODES.M; 1797 } catch (PackageManager.NameNotFoundException e) { 1798 // In case of exception, assume M app (more strict checking) 1799 } 1800 return true; 1801 } 1802 1803 public void hideCertFromUnaffiliatedUsers(String alias) { 1804 mCertManager.hideCertFromUnaffiliatedUsers(alias); 1805 } 1806 1807 public String[] listClientCertsForCurrentUser() { 1808 return mCertManager.listClientCertsForCurrentUser(); 1809 } 1810 1811 /** 1812 * Return true if the specified package name is a foreground app. 1813 * 1814 * @param pkgName application package name. 1815 */ 1816 private boolean isForegroundApp(String pkgName) { 1817 ActivityManager am = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE); 1818 List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1); 1819 return !tasks.isEmpty() && pkgName.equals(tasks.get(0).topActivity.getPackageName()); 1820 } 1821 1822 /** 1823 * Enable/disable WifiConnectivityManager at runtime 1824 * 1825 * @param enabled true-enable; false-disable 1826 */ 1827 @Override 1828 public void enableWifiConnectivityManager(boolean enabled) { 1829 enforceConnectivityInternalPermission(); 1830 mWifiStateMachine.enableWifiConnectivityManager(enabled); 1831 } 1832 1833 /** 1834 * Retrieve the data to be backed to save the current state. 1835 * 1836 * @return Raw byte stream of the data to be backed up. 1837 */ 1838 @Override 1839 public byte[] retrieveBackupData() { 1840 enforceReadCredentialPermission(); 1841 enforceAccessPermission(); 1842 if (mWifiStateMachineChannel == null) { 1843 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1844 return null; 1845 } 1846 1847 Slog.d(TAG, "Retrieving backup data"); 1848 List<WifiConfiguration> wifiConfigurations = 1849 mWifiStateMachine.syncGetPrivilegedConfiguredNetwork(mWifiStateMachineChannel); 1850 byte[] backupData = 1851 mWifiBackupRestore.retrieveBackupDataFromConfigurations(wifiConfigurations); 1852 Slog.d(TAG, "Retrieved backup data"); 1853 return backupData; 1854 } 1855 1856 /** 1857 * Helper method to restore networks retrieved from backup data. 1858 * 1859 * @param configurations list of WifiConfiguration objects parsed from the backup data. 1860 */ 1861 private void restoreNetworks(List<WifiConfiguration> configurations) { 1862 if (configurations == null) { 1863 Slog.e(TAG, "Backup data parse failed"); 1864 return; 1865 } 1866 for (WifiConfiguration configuration : configurations) { 1867 int networkId = mWifiStateMachine.syncAddOrUpdateNetwork( 1868 mWifiStateMachineChannel, configuration); 1869 if (networkId == WifiConfiguration.INVALID_NETWORK_ID) { 1870 Slog.e(TAG, "Restore network failed: " + configuration.configKey()); 1871 continue; 1872 } 1873 // Enable all networks restored. 1874 mWifiStateMachine.syncEnableNetwork(mWifiStateMachineChannel, networkId, false); 1875 } 1876 } 1877 1878 /** 1879 * Restore state from the backed up data. 1880 * 1881 * @param data Raw byte stream of the backed up data. 1882 */ 1883 @Override 1884 public void restoreBackupData(byte[] data) { 1885 enforceChangePermission(); 1886 if (mWifiStateMachineChannel == null) { 1887 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1888 return; 1889 } 1890 1891 Slog.d(TAG, "Restoring backup data"); 1892 List<WifiConfiguration> wifiConfigurations = 1893 mWifiBackupRestore.retrieveConfigurationsFromBackupData(data); 1894 restoreNetworks(wifiConfigurations); 1895 Slog.d(TAG, "Restored backup data"); 1896 } 1897 1898 /** 1899 * Restore state from the older supplicant back up data. 1900 * The old backup data was essentially a backup of wpa_supplicant.conf & ipconfig.txt file. 1901 * 1902 * @param supplicantData Raw byte stream of wpa_supplicant.conf 1903 * @param ipConfigData Raw byte stream of ipconfig.txt 1904 */ 1905 public void restoreSupplicantBackupData(byte[] supplicantData, byte[] ipConfigData) { 1906 enforceChangePermission(); 1907 if (mWifiStateMachineChannel == null) { 1908 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1909 return; 1910 } 1911 1912 Slog.d(TAG, "Restoring supplicant backup data"); 1913 List<WifiConfiguration> wifiConfigurations = 1914 mWifiBackupRestore.retrieveConfigurationsFromSupplicantBackupData( 1915 supplicantData, ipConfigData); 1916 restoreNetworks(wifiConfigurations); 1917 Slog.d(TAG, "Restored supplicant backup data"); 1918 } 1919} 1920