WifiServiceImpl.java revision 031cdffdaf223772d4ea52569ec7a08d00013208
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.connectivity.tethering.IControlsTethering.STATE_TETHERED; 20import static com.android.server.wifi.WifiController.CMD_AIRPLANE_TOGGLED; 21import static com.android.server.wifi.WifiController.CMD_BATTERY_CHANGED; 22import static com.android.server.wifi.WifiController.CMD_EMERGENCY_CALL_STATE_CHANGED; 23import static com.android.server.wifi.WifiController.CMD_EMERGENCY_MODE_CHANGED; 24import static com.android.server.wifi.WifiController.CMD_LOCKS_CHANGED; 25import static com.android.server.wifi.WifiController.CMD_SCAN_ALWAYS_MODE_CHANGED; 26import static com.android.server.wifi.WifiController.CMD_SCREEN_OFF; 27import static com.android.server.wifi.WifiController.CMD_SCREEN_ON; 28import static com.android.server.wifi.WifiController.CMD_SET_AP; 29import static com.android.server.wifi.WifiController.CMD_USER_PRESENT; 30import static com.android.server.wifi.WifiController.CMD_WIFI_TOGGLED; 31 32import android.Manifest; 33import android.app.ActivityManager; 34import android.app.ActivityManager.RunningAppProcessInfo; 35import android.app.AppOpsManager; 36import android.bluetooth.BluetoothAdapter; 37import android.content.BroadcastReceiver; 38import android.content.Context; 39import android.content.Intent; 40import android.content.IntentFilter; 41import android.content.pm.ApplicationInfo; 42import android.content.pm.PackageManager; 43import android.content.pm.ParceledListSlice; 44import android.database.ContentObserver; 45import android.net.DhcpInfo; 46import android.net.DhcpResults; 47import android.net.IpConfiguration; 48import android.net.Network; 49import android.net.NetworkUtils; 50import android.net.StaticIpConfiguration; 51import android.net.Uri; 52import android.net.ip.IpManager; 53import android.net.wifi.IWifiManager; 54import android.net.wifi.ScanResult; 55import android.net.wifi.ScanSettings; 56import android.net.wifi.WifiActivityEnergyInfo; 57import android.net.wifi.WifiConfiguration; 58import android.net.wifi.WifiConnectionStatistics; 59import android.net.wifi.WifiEnterpriseConfig; 60import android.net.wifi.WifiInfo; 61import android.net.wifi.WifiLinkLayerStats; 62import android.net.wifi.WifiManager; 63import android.net.wifi.WifiManager.LocalOnlyHotspotCallback; 64import android.net.wifi.WifiScanner; 65import android.net.wifi.hotspot2.PasspointConfiguration; 66import android.os.AsyncTask; 67import android.os.BatteryStats; 68import android.os.Binder; 69import android.os.Build; 70import android.os.Bundle; 71import android.os.HandlerThread; 72import android.os.IBinder; 73import android.os.Looper; 74import android.os.Message; 75import android.os.Messenger; 76import android.os.PowerManager; 77import android.os.Process; 78import android.os.RemoteException; 79import android.os.ResultReceiver; 80import android.os.UserHandle; 81import android.os.UserManager; 82import android.os.WorkSource; 83import android.provider.Settings; 84import android.text.TextUtils; 85import android.util.ArrayMap; 86import android.util.ArraySet; 87import android.util.Log; 88import android.util.Slog; 89 90import com.android.internal.annotations.VisibleForTesting; 91import com.android.internal.telephony.IccCardConstants; 92import com.android.internal.telephony.PhoneConstants; 93import com.android.internal.telephony.TelephonyIntents; 94import com.android.internal.util.AsyncChannel; 95import com.android.server.wifi.util.WifiHandler; 96import com.android.server.wifi.util.WifiPermissionsUtil; 97 98import java.io.BufferedReader; 99import java.io.FileDescriptor; 100import java.io.FileNotFoundException; 101import java.io.FileReader; 102import java.io.IOException; 103import java.io.PrintWriter; 104import java.net.Inet4Address; 105import java.net.InetAddress; 106import java.security.GeneralSecurityException; 107import java.security.KeyStore; 108import java.security.cert.CertPath; 109import java.security.cert.CertPathValidator; 110import java.security.cert.CertPathValidatorException; 111import java.security.cert.CertificateFactory; 112import java.security.cert.PKIXParameters; 113import java.security.cert.X509Certificate; 114import java.util.ArrayList; 115import java.util.Arrays; 116import java.util.List; 117import java.util.concurrent.ConcurrentHashMap; 118 119/** 120 * WifiService handles remote WiFi operation requests by implementing 121 * the IWifiManager interface. 122 * 123 * @hide 124 */ 125public class WifiServiceImpl extends IWifiManager.Stub { 126 private static final String TAG = "WifiService"; 127 private static final boolean DBG = true; 128 private static final boolean VDBG = false; 129 130 // Package names for Settings, QuickSettings and QuickQuickSettings 131 private static final String SYSUI_PACKAGE_NAME = "com.android.systemui"; 132 private static final String SETTINGS_PACKAGE_NAME = "com.android.settings"; 133 134 // Dumpsys argument to enable/disable disconnect on IP reachability failures. 135 private static final String DUMP_ARG_SET_IPREACH_DISCONNECT = "set-ipreach-disconnect"; 136 private static final String DUMP_ARG_SET_IPREACH_DISCONNECT_ENABLED = "enabled"; 137 private static final String DUMP_ARG_SET_IPREACH_DISCONNECT_DISABLED = "disabled"; 138 139 // Default scan background throttling interval if not overriden in settings 140 private static final long DEFAULT_SCAN_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000; 141 142 // Apps with importance higher than this value is considered as background app. 143 private static final int BACKGROUND_IMPORTANCE_CUTOFF = 144 RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; 145 146 final WifiStateMachine mWifiStateMachine; 147 148 private final Context mContext; 149 private final FrameworkFacade mFacade; 150 private final Clock mClock; 151 private final ArraySet<String> mBackgroundThrottlePackageWhitelist = new ArraySet<>(); 152 153 private final PowerManager mPowerManager; 154 private final AppOpsManager mAppOps; 155 private final UserManager mUserManager; 156 private final ActivityManager mActivityManager; 157 private final WifiCountryCode mCountryCode; 158 private long mBackgroundThrottleInterval; 159 // Debug counter tracking scan requests sent by WifiManager 160 private int scanRequestCounter = 0; 161 162 /* Polls traffic stats and notifies clients */ 163 private WifiTrafficPoller mTrafficPoller; 164 /* Tracks the persisted states for wi-fi & airplane mode */ 165 final WifiSettingsStore mSettingsStore; 166 /* Logs connection events and some general router and scan stats */ 167 private final WifiMetrics mWifiMetrics; 168 /* Manages affiliated certificates for current user */ 169 private final WifiCertManager mCertManager; 170 171 private final WifiInjector mWifiInjector; 172 /* Backup/Restore Module */ 173 private final WifiBackupRestore mWifiBackupRestore; 174 175 // Map of package name of background scan apps and last scan timestamp. 176 private final ArrayMap<String, Long> mLastScanTimestamps; 177 178 private WifiScanner mWifiScanner; 179 private WifiLog mLog; 180 181 /** 182 * Asynchronous channel to WifiStateMachine 183 */ 184 private AsyncChannel mWifiStateMachineChannel; 185 186 private final boolean mPermissionReviewRequired; 187 private final FrameworkFacade mFrameworkFacade; 188 189 private WifiPermissionsUtil mWifiPermissionsUtil; 190 191 private final ConcurrentHashMap<String, Integer> mIfaceIpModes; 192 193 /** 194 * Handles client connections 195 */ 196 private class ClientHandler extends WifiHandler { 197 198 ClientHandler(String tag, Looper looper) { 199 super(tag, looper); 200 } 201 202 @Override 203 public void handleMessage(Message msg) { 204 super.handleMessage(msg); 205 switch (msg.what) { 206 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: { 207 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 208 if (DBG) Slog.d(TAG, "New client listening to asynchronous messages"); 209 // We track the clients by the Messenger 210 // since it is expected to be always available 211 mTrafficPoller.addClient(msg.replyTo); 212 } else { 213 Slog.e(TAG, "Client connection failure, error=" + msg.arg1); 214 } 215 break; 216 } 217 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { 218 if (msg.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) { 219 if (DBG) Slog.d(TAG, "Send failed, client connection lost"); 220 } else { 221 if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1); 222 } 223 mTrafficPoller.removeClient(msg.replyTo); 224 break; 225 } 226 case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: { 227 AsyncChannel ac = mFrameworkFacade.makeWifiAsyncChannel(TAG); 228 ac.connect(mContext, this, msg.replyTo); 229 break; 230 } 231 case WifiManager.CONNECT_NETWORK: { 232 WifiConfiguration config = (WifiConfiguration) msg.obj; 233 int networkId = msg.arg1; 234 Slog.d("WiFiServiceImpl ", "CONNECT " 235 + " nid=" + Integer.toString(networkId) 236 + " uid=" + msg.sendingUid 237 + " name=" 238 + mContext.getPackageManager().getNameForUid(msg.sendingUid)); 239 if (config != null && isValid(config)) { 240 if (DBG) Slog.d(TAG, "Connect with config " + config); 241 /* Command is forwarded to state machine */ 242 mWifiStateMachine.sendMessage(Message.obtain(msg)); 243 } else if (config == null 244 && networkId != WifiConfiguration.INVALID_NETWORK_ID) { 245 if (DBG) Slog.d(TAG, "Connect with networkId " + networkId); 246 mWifiStateMachine.sendMessage(Message.obtain(msg)); 247 } else { 248 Slog.e(TAG, "ClientHandler.handleMessage ignoring invalid msg=" + msg); 249 replyFailed(msg, WifiManager.CONNECT_NETWORK_FAILED, 250 WifiManager.INVALID_ARGS); 251 } 252 break; 253 } 254 case WifiManager.SAVE_NETWORK: { 255 WifiConfiguration config = (WifiConfiguration) msg.obj; 256 int networkId = msg.arg1; 257 Slog.d("WiFiServiceImpl ", "SAVE" 258 + " nid=" + Integer.toString(networkId) 259 + " uid=" + msg.sendingUid 260 + " name=" 261 + mContext.getPackageManager().getNameForUid(msg.sendingUid)); 262 if (config != null && isValid(config)) { 263 if (DBG) Slog.d(TAG, "Save network with config " + config); 264 /* Command is forwarded to state machine */ 265 mWifiStateMachine.sendMessage(Message.obtain(msg)); 266 } else { 267 Slog.e(TAG, "ClientHandler.handleMessage ignoring invalid msg=" + msg); 268 replyFailed(msg, WifiManager.SAVE_NETWORK_FAILED, 269 WifiManager.INVALID_ARGS); 270 } 271 break; 272 } 273 case WifiManager.FORGET_NETWORK: 274 mWifiStateMachine.sendMessage(Message.obtain(msg)); 275 break; 276 case WifiManager.START_WPS: 277 case WifiManager.CANCEL_WPS: 278 case WifiManager.DISABLE_NETWORK: 279 case WifiManager.RSSI_PKTCNT_FETCH: { 280 mWifiStateMachine.sendMessage(Message.obtain(msg)); 281 break; 282 } 283 default: { 284 Slog.d(TAG, "ClientHandler.handleMessage ignoring msg=" + msg); 285 break; 286 } 287 } 288 } 289 290 private void replyFailed(Message msg, int what, int why) { 291 if (msg.replyTo == null) return; 292 Message reply = Message.obtain(); 293 reply.what = what; 294 reply.arg1 = why; 295 try { 296 msg.replyTo.send(reply); 297 } catch (RemoteException e) { 298 // There's not much we can do if reply can't be sent! 299 } 300 } 301 } 302 private ClientHandler mClientHandler; 303 304 /** 305 * Handles interaction with WifiStateMachine 306 */ 307 private class WifiStateMachineHandler extends WifiHandler { 308 private AsyncChannel mWsmChannel; 309 310 WifiStateMachineHandler(String tag, Looper looper, AsyncChannel asyncChannel) { 311 super(tag, looper); 312 mWsmChannel = asyncChannel; 313 mWsmChannel.connect(mContext, this, mWifiStateMachine.getHandler()); 314 } 315 316 @Override 317 public void handleMessage(Message msg) { 318 super.handleMessage(msg); 319 switch (msg.what) { 320 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: { 321 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 322 mWifiStateMachineChannel = mWsmChannel; 323 } else { 324 Slog.e(TAG, "WifiStateMachine connection failure, error=" + msg.arg1); 325 mWifiStateMachineChannel = null; 326 } 327 break; 328 } 329 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { 330 Slog.e(TAG, "WifiStateMachine channel lost, msg.arg1 =" + msg.arg1); 331 mWifiStateMachineChannel = null; 332 //Re-establish connection to state machine 333 mWsmChannel.connect(mContext, this, mWifiStateMachine.getHandler()); 334 break; 335 } 336 default: { 337 Slog.d(TAG, "WifiStateMachineHandler.handleMessage ignoring msg=" + msg); 338 break; 339 } 340 } 341 } 342 } 343 344 WifiStateMachineHandler mWifiStateMachineHandler; 345 private WifiController mWifiController; 346 private final WifiLockManager mWifiLockManager; 347 private final WifiMulticastLockManager mWifiMulticastLockManager; 348 349 public WifiServiceImpl(Context context, WifiInjector wifiInjector, AsyncChannel asyncChannel) { 350 mContext = context; 351 mWifiInjector = wifiInjector; 352 mClock = wifiInjector.getClock(); 353 354 mFacade = mWifiInjector.getFrameworkFacade(); 355 mWifiMetrics = mWifiInjector.getWifiMetrics(); 356 mTrafficPoller = mWifiInjector.getWifiTrafficPoller(); 357 mUserManager = mWifiInjector.getUserManager(); 358 mCountryCode = mWifiInjector.getWifiCountryCode(); 359 mWifiStateMachine = mWifiInjector.getWifiStateMachine(); 360 mWifiStateMachine.enableRssiPolling(true); 361 mSettingsStore = mWifiInjector.getWifiSettingsStore(); 362 mPowerManager = mContext.getSystemService(PowerManager.class); 363 mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 364 mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); 365 mCertManager = mWifiInjector.getWifiCertManager(); 366 mWifiLockManager = mWifiInjector.getWifiLockManager(); 367 mWifiMulticastLockManager = mWifiInjector.getWifiMulticastLockManager(); 368 HandlerThread wifiServiceHandlerThread = mWifiInjector.getWifiServiceHandlerThread(); 369 mClientHandler = new ClientHandler(TAG, wifiServiceHandlerThread.getLooper()); 370 mWifiStateMachineHandler = new WifiStateMachineHandler(TAG, 371 wifiServiceHandlerThread.getLooper(), asyncChannel); 372 mWifiController = mWifiInjector.getWifiController(); 373 mWifiBackupRestore = mWifiInjector.getWifiBackupRestore(); 374 mPermissionReviewRequired = Build.PERMISSIONS_REVIEW_REQUIRED 375 || context.getResources().getBoolean( 376 com.android.internal.R.bool.config_permissionReviewRequired); 377 mWifiPermissionsUtil = mWifiInjector.getWifiPermissionsUtil(); 378 mLog = mWifiInjector.makeLog(TAG); 379 mFrameworkFacade = wifiInjector.getFrameworkFacade(); 380 mLastScanTimestamps = new ArrayMap<>(); 381 updateBackgroundThrottleInterval(); 382 updateBackgroundThrottlingWhitelist(); 383 mIfaceIpModes = new ConcurrentHashMap<>(); 384 enableVerboseLoggingInternal(getVerboseLoggingLevel()); 385 } 386 387 /** 388 * Provide a way for unit tests to set valid log object in the WifiHandler 389 * @param log WifiLog object to assign to the clientHandler 390 */ 391 @VisibleForTesting 392 public void setWifiHandlerLogForTest(WifiLog log) { 393 mClientHandler.setWifiLog(log); 394 } 395 396 /** 397 * Check if we are ready to start wifi. 398 * 399 * First check if we will be restarting system services to decrypt the device. If the device is 400 * not encrypted, check if Wi-Fi needs to be enabled and start if needed 401 * 402 * This function is used only at boot time. 403 */ 404 public void checkAndStartWifi() { 405 // First check if we will end up restarting WifiService 406 if (mFrameworkFacade.inStorageManagerCryptKeeperBounce()) { 407 Log.d(TAG, "Device still encrypted. Need to restart SystemServer. Do not start wifi."); 408 return; 409 } 410 411 // Check if wi-fi needs to be enabled 412 boolean wifiEnabled = mSettingsStore.isWifiToggleEnabled(); 413 Slog.i(TAG, "WifiService starting up with Wi-Fi " + 414 (wifiEnabled ? "enabled" : "disabled")); 415 416 registerForScanModeChange(); 417 registerForBackgroundThrottleChanges(); 418 mContext.registerReceiver( 419 new BroadcastReceiver() { 420 @Override 421 public void onReceive(Context context, Intent intent) { 422 if (mSettingsStore.handleAirplaneModeToggled()) { 423 mWifiController.sendMessage(CMD_AIRPLANE_TOGGLED); 424 } 425 if (mSettingsStore.isAirplaneModeOn()) { 426 Log.d(TAG, "resetting country code because Airplane mode is ON"); 427 mCountryCode.airplaneModeEnabled(); 428 } 429 } 430 }, 431 new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED)); 432 433 mContext.registerReceiver( 434 new BroadcastReceiver() { 435 @Override 436 public void onReceive(Context context, Intent intent) { 437 String state = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE); 438 if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(state)) { 439 Log.d(TAG, "resetting networks because SIM was removed"); 440 mWifiStateMachine.resetSimAuthNetworks(false); 441 Log.d(TAG, "resetting country code because SIM is removed"); 442 mCountryCode.simCardRemoved(); 443 } else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(state)) { 444 Log.d(TAG, "resetting networks because SIM was loaded"); 445 mWifiStateMachine.resetSimAuthNetworks(true); 446 } 447 } 448 }, 449 new IntentFilter(TelephonyIntents.ACTION_SIM_STATE_CHANGED)); 450 451 // Adding optimizations of only receiving broadcasts when wifi is enabled 452 // can result in race conditions when apps toggle wifi in the background 453 // without active user involvement. Always receive broadcasts. 454 registerForBroadcasts(); 455 registerForPackageOrUserRemoval(); 456 mInIdleMode = mPowerManager.isDeviceIdleMode(); 457 458 if (!mWifiStateMachine.syncInitialize(mWifiStateMachineChannel)) { 459 Log.wtf(TAG, "Failed to initialize WifiStateMachine"); 460 } 461 mWifiController.start(); 462 463 // If we are already disabled (could be due to airplane mode), avoid changing persist 464 // state here 465 if (wifiEnabled) { 466 try { 467 setWifiEnabled(mContext.getPackageName(), wifiEnabled); 468 } catch (RemoteException e) { 469 /* ignore - local call */ 470 } 471 } 472 } 473 474 public void handleUserSwitch(int userId) { 475 mWifiStateMachine.handleUserSwitch(userId); 476 } 477 478 public void handleUserUnlock(int userId) { 479 mWifiStateMachine.handleUserUnlock(userId); 480 } 481 482 public void handleUserStop(int userId) { 483 mWifiStateMachine.handleUserStop(userId); 484 } 485 486 /** 487 * see {@link android.net.wifi.WifiManager#startScan} 488 * and {@link android.net.wifi.WifiManager#startCustomizedScan} 489 * 490 * @param settings If null, use default parameter, i.e. full scan. 491 * @param workSource If null, all blame is given to the calling uid. 492 * @param packageName Package name of the app that requests wifi scan. 493 */ 494 @Override 495 public void startScan(ScanSettings settings, WorkSource workSource, String packageName) { 496 enforceChangePermission(); 497 498 mLog.trace("startScan uid=%").c(Binder.getCallingUid()).flush(); 499 // Check and throttle background apps for wifi scan. 500 if (isRequestFromBackground(packageName)) { 501 long lastScanMs = mLastScanTimestamps.getOrDefault(packageName, 0L); 502 long elapsedRealtime = mClock.getElapsedSinceBootMillis(); 503 504 if (lastScanMs != 0 && (elapsedRealtime - lastScanMs) < mBackgroundThrottleInterval) { 505 sendFailedScanBroadcast(); 506 return; 507 } 508 // Proceed with the scan request and record the time. 509 mLastScanTimestamps.put(packageName, elapsedRealtime); 510 } 511 synchronized (this) { 512 if (mWifiScanner == null) { 513 mWifiScanner = mWifiInjector.getWifiScanner(); 514 } 515 if (mInIdleMode) { 516 // Need to send an immediate scan result broadcast in case the 517 // caller is waiting for a result .. 518 519 // TODO: investigate if the logic to cancel scans when idle can move to 520 // WifiScanningServiceImpl. This will 1 - clean up WifiServiceImpl and 2 - 521 // avoid plumbing an awkward path to report a cancelled/failed scan. This will 522 // be sent directly until b/31398592 is fixed. 523 sendFailedScanBroadcast(); 524 mScanPending = true; 525 return; 526 } 527 } 528 if (settings != null) { 529 settings = new ScanSettings(settings); 530 if (!settings.isValid()) { 531 Slog.e(TAG, "invalid scan setting"); 532 return; 533 } 534 } 535 if (workSource != null) { 536 enforceWorkSourcePermission(); 537 // WifiManager currently doesn't use names, so need to clear names out of the 538 // supplied WorkSource to allow future WorkSource combining. 539 workSource.clearNames(); 540 } 541 if (workSource == null && Binder.getCallingUid() >= 0) { 542 workSource = new WorkSource(Binder.getCallingUid()); 543 } 544 mWifiStateMachine.startScan(Binder.getCallingUid(), scanRequestCounter++, 545 settings, workSource); 546 } 547 548 // Send a failed scan broadcast to indicate the current scan request failed. 549 private void sendFailedScanBroadcast() { 550 // clear calling identity to send broadcast 551 long callingIdentity = Binder.clearCallingIdentity(); 552 try { 553 Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); 554 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 555 intent.putExtra(WifiManager.EXTRA_RESULTS_UPDATED, false); 556 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 557 } finally { 558 // restore calling identity 559 Binder.restoreCallingIdentity(callingIdentity); 560 } 561 562 } 563 564 // Check if the request comes from background. 565 private boolean isRequestFromBackground(String packageName) { 566 // Requests from system or wifi are not background. 567 if (Binder.getCallingUid() == Process.SYSTEM_UID 568 || Binder.getCallingUid() == Process.WIFI_UID) { 569 return false; 570 } 571 mAppOps.checkPackage(Binder.getCallingUid(), packageName); 572 if (mBackgroundThrottlePackageWhitelist.contains(packageName)) { 573 return false; 574 } 575 576 // getPackageImportance requires PACKAGE_USAGE_STATS permission, so clearing the incoming 577 // identify so the permission check can be done on system process where wifi runs in. 578 long callingIdentity = Binder.clearCallingIdentity(); 579 try { 580 return mActivityManager.getPackageImportance(packageName) 581 > BACKGROUND_IMPORTANCE_CUTOFF; 582 } finally { 583 Binder.restoreCallingIdentity(callingIdentity); 584 } 585 } 586 587 @Override 588 public String getCurrentNetworkWpsNfcConfigurationToken() { 589 enforceConnectivityInternalPermission(); 590 mLog.trace("getCurrentNetworkWpsNfcConfigurationToken uid=%") 591 .c(Binder.getCallingUid()).flush(); 592 // TODO Add private logging for netId b/33807876 593 return mWifiStateMachine.syncGetCurrentNetworkWpsNfcConfigurationToken(); 594 } 595 596 boolean mInIdleMode; 597 boolean mScanPending; 598 599 void handleIdleModeChanged() { 600 boolean doScan = false; 601 synchronized (this) { 602 boolean idle = mPowerManager.isDeviceIdleMode(); 603 if (mInIdleMode != idle) { 604 mInIdleMode = idle; 605 if (!idle) { 606 if (mScanPending) { 607 mScanPending = false; 608 doScan = true; 609 } 610 } 611 } 612 } 613 if (doScan) { 614 // Someone requested a scan while we were idle; do a full scan now. 615 // The package name doesn't matter as the request comes from System UID. 616 startScan(null, null, ""); 617 } 618 } 619 620 private void enforceNetworkStackPermission() { 621 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.NETWORK_STACK, 622 "WifiService"); 623 } 624 625 private void enforceAccessPermission() { 626 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE, 627 "WifiService"); 628 } 629 630 private void enforceChangePermission() { 631 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE, 632 "WifiService"); 633 } 634 635 private void enforceLocationHardwarePermission() { 636 mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, 637 "LocationHardware"); 638 } 639 640 private void enforceReadCredentialPermission() { 641 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.READ_WIFI_CREDENTIAL, 642 "WifiService"); 643 } 644 645 private void enforceWorkSourcePermission() { 646 mContext.enforceCallingPermission(android.Manifest.permission.UPDATE_DEVICE_STATS, 647 "WifiService"); 648 649 } 650 651 private void enforceMulticastChangePermission() { 652 mContext.enforceCallingOrSelfPermission( 653 android.Manifest.permission.CHANGE_WIFI_MULTICAST_STATE, 654 "WifiService"); 655 } 656 657 private void enforceConnectivityInternalPermission() { 658 mContext.enforceCallingOrSelfPermission( 659 android.Manifest.permission.CONNECTIVITY_INTERNAL, 660 "ConnectivityService"); 661 } 662 663 private void enforceLocationPermission(String pkgName, int uid) { 664 mWifiPermissionsUtil.enforceLocationPermission(pkgName, uid); 665 } 666 667 /** 668 * see {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)} 669 * @param enable {@code true} to enable, {@code false} to disable. 670 * @return {@code true} if the enable/disable operation was 671 * started or is already in the queue. 672 */ 673 @Override 674 public synchronized boolean setWifiEnabled(String packageName, boolean enable) 675 throws RemoteException { 676 enforceChangePermission(); 677 Slog.d(TAG, "setWifiEnabled: " + enable + " pid=" + Binder.getCallingPid() 678 + ", uid=" + Binder.getCallingUid() + ", package=" + packageName); 679 mLog.trace("setWifiEnabled package=% uid=% enable=%").c(packageName) 680 .c(Binder.getCallingUid()).c(enable).flush(); 681 682 // If SoftAp is enabled, only Settings is allowed to toggle wifi 683 boolean apEnabled = 684 mWifiStateMachine.syncGetWifiApState() != WifiManager.WIFI_AP_STATE_DISABLED; 685 boolean isFromSettings = 686 packageName.equals(SYSUI_PACKAGE_NAME) || packageName.equals(SETTINGS_PACKAGE_NAME); 687 if (apEnabled && !isFromSettings) { 688 mLog.trace("setWifiEnabled SoftAp not disabled: only Settings can enable wifi").flush(); 689 return false; 690 } 691 692 /* 693 * Caller might not have WRITE_SECURE_SETTINGS, 694 * only CHANGE_WIFI_STATE is enforced 695 */ 696 long ident = Binder.clearCallingIdentity(); 697 try { 698 if (! mSettingsStore.handleWifiToggled(enable)) { 699 // Nothing to do if wifi cannot be toggled 700 return true; 701 } 702 } finally { 703 Binder.restoreCallingIdentity(ident); 704 } 705 706 707 if (mPermissionReviewRequired) { 708 final int wiFiEnabledState = getWifiEnabledState(); 709 if (enable) { 710 if (wiFiEnabledState == WifiManager.WIFI_STATE_DISABLING 711 || wiFiEnabledState == WifiManager.WIFI_STATE_DISABLED) { 712 if (startConsentUi(packageName, Binder.getCallingUid(), 713 WifiManager.ACTION_REQUEST_ENABLE)) { 714 return true; 715 } 716 } 717 } else if (wiFiEnabledState == WifiManager.WIFI_STATE_ENABLING 718 || wiFiEnabledState == WifiManager.WIFI_STATE_ENABLED) { 719 if (startConsentUi(packageName, Binder.getCallingUid(), 720 WifiManager.ACTION_REQUEST_DISABLE)) { 721 return true; 722 } 723 } 724 } 725 726 mWifiController.sendMessage(CMD_WIFI_TOGGLED); 727 return true; 728 } 729 730 /** 731 * see {@link WifiManager#getWifiState()} 732 * @return One of {@link WifiManager#WIFI_STATE_DISABLED}, 733 * {@link WifiManager#WIFI_STATE_DISABLING}, 734 * {@link WifiManager#WIFI_STATE_ENABLED}, 735 * {@link WifiManager#WIFI_STATE_ENABLING}, 736 * {@link WifiManager#WIFI_STATE_UNKNOWN} 737 */ 738 @Override 739 public int getWifiEnabledState() { 740 enforceAccessPermission(); 741 mLog.trace("getWifiEnabledState uid=%").c(Binder.getCallingUid()).flush(); 742 return mWifiStateMachine.syncGetWifiState(); 743 } 744 745 /** 746 * see {@link android.net.wifi.WifiManager#setWifiApEnabled(WifiConfiguration, boolean)} 747 * @param wifiConfig SSID, security and channel details as 748 * part of WifiConfiguration 749 * @param enabled true to enable and false to disable 750 */ 751 @Override 752 public void setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) { 753 enforceChangePermission(); 754 mWifiPermissionsUtil.enforceTetherChangePermission(mContext); 755 756 mLog.trace("setWifiApEnabled uid=% enable=%").c(Binder.getCallingUid()).c(enabled).flush(); 757 758 if (mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING)) { 759 throw new SecurityException("DISALLOW_CONFIG_TETHERING is enabled for this user."); 760 } 761 // null wifiConfig is a meaningful input for CMD_SET_AP 762 if (wifiConfig == null || isValid(wifiConfig)) { 763 mWifiController.sendMessage(CMD_SET_AP, enabled ? 1 : 0, 0, wifiConfig); 764 } else { 765 Slog.e(TAG, "Invalid WifiConfiguration"); 766 } 767 } 768 769 /** 770 * see {@link WifiManager#getWifiApState()} 771 * @return One of {@link WifiManager#WIFI_AP_STATE_DISABLED}, 772 * {@link WifiManager#WIFI_AP_STATE_DISABLING}, 773 * {@link WifiManager#WIFI_AP_STATE_ENABLED}, 774 * {@link WifiManager#WIFI_AP_STATE_ENABLING}, 775 * {@link WifiManager#WIFI_AP_STATE_FAILED} 776 */ 777 @Override 778 public int getWifiApEnabledState() { 779 enforceAccessPermission(); 780 mLog.trace("getWifiApEnabledState uid=%").c(Binder.getCallingUid()).flush(); 781 return mWifiStateMachine.syncGetWifiApState(); 782 } 783 784 /** 785 * see {@link android.net.wifi.WifiManager#updateInterfaceIpState(String, int)} 786 * 787 * The possible modes include: {@link WifiManager#IFACE_IP_MODE_TETHERED}, 788 * {@link WifiManager#IFACE_IP_MODE_LOCAL_ONLY}, 789 * {@link WifiManager#IFACE_IP_MODE_CONFIGURATION_ERROR} 790 * 791 * @param ifaceName String name of the updated interface 792 * @param mode new operating mode of the interface 793 * 794 * @throws SecurityException if the caller does not have permission to call update 795 */ 796 @Override 797 public void updateInterfaceIpState(String ifaceName, int mode) { 798 // NETWORK_STACK is a signature only permission. 799 enforceNetworkStackPermission(); 800 801 Integer previousMode = mIfaceIpModes.put(ifaceName, mode); 802 Slog.d(TAG, "updateInterfaceIpState: ifaceName=" + ifaceName + " mode=" + mode 803 + " previous mode= " + previousMode); 804 805 // TODO: check the mode when startLOHS comes in in case it is already active 806 // TODO: if mode == LOCAL_ONLY, trigger onStarted callbacks 807 } 808 809 /** 810 * see {@link android.net.wifi.WifiManager#startSoftAp(WifiConfiguration)} 811 * @param wifiConfig SSID, security and channel details as part of WifiConfiguration 812 * @return {@code true} if softap start was triggered 813 * @throws SecurityException if the caller does not have permission to start softap 814 */ 815 @Override 816 public boolean startSoftAp(WifiConfiguration wifiConfig) { 817 // NETWORK_STACK is a signature only permission. 818 enforceNetworkStackPermission(); 819 820 mLog.trace("startSoftAp uid=%").c(Binder.getCallingUid()).flush(); 821 822 return startSoftApInternal(wifiConfig, STATE_TETHERED); 823 } 824 825 private boolean startSoftApInternal(WifiConfiguration wifiConfig, int mode) { 826 mLog.trace("startSoftApInternal uid=% mode=%") 827 .c(Binder.getCallingUid()).c(mode).flush(); 828 829 // null wifiConfig is a meaningful input for CMD_SET_AP 830 if (wifiConfig == null || isValid(wifiConfig)) { 831 // TODO: need a way to set the mode 832 mWifiController.sendMessage(CMD_SET_AP, 1, 0, wifiConfig); 833 return true; 834 } 835 Slog.e(TAG, "Invalid WifiConfiguration"); 836 return false; 837 } 838 839 /** 840 * see {@link android.net.wifi.WifiManager#stopSoftAp()} 841 * @return {@code true} if softap stop was triggered 842 * @throws SecurityException if the caller does not have permission to stop softap 843 */ 844 @Override 845 public boolean stopSoftAp() { 846 // NETWORK_STACK is a signature only permission. 847 enforceNetworkStackPermission(); 848 849 mLog.trace("stopSoftAp uid=%").c(Binder.getCallingUid()).flush(); 850 851 // add checks here to make sure this is the proper caller - apps can't disable tethering or 852 // instances of local only hotspot that they didn't start. return false for those cases 853 854 return stopSoftApInternal(); 855 } 856 857 /** 858 * Internal method to stop softap mode. Callers of this method should have already checked 859 * proper permissions beyond the NetworkStack permission. 860 */ 861 private boolean stopSoftApInternal() { 862 mLog.trace("stopSoftApInternal uid=%").c(Binder.getCallingUid()).flush(); 863 864 mWifiController.sendMessage(CMD_SET_AP, 0, 0); 865 return true; 866 } 867 868 /** 869 * Method to start LocalOnlyHotspot. In this method, permissions, settings and modes are 870 * checked to verify that we can enter softapmode. This method returns 871 * {@link LocalOnlyHotspotCallback#REQUEST_REGISTERED} if we will attempt to start, otherwise, 872 * possible startup erros may include tethering being disallowed failure reason {@link 873 * LocalOnlyHotspotCallback#ERROR_TETHERING_DISALLOWED} or an incompatible mode failure reason 874 * {@link LocalOnlyHotspotCallback#ERROR_INCOMPATIBLE_MODE}. 875 * 876 * see {@link WifiManager#startLocalOnlyHotspot(LocalOnlyHotspotCallback)} 877 * 878 * @param messenger Messenger to send messages to the corresponding WifiManager. 879 * @param binder IBinder instance to allow cleanup if the app dies 880 * 881 * @return int return code for attempt to start LocalOnlyHotspot. 882 * 883 * @throws SecurityException if the caller does not have permission to start a Local Only 884 * Hotspot. 885 * @throws IllegalStateException if the caller attempts to start the LocalOnlyHotspot while they 886 * have an outstanding request. 887 */ 888 @Override 889 public int startLocalOnlyHotspot(Messenger messenger, IBinder binder) { 890 // first check if the caller has permission to start a local only hotspot 891 // need to check for WIFI_STATE_CHANGE and location permission 892 final int uid = Binder.getCallingUid(); 893 final String pkgName = mContext.getOpPackageName(); 894 895 enforceChangePermission(); 896 enforceLocationPermission(pkgName, uid); 897 // also need to verify that Locations services are enabled. 898 if (mSettingsStore.getLocationModeSetting(mContext) == Settings.Secure.LOCATION_MODE_OFF) { 899 throw new SecurityException("Location mode is not enabled."); 900 } 901 902 // verify that tethering is not disabled 903 if (mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING)) { 904 return LocalOnlyHotspotCallback.ERROR_TETHERING_DISALLOWED; 905 } 906 907 mLog.trace("startLocalOnlyHotspot uid=%").c(uid).flush(); 908 909 // check current mode to see if we can start localOnlyHotspot 910 boolean apDisabled = 911 mWifiStateMachine.syncGetWifiApState() == WifiManager.WIFI_AP_STATE_DISABLED; 912 if (!apDisabled) { 913 // Tethering is enabled, cannot start LocalOnlyHotspot 914 mLog.trace("Cannot start localOnlyHotspot when WiFi Tethering is active."); 915 return LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE; 916 } 917 918 throw new UnsupportedOperationException("LocalOnlyHotspot is still in development"); 919 } 920 921 /** 922 * see {@link WifiManager#stopLocalOnlyHotspot()} 923 * 924 * @throws SecurityException if the caller does not have permission to stop a Local Only 925 * Hotspot. 926 */ 927 @Override 928 public void stopLocalOnlyHotspot() { 929 // first check if the caller has permission to stop a local only hotspot 930 enforceChangePermission(); 931 final int uid = Binder.getCallingUid(); 932 933 mLog.trace("stopLocalOnlyHotspot uid=%").c(uid).flush(); 934 935 throw new UnsupportedOperationException("LocalOnlyHotspot is still in development"); 936 } 937 938 /** 939 * see {@link WifiManager#watchLocalOnlyHotspot(LocalOnlyHotspotObserver)} 940 * 941 * @param messenger Messenger to send messages to the corresponding WifiManager. 942 * @param binder IBinder instance to allow cleanup if the app dies 943 * 944 * @throws SecurityException if the caller does not have permission to watch Local Only Hotspot 945 * status updates. 946 * @throws IllegalStateException if the caller attempts to watch LocalOnlyHotspot updates with 947 * an existing subscription. 948 */ 949 @Override 950 public void startWatchLocalOnlyHotspot(Messenger messenger, IBinder binder) { 951 throw new UnsupportedOperationException("LocalOnlyHotspot is still in development"); 952 } 953 954 /** 955 * see {@link WifiManager#unregisterLocalOnlyHotspotObserver()} 956 */ 957 @Override 958 public void stopWatchLocalOnlyHotspot() { 959 throw new UnsupportedOperationException("LocalOnlyHotspot is still in development"); 960 } 961 962 /** 963 * see {@link WifiManager#getWifiApConfiguration()} 964 * @return soft access point configuration 965 * @throws SecurityException if the caller does not have permission to retrieve the softap 966 * config 967 */ 968 @Override 969 public WifiConfiguration getWifiApConfiguration() { 970 enforceAccessPermission(); 971 int uid = Binder.getCallingUid(); 972 // only allow Settings UI to get the saved SoftApConfig 973 if (!mWifiPermissionsUtil.checkConfigOverridePermission(uid)) { 974 // random apps should not be allowed to read the user specified config 975 throw new SecurityException("App not allowed to read or update stored WiFi Ap config " 976 + "(uid = " + uid + ")"); 977 } 978 mLog.trace("getWifiApConfiguration uid=%").c(uid).flush(); 979 return mWifiStateMachine.syncGetWifiApConfiguration(); 980 } 981 982 /** 983 * see {@link WifiManager#setWifiApConfiguration(WifiConfiguration)} 984 * @param wifiConfig WifiConfiguration details for soft access point 985 * @throws SecurityException if the caller does not have permission to write the sotap config 986 */ 987 @Override 988 public void setWifiApConfiguration(WifiConfiguration wifiConfig) { 989 enforceChangePermission(); 990 int uid = Binder.getCallingUid(); 991 // only allow Settings UI to write the stored SoftApConfig 992 if (!mWifiPermissionsUtil.checkConfigOverridePermission(uid)) { 993 // random apps should not be allowed to read the user specified config 994 throw new SecurityException("App not allowed to read or update stored WiFi AP config " 995 + "(uid = " + uid + ")"); 996 } 997 mLog.trace("setWifiApConfiguration uid=%").c(uid).flush(); 998 if (wifiConfig == null) 999 return; 1000 if (isValid(wifiConfig)) { 1001 mWifiStateMachine.setWifiApConfiguration(wifiConfig); 1002 } else { 1003 Slog.e(TAG, "Invalid WifiConfiguration"); 1004 } 1005 } 1006 1007 /** 1008 * see {@link android.net.wifi.WifiManager#isScanAlwaysAvailable()} 1009 */ 1010 @Override 1011 public boolean isScanAlwaysAvailable() { 1012 enforceAccessPermission(); 1013 mLog.trace("isScanAlwaysAvailable uid=%").c(Binder.getCallingUid()).flush(); 1014 return mSettingsStore.isScanAlwaysAvailable(); 1015 } 1016 1017 /** 1018 * see {@link android.net.wifi.WifiManager#disconnect()} 1019 */ 1020 @Override 1021 public void disconnect() { 1022 enforceChangePermission(); 1023 mLog.trace("disconnect uid=%").c(Binder.getCallingUid()).flush(); 1024 mWifiStateMachine.disconnectCommand(); 1025 } 1026 1027 /** 1028 * see {@link android.net.wifi.WifiManager#reconnect()} 1029 */ 1030 @Override 1031 public void reconnect() { 1032 enforceChangePermission(); 1033 mLog.trace("reconnect uid=%").c(Binder.getCallingUid()).flush(); 1034 mWifiStateMachine.reconnectCommand(); 1035 } 1036 1037 /** 1038 * see {@link android.net.wifi.WifiManager#reassociate()} 1039 */ 1040 @Override 1041 public void reassociate() { 1042 enforceChangePermission(); 1043 mLog.trace("reassociate uid=%").c(Binder.getCallingUid()).flush(); 1044 mWifiStateMachine.reassociateCommand(); 1045 } 1046 1047 /** 1048 * see {@link android.net.wifi.WifiManager#getSupportedFeatures} 1049 */ 1050 @Override 1051 public int getSupportedFeatures() { 1052 enforceAccessPermission(); 1053 mLog.trace("getSupportedFeatures uid=%").c(Binder.getCallingUid()).flush(); 1054 if (mWifiStateMachineChannel != null) { 1055 return mWifiStateMachine.syncGetSupportedFeatures(mWifiStateMachineChannel); 1056 } else { 1057 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1058 return 0; 1059 } 1060 } 1061 1062 @Override 1063 public void requestActivityInfo(ResultReceiver result) { 1064 Bundle bundle = new Bundle(); 1065 mLog.trace("requestActivityInfo uid=%").c(Binder.getCallingUid()).flush(); 1066 bundle.putParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY, reportActivityInfo()); 1067 result.send(0, bundle); 1068 } 1069 1070 /** 1071 * see {@link android.net.wifi.WifiManager#getControllerActivityEnergyInfo(int)} 1072 */ 1073 @Override 1074 public WifiActivityEnergyInfo reportActivityInfo() { 1075 enforceAccessPermission(); 1076 mLog.trace("reportActivityInfo uid=%").c(Binder.getCallingUid()).flush(); 1077 if ((getSupportedFeatures() & WifiManager.WIFI_FEATURE_LINK_LAYER_STATS) == 0) { 1078 return null; 1079 } 1080 WifiLinkLayerStats stats; 1081 WifiActivityEnergyInfo energyInfo = null; 1082 if (mWifiStateMachineChannel != null) { 1083 stats = mWifiStateMachine.syncGetLinkLayerStats(mWifiStateMachineChannel); 1084 if (stats != null) { 1085 final long rxIdleCurrent = mContext.getResources().getInteger( 1086 com.android.internal.R.integer.config_wifi_idle_receive_cur_ma); 1087 final long rxCurrent = mContext.getResources().getInteger( 1088 com.android.internal.R.integer.config_wifi_active_rx_cur_ma); 1089 final long txCurrent = mContext.getResources().getInteger( 1090 com.android.internal.R.integer.config_wifi_tx_cur_ma); 1091 final double voltage = mContext.getResources().getInteger( 1092 com.android.internal.R.integer.config_wifi_operating_voltage_mv) 1093 / 1000.0; 1094 1095 final long rxIdleTime = stats.on_time - stats.tx_time - stats.rx_time; 1096 final long[] txTimePerLevel; 1097 if (stats.tx_time_per_level != null) { 1098 txTimePerLevel = new long[stats.tx_time_per_level.length]; 1099 for (int i = 0; i < txTimePerLevel.length; i++) { 1100 txTimePerLevel[i] = stats.tx_time_per_level[i]; 1101 // TODO(b/27227497): Need to read the power consumed per level from config 1102 } 1103 } else { 1104 // This will happen if the HAL get link layer API returned null. 1105 txTimePerLevel = new long[0]; 1106 } 1107 final long energyUsed = (long)((stats.tx_time * txCurrent + 1108 stats.rx_time * rxCurrent + 1109 rxIdleTime * rxIdleCurrent) * voltage); 1110 if (VDBG || rxIdleTime < 0 || stats.on_time < 0 || stats.tx_time < 0 || 1111 stats.rx_time < 0 || energyUsed < 0) { 1112 StringBuilder sb = new StringBuilder(); 1113 sb.append(" rxIdleCur=" + rxIdleCurrent); 1114 sb.append(" rxCur=" + rxCurrent); 1115 sb.append(" txCur=" + txCurrent); 1116 sb.append(" voltage=" + voltage); 1117 sb.append(" on_time=" + stats.on_time); 1118 sb.append(" tx_time=" + stats.tx_time); 1119 sb.append(" tx_time_per_level=" + Arrays.toString(txTimePerLevel)); 1120 sb.append(" rx_time=" + stats.rx_time); 1121 sb.append(" rxIdleTime=" + rxIdleTime); 1122 sb.append(" energy=" + energyUsed); 1123 Log.d(TAG, " reportActivityInfo: " + sb.toString()); 1124 } 1125 1126 // Convert the LinkLayerStats into EnergyActivity 1127 energyInfo = new WifiActivityEnergyInfo(mClock.getElapsedSinceBootMillis(), 1128 WifiActivityEnergyInfo.STACK_STATE_STATE_IDLE, stats.tx_time, 1129 txTimePerLevel, stats.rx_time, rxIdleTime, energyUsed); 1130 } 1131 if (energyInfo != null && energyInfo.isValid()) { 1132 return energyInfo; 1133 } else { 1134 return null; 1135 } 1136 } else { 1137 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1138 return null; 1139 } 1140 } 1141 1142 /** 1143 * see {@link android.net.wifi.WifiManager#getConfiguredNetworks()} 1144 * @return the list of configured networks 1145 */ 1146 @Override 1147 public ParceledListSlice<WifiConfiguration> getConfiguredNetworks() { 1148 enforceAccessPermission(); 1149 mLog.trace("getConfiguredNetworks uid=%").c(Binder.getCallingUid()).flush(); 1150 if (mWifiStateMachineChannel != null) { 1151 List<WifiConfiguration> configs = mWifiStateMachine.syncGetConfiguredNetworks( 1152 Binder.getCallingUid(), mWifiStateMachineChannel); 1153 if (configs != null) { 1154 return new ParceledListSlice<WifiConfiguration>(configs); 1155 } 1156 } else { 1157 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1158 } 1159 return null; 1160 } 1161 1162 /** 1163 * see {@link android.net.wifi.WifiManager#getPrivilegedConfiguredNetworks()} 1164 * @return the list of configured networks with real preSharedKey 1165 */ 1166 @Override 1167 public ParceledListSlice<WifiConfiguration> getPrivilegedConfiguredNetworks() { 1168 enforceReadCredentialPermission(); 1169 enforceAccessPermission(); 1170 mLog.trace("getPrivilegedConfiguredNetworks uid=%").c(Binder.getCallingUid()).flush(); 1171 if (mWifiStateMachineChannel != null) { 1172 List<WifiConfiguration> configs = 1173 mWifiStateMachine.syncGetPrivilegedConfiguredNetwork(mWifiStateMachineChannel); 1174 if (configs != null) { 1175 return new ParceledListSlice<WifiConfiguration>(configs); 1176 } 1177 } else { 1178 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1179 } 1180 return null; 1181 } 1182 1183 /** 1184 * Returns a WifiConfiguration for a Passpoint network matching this ScanResult. 1185 * 1186 * @param scanResult scanResult that represents the BSSID 1187 * @return {@link WifiConfiguration} that matches this BSSID or null 1188 */ 1189 @Override 1190 public WifiConfiguration getMatchingWifiConfig(ScanResult scanResult) { 1191 enforceAccessPermission(); 1192 mLog.trace("getMatchingWifiConfig uid=%").c(Binder.getCallingUid()).flush(); 1193 if (!mContext.getResources().getBoolean( 1194 com.android.internal.R.bool.config_wifi_hotspot2_enabled)) { 1195 throw new UnsupportedOperationException("Passpoint not enabled"); 1196 } 1197 return mWifiStateMachine.syncGetMatchingWifiConfig(scanResult, mWifiStateMachineChannel); 1198 } 1199 1200 /** 1201 * see {@link android.net.wifi.WifiManager#addOrUpdateNetwork(WifiConfiguration)} 1202 * @return the supplicant-assigned identifier for the new or updated 1203 * network if the operation succeeds, or {@code -1} if it fails 1204 */ 1205 @Override 1206 public int addOrUpdateNetwork(WifiConfiguration config) { 1207 enforceChangePermission(); 1208 mLog.trace("addOrUpdateNetwork uid=%").c(Binder.getCallingUid()).flush(); 1209 if (isValid(config) && isValidPasspoint(config)) { 1210 1211 WifiEnterpriseConfig enterpriseConfig = config.enterpriseConfig; 1212 1213 if (config.isPasspoint() && 1214 (enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TLS || 1215 enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TTLS)) { 1216 if (config.updateIdentifier != null) { 1217 enforceAccessPermission(); 1218 } 1219 else { 1220 try { 1221 verifyCert(enterpriseConfig.getCaCertificate()); 1222 } catch (CertPathValidatorException cpve) { 1223 Slog.e(TAG, "CA Cert " + 1224 enterpriseConfig.getCaCertificate().getSubjectX500Principal() + 1225 " untrusted: " + cpve.getMessage()); 1226 return -1; 1227 } catch (GeneralSecurityException | IOException e) { 1228 Slog.e(TAG, "Failed to verify certificate" + 1229 enterpriseConfig.getCaCertificate().getSubjectX500Principal() + 1230 ": " + e); 1231 return -1; 1232 } 1233 } 1234 } 1235 1236 //TODO: pass the Uid the WifiStateMachine as a message parameter 1237 Slog.i("addOrUpdateNetwork", " uid = " + Integer.toString(Binder.getCallingUid()) 1238 + " SSID " + config.SSID 1239 + " nid=" + Integer.toString(config.networkId)); 1240 if (config.networkId == WifiConfiguration.INVALID_NETWORK_ID) { 1241 config.creatorUid = Binder.getCallingUid(); 1242 } else { 1243 config.lastUpdateUid = Binder.getCallingUid(); 1244 } 1245 if (mWifiStateMachineChannel != null) { 1246 return mWifiStateMachine.syncAddOrUpdateNetwork(mWifiStateMachineChannel, config); 1247 } else { 1248 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1249 return -1; 1250 } 1251 } else { 1252 Slog.e(TAG, "bad network configuration"); 1253 return -1; 1254 } 1255 } 1256 1257 public static void verifyCert(X509Certificate caCert) 1258 throws GeneralSecurityException, IOException { 1259 CertificateFactory factory = CertificateFactory.getInstance("X.509"); 1260 CertPathValidator validator = 1261 CertPathValidator.getInstance(CertPathValidator.getDefaultType()); 1262 CertPath path = factory.generateCertPath( 1263 Arrays.asList(caCert)); 1264 KeyStore ks = KeyStore.getInstance("AndroidCAStore"); 1265 ks.load(null, null); 1266 PKIXParameters params = new PKIXParameters(ks); 1267 params.setRevocationEnabled(false); 1268 validator.validate(path, params); 1269 } 1270 1271 /** 1272 * See {@link android.net.wifi.WifiManager#removeNetwork(int)} 1273 * @param netId the integer that identifies the network configuration 1274 * to the supplicant 1275 * @return {@code true} if the operation succeeded 1276 */ 1277 @Override 1278 public boolean removeNetwork(int netId) { 1279 enforceChangePermission(); 1280 mLog.trace("removeNetwork uid=%").c(Binder.getCallingUid()).flush(); 1281 // TODO Add private logging for netId b/33807876 1282 if (mWifiStateMachineChannel != null) { 1283 return mWifiStateMachine.syncRemoveNetwork(mWifiStateMachineChannel, netId); 1284 } else { 1285 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1286 return false; 1287 } 1288 } 1289 1290 /** 1291 * See {@link android.net.wifi.WifiManager#enableNetwork(int, boolean)} 1292 * @param netId the integer that identifies the network configuration 1293 * to the supplicant 1294 * @param disableOthers if true, disable all other networks. 1295 * @return {@code true} if the operation succeeded 1296 */ 1297 @Override 1298 public boolean enableNetwork(int netId, boolean disableOthers) { 1299 enforceChangePermission(); 1300 // TODO b/33807876 Log netId 1301 mLog.trace("enableNetwork uid=% disableOthers=%") 1302 .c(Binder.getCallingUid()) 1303 .c(disableOthers).flush(); 1304 1305 if (mWifiStateMachineChannel != null) { 1306 return mWifiStateMachine.syncEnableNetwork(mWifiStateMachineChannel, netId, 1307 disableOthers); 1308 } else { 1309 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1310 return false; 1311 } 1312 } 1313 1314 /** 1315 * See {@link android.net.wifi.WifiManager#disableNetwork(int)} 1316 * @param netId the integer that identifies the network configuration 1317 * to the supplicant 1318 * @return {@code true} if the operation succeeded 1319 */ 1320 @Override 1321 public boolean disableNetwork(int netId) { 1322 enforceChangePermission(); 1323 // TODO b/33807876 Log netId 1324 mLog.trace("disableNetwork uid=%").c(Binder.getCallingUid()).flush(); 1325 1326 if (mWifiStateMachineChannel != null) { 1327 return mWifiStateMachine.syncDisableNetwork(mWifiStateMachineChannel, netId); 1328 } else { 1329 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1330 return false; 1331 } 1332 } 1333 1334 /** 1335 * See {@link android.net.wifi.WifiManager#getConnectionInfo()} 1336 * @return the Wi-Fi information, contained in {@link WifiInfo}. 1337 */ 1338 @Override 1339 public WifiInfo getConnectionInfo() { 1340 enforceAccessPermission(); 1341 mLog.trace("getConnectionInfo uid=%").c(Binder.getCallingUid()).flush(); 1342 /* 1343 * Make sure we have the latest information, by sending 1344 * a status request to the supplicant. 1345 */ 1346 return mWifiStateMachine.syncRequestConnectionInfo(); 1347 } 1348 1349 /** 1350 * Return the results of the most recent access point scan, in the form of 1351 * a list of {@link ScanResult} objects. 1352 * @return the list of results 1353 */ 1354 @Override 1355 public List<ScanResult> getScanResults(String callingPackage) { 1356 enforceAccessPermission(); 1357 int uid = Binder.getCallingUid(); 1358 long ident = Binder.clearCallingIdentity(); 1359 try { 1360 if (!mWifiPermissionsUtil.canAccessScanResults(callingPackage, 1361 uid, Build.VERSION_CODES.M)) { 1362 return new ArrayList<ScanResult>(); 1363 } 1364 if (mWifiScanner == null) { 1365 mWifiScanner = mWifiInjector.getWifiScanner(); 1366 } 1367 return mWifiScanner.getSingleScanResults(); 1368 } finally { 1369 Binder.restoreCallingIdentity(ident); 1370 } 1371 } 1372 1373 /** 1374 * Add or update a Passpoint configuration. 1375 * 1376 * @param config The Passpoint configuration to be added 1377 * @return true on success or false on failure 1378 */ 1379 @Override 1380 public boolean addOrUpdatePasspointConfiguration(PasspointConfiguration config) { 1381 enforceChangePermission(); 1382 mLog.trace("addorUpdatePasspointConfiguration uid=%").c(Binder.getCallingUid()).flush(); 1383 if (!mContext.getResources().getBoolean( 1384 com.android.internal.R.bool.config_wifi_hotspot2_enabled)) { 1385 throw new UnsupportedOperationException("Passpoint not enabled"); 1386 } 1387 return mWifiStateMachine.syncAddOrUpdatePasspointConfig(mWifiStateMachineChannel, config, 1388 Binder.getCallingUid()); 1389 } 1390 1391 /** 1392 * Remove the Passpoint configuration identified by its FQDN (Fully Qualified Domain Name). 1393 * 1394 * @param fqdn The FQDN of the Passpoint configuration to be removed 1395 * @return true on success or false on failure 1396 */ 1397 @Override 1398 public boolean removePasspointConfiguration(String fqdn) { 1399 enforceChangePermission(); 1400 mLog.trace("removePasspointConfiguration uid=%").c(Binder.getCallingUid()).flush(); 1401 if (!mContext.getResources().getBoolean( 1402 com.android.internal.R.bool.config_wifi_hotspot2_enabled)) { 1403 throw new UnsupportedOperationException("Passpoint not enabled"); 1404 } 1405 return mWifiStateMachine.syncRemovePasspointConfig(mWifiStateMachineChannel, fqdn); 1406 } 1407 1408 /** 1409 * Return the list of the installed Passpoint configurations. 1410 * 1411 * An empty list will be returned when no configuration is installed. 1412 * 1413 * @return A list of {@link PasspointConfiguration} 1414 */ 1415 @Override 1416 public List<PasspointConfiguration> getPasspointConfigurations() { 1417 enforceAccessPermission(); 1418 mLog.trace("getPasspointConfigurations uid=%").c(Binder.getCallingUid()).flush(); 1419 if (!mContext.getResources().getBoolean( 1420 com.android.internal.R.bool.config_wifi_hotspot2_enabled)) { 1421 throw new UnsupportedOperationException("Passpoint not enabled"); 1422 } 1423 return mWifiStateMachine.syncGetPasspointConfigs(mWifiStateMachineChannel); 1424 } 1425 1426 /** 1427 * Query for a Hotspot 2.0 release 2 OSU icon 1428 * @param bssid The BSSID of the AP 1429 * @param fileName Icon file name 1430 */ 1431 @Override 1432 public void queryPasspointIcon(long bssid, String fileName) { 1433 enforceAccessPermission(); 1434 mLog.trace("queryPasspointIcon uid=%").c(Binder.getCallingUid()).flush(); 1435 if (!mContext.getResources().getBoolean( 1436 com.android.internal.R.bool.config_wifi_hotspot2_enabled)) { 1437 throw new UnsupportedOperationException("Passpoint not enabled"); 1438 } 1439 mWifiStateMachine.syncQueryPasspointIcon(mWifiStateMachineChannel, bssid, fileName); 1440 } 1441 1442 /** 1443 * Match the currently associated network against the SP matching the given FQDN 1444 * @param fqdn FQDN of the SP 1445 * @return ordinal [HomeProvider, RoamingProvider, Incomplete, None, Declined] 1446 */ 1447 @Override 1448 public int matchProviderWithCurrentNetwork(String fqdn) { 1449 mLog.trace("matchProviderWithCurrentNetwork uid=%").c(Binder.getCallingUid()).flush(); 1450 return mWifiStateMachine.matchProviderWithCurrentNetwork(mWifiStateMachineChannel, fqdn); 1451 } 1452 1453 /** 1454 * Deauthenticate and set the re-authentication hold off time for the current network 1455 * @param holdoff hold off time in milliseconds 1456 * @param ess set if the hold off pertains to an ESS rather than a BSS 1457 */ 1458 @Override 1459 public void deauthenticateNetwork(long holdoff, boolean ess) { 1460 mLog.trace("deauthenticateNetwork uid=%").c(Binder.getCallingUid()).flush(); 1461 mWifiStateMachine.deauthenticateNetwork(mWifiStateMachineChannel, holdoff, ess); 1462 } 1463 1464 /** 1465 * Tell the supplicant to persist the current list of configured networks. 1466 * @return {@code true} if the operation succeeded 1467 * 1468 * TODO: deprecate this 1469 */ 1470 @Override 1471 public boolean saveConfiguration() { 1472 enforceChangePermission(); 1473 mLog.trace("saveConfiguration uid=%").c(Binder.getCallingUid()).flush(); 1474 if (mWifiStateMachineChannel != null) { 1475 return mWifiStateMachine.syncSaveConfig(mWifiStateMachineChannel); 1476 } else { 1477 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1478 return false; 1479 } 1480 } 1481 1482 /** 1483 * Set the country code 1484 * @param countryCode ISO 3166 country code. 1485 * @param persist {@code true} if the setting should be remembered. 1486 * 1487 * The persist behavior exists so that wifi can fall back to the last 1488 * persisted country code on a restart, when the locale information is 1489 * not available from telephony. 1490 */ 1491 @Override 1492 public void setCountryCode(String countryCode, boolean persist) { 1493 Slog.i(TAG, "WifiService trying to set country code to " + countryCode + 1494 " with persist set to " + persist); 1495 enforceConnectivityInternalPermission(); 1496 mLog.trace("setCountryCode uid=%").c(Binder.getCallingUid()).flush(); 1497 final long token = Binder.clearCallingIdentity(); 1498 mCountryCode.setCountryCode(countryCode); 1499 Binder.restoreCallingIdentity(token); 1500 } 1501 1502 /** 1503 * Get the country code 1504 * @return Get the best choice country code for wifi, regardless of if it was set or 1505 * not. 1506 * Returns null when there is no country code available. 1507 */ 1508 @Override 1509 public String getCountryCode() { 1510 enforceConnectivityInternalPermission(); 1511 mLog.trace("getCountryCode uid=%").c(Binder.getCallingUid()).flush(); 1512 String country = mCountryCode.getCountryCode(); 1513 return country; 1514 } 1515 1516 @Override 1517 public boolean isDualBandSupported() { 1518 //TODO: Should move towards adding a driver API that checks at runtime 1519 mLog.trace("isDualBandSupported uid=%").c(Binder.getCallingUid()).flush(); 1520 return mContext.getResources().getBoolean( 1521 com.android.internal.R.bool.config_wifi_dual_band_support); 1522 } 1523 1524 /** 1525 * Return the DHCP-assigned addresses from the last successful DHCP request, 1526 * if any. 1527 * @return the DHCP information 1528 * @deprecated 1529 */ 1530 @Override 1531 @Deprecated 1532 public DhcpInfo getDhcpInfo() { 1533 enforceAccessPermission(); 1534 mLog.trace("getDhcpInfo uid=%").c(Binder.getCallingUid()).flush(); 1535 DhcpResults dhcpResults = mWifiStateMachine.syncGetDhcpResults(); 1536 1537 DhcpInfo info = new DhcpInfo(); 1538 1539 if (dhcpResults.ipAddress != null && 1540 dhcpResults.ipAddress.getAddress() instanceof Inet4Address) { 1541 info.ipAddress = NetworkUtils.inetAddressToInt((Inet4Address) dhcpResults.ipAddress.getAddress()); 1542 } 1543 1544 if (dhcpResults.gateway != null) { 1545 info.gateway = NetworkUtils.inetAddressToInt((Inet4Address) dhcpResults.gateway); 1546 } 1547 1548 int dnsFound = 0; 1549 for (InetAddress dns : dhcpResults.dnsServers) { 1550 if (dns instanceof Inet4Address) { 1551 if (dnsFound == 0) { 1552 info.dns1 = NetworkUtils.inetAddressToInt((Inet4Address)dns); 1553 } else { 1554 info.dns2 = NetworkUtils.inetAddressToInt((Inet4Address)dns); 1555 } 1556 if (++dnsFound > 1) break; 1557 } 1558 } 1559 Inet4Address serverAddress = dhcpResults.serverAddress; 1560 if (serverAddress != null) { 1561 info.serverAddress = NetworkUtils.inetAddressToInt(serverAddress); 1562 } 1563 info.leaseDuration = dhcpResults.leaseDuration; 1564 1565 return info; 1566 } 1567 1568 /** 1569 * enable TDLS for the local NIC to remote NIC 1570 * The APPs don't know the remote MAC address to identify NIC though, 1571 * so we need to do additional work to find it from remote IP address 1572 */ 1573 1574 class TdlsTaskParams { 1575 public String remoteIpAddress; 1576 public boolean enable; 1577 } 1578 1579 class TdlsTask extends AsyncTask<TdlsTaskParams, Integer, Integer> { 1580 @Override 1581 protected Integer doInBackground(TdlsTaskParams... params) { 1582 1583 // Retrieve parameters for the call 1584 TdlsTaskParams param = params[0]; 1585 String remoteIpAddress = param.remoteIpAddress.trim(); 1586 boolean enable = param.enable; 1587 1588 // Get MAC address of Remote IP 1589 String macAddress = null; 1590 1591 BufferedReader reader = null; 1592 1593 try { 1594 reader = new BufferedReader(new FileReader("/proc/net/arp")); 1595 1596 // Skip over the line bearing colum titles 1597 String line = reader.readLine(); 1598 1599 while ((line = reader.readLine()) != null) { 1600 String[] tokens = line.split("[ ]+"); 1601 if (tokens.length < 6) { 1602 continue; 1603 } 1604 1605 // ARP column format is 1606 // Address HWType HWAddress Flags Mask IFace 1607 String ip = tokens[0]; 1608 String mac = tokens[3]; 1609 1610 if (remoteIpAddress.equals(ip)) { 1611 macAddress = mac; 1612 break; 1613 } 1614 } 1615 1616 if (macAddress == null) { 1617 Slog.w(TAG, "Did not find remoteAddress {" + remoteIpAddress + "} in " + 1618 "/proc/net/arp"); 1619 } else { 1620 enableTdlsWithMacAddress(macAddress, enable); 1621 } 1622 1623 } catch (FileNotFoundException e) { 1624 Slog.e(TAG, "Could not open /proc/net/arp to lookup mac address"); 1625 } catch (IOException e) { 1626 Slog.e(TAG, "Could not read /proc/net/arp to lookup mac address"); 1627 } finally { 1628 try { 1629 if (reader != null) { 1630 reader.close(); 1631 } 1632 } 1633 catch (IOException e) { 1634 // Do nothing 1635 } 1636 } 1637 1638 return 0; 1639 } 1640 } 1641 1642 @Override 1643 public void enableTdls(String remoteAddress, boolean enable) { 1644 if (remoteAddress == null) { 1645 throw new IllegalArgumentException("remoteAddress cannot be null"); 1646 } 1647 mLog.trace("enableTdls uid=% enable=%").c(Binder.getCallingUid()).c(enable).flush(); 1648 TdlsTaskParams params = new TdlsTaskParams(); 1649 params.remoteIpAddress = remoteAddress; 1650 params.enable = enable; 1651 new TdlsTask().execute(params); 1652 } 1653 1654 1655 @Override 1656 public void enableTdlsWithMacAddress(String remoteMacAddress, boolean enable) { 1657 mLog.trace("enableTdlsWithMacAddress uid=% enable=%") 1658 .c(Binder.getCallingUid()) 1659 .c(enable) 1660 .flush(); 1661 if (remoteMacAddress == null) { 1662 throw new IllegalArgumentException("remoteMacAddress cannot be null"); 1663 } 1664 1665 mWifiStateMachine.enableTdls(remoteMacAddress, enable); 1666 } 1667 1668 /** 1669 * Get a reference to handler. This is used by a client to establish 1670 * an AsyncChannel communication with WifiService 1671 */ 1672 @Override 1673 public Messenger getWifiServiceMessenger() { 1674 enforceAccessPermission(); 1675 enforceChangePermission(); 1676 mLog.trace("getWifiServiceMessenger uid=%").c(Binder.getCallingUid()).flush(); 1677 return new Messenger(mClientHandler); 1678 } 1679 1680 /** 1681 * Disable an ephemeral network, i.e. network that is created thru a WiFi Scorer 1682 */ 1683 @Override 1684 public void disableEphemeralNetwork(String SSID) { 1685 enforceAccessPermission(); 1686 enforceChangePermission(); 1687 mLog.trace("disableEphemeralNetwork uid=%").c(Binder.getCallingUid()).flush(); 1688 mWifiStateMachine.disableEphemeralNetwork(SSID); 1689 } 1690 1691 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 1692 @Override 1693 public void onReceive(Context context, Intent intent) { 1694 String action = intent.getAction(); 1695 if (action.equals(Intent.ACTION_SCREEN_ON)) { 1696 mWifiController.sendMessage(CMD_SCREEN_ON); 1697 } else if (action.equals(Intent.ACTION_USER_PRESENT)) { 1698 mWifiController.sendMessage(CMD_USER_PRESENT); 1699 } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { 1700 mWifiController.sendMessage(CMD_SCREEN_OFF); 1701 } else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { 1702 int pluggedType = intent.getIntExtra("plugged", 0); 1703 mWifiController.sendMessage(CMD_BATTERY_CHANGED, pluggedType, 0, null); 1704 } else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) { 1705 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, 1706 BluetoothAdapter.STATE_DISCONNECTED); 1707 mWifiStateMachine.sendBluetoothAdapterStateChange(state); 1708 } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) { 1709 boolean emergencyMode = intent.getBooleanExtra("phoneinECMState", false); 1710 mWifiController.sendMessage(CMD_EMERGENCY_MODE_CHANGED, emergencyMode ? 1 : 0, 0); 1711 } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED)) { 1712 boolean inCall = intent.getBooleanExtra(PhoneConstants.PHONE_IN_EMERGENCY_CALL, false); 1713 mWifiController.sendMessage(CMD_EMERGENCY_CALL_STATE_CHANGED, inCall ? 1 : 0, 0); 1714 } else if (action.equals(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED)) { 1715 handleIdleModeChanged(); 1716 } 1717 } 1718 }; 1719 1720 private boolean startConsentUi(String packageName, 1721 int callingUid, String intentAction) throws RemoteException { 1722 if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) { 1723 return false; 1724 } 1725 try { 1726 // Validate the package only if we are going to use it 1727 ApplicationInfo applicationInfo = mContext.getPackageManager() 1728 .getApplicationInfoAsUser(packageName, 1729 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, 1730 UserHandle.getUserId(callingUid)); 1731 if (applicationInfo.uid != callingUid) { 1732 throw new SecurityException("Package " + callingUid 1733 + " not in uid " + callingUid); 1734 } 1735 1736 // Permission review mode, trigger a user prompt 1737 Intent intent = new Intent(intentAction); 1738 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK 1739 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 1740 intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName); 1741 mContext.startActivity(intent); 1742 return true; 1743 } catch (PackageManager.NameNotFoundException e) { 1744 throw new RemoteException(e.getMessage()); 1745 } 1746 } 1747 1748 /** 1749 * Observes settings changes to scan always mode. 1750 */ 1751 private void registerForScanModeChange() { 1752 ContentObserver contentObserver = new ContentObserver(null) { 1753 @Override 1754 public void onChange(boolean selfChange) { 1755 mSettingsStore.handleWifiScanAlwaysAvailableToggled(); 1756 mWifiController.sendMessage(CMD_SCAN_ALWAYS_MODE_CHANGED); 1757 } 1758 }; 1759 mFrameworkFacade.registerContentObserver(mContext, 1760 Settings.Global.getUriFor(Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE), 1761 false, contentObserver); 1762 1763 } 1764 1765 // Monitors settings changes related to background wifi scan throttling. 1766 private void registerForBackgroundThrottleChanges() { 1767 mFrameworkFacade.registerContentObserver( 1768 mContext, 1769 Settings.Global.getUriFor( 1770 Settings.Global.WIFI_SCAN_BACKGROUND_THROTTLE_INTERVAL_MS), 1771 false, 1772 new ContentObserver(null) { 1773 @Override 1774 public void onChange(boolean selfChange) { 1775 updateBackgroundThrottleInterval(); 1776 } 1777 } 1778 ); 1779 mFrameworkFacade.registerContentObserver( 1780 mContext, 1781 Settings.Global.getUriFor( 1782 Settings.Global.WIFI_SCAN_BACKGROUND_THROTTLE_PACKAGE_WHITELIST), 1783 false, 1784 new ContentObserver(null) { 1785 @Override 1786 public void onChange(boolean selfChange) { 1787 updateBackgroundThrottlingWhitelist(); 1788 } 1789 } 1790 ); 1791 } 1792 1793 private void updateBackgroundThrottleInterval() { 1794 mBackgroundThrottleInterval = mFrameworkFacade.getLongSetting( 1795 mContext, 1796 Settings.Global.WIFI_SCAN_BACKGROUND_THROTTLE_INTERVAL_MS, 1797 DEFAULT_SCAN_BACKGROUND_THROTTLE_INTERVAL_MS); 1798 } 1799 1800 private void updateBackgroundThrottlingWhitelist() { 1801 String setting = mFrameworkFacade.getStringSetting( 1802 mContext, 1803 Settings.Global.WIFI_SCAN_BACKGROUND_THROTTLE_PACKAGE_WHITELIST); 1804 mBackgroundThrottlePackageWhitelist.clear(); 1805 if (setting != null) { 1806 mBackgroundThrottlePackageWhitelist.addAll(Arrays.asList(setting.split(","))); 1807 } 1808 } 1809 1810 private void registerForBroadcasts() { 1811 IntentFilter intentFilter = new IntentFilter(); 1812 intentFilter.addAction(Intent.ACTION_SCREEN_ON); 1813 intentFilter.addAction(Intent.ACTION_USER_PRESENT); 1814 intentFilter.addAction(Intent.ACTION_SCREEN_OFF); 1815 intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); 1816 intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); 1817 intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); 1818 intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED); 1819 intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); 1820 1821 boolean trackEmergencyCallState = mContext.getResources().getBoolean( 1822 com.android.internal.R.bool.config_wifi_turn_off_during_emergency_call); 1823 if (trackEmergencyCallState) { 1824 intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED); 1825 } 1826 1827 mContext.registerReceiver(mReceiver, intentFilter); 1828 } 1829 1830 private void registerForPackageOrUserRemoval() { 1831 IntentFilter intentFilter = new IntentFilter(); 1832 intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 1833 intentFilter.addAction(Intent.ACTION_USER_REMOVED); 1834 mContext.registerReceiverAsUser(new BroadcastReceiver() { 1835 @Override 1836 public void onReceive(Context context, Intent intent) { 1837 switch (intent.getAction()) { 1838 case Intent.ACTION_PACKAGE_REMOVED: { 1839 if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { 1840 return; 1841 } 1842 int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); 1843 Uri uri = intent.getData(); 1844 if (uid == -1 || uri == null) { 1845 return; 1846 } 1847 String pkgName = uri.getSchemeSpecificPart(); 1848 mWifiStateMachine.removeAppConfigs(pkgName, uid); 1849 break; 1850 } 1851 case Intent.ACTION_USER_REMOVED: { 1852 int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); 1853 mWifiStateMachine.removeUserConfigs(userHandle); 1854 break; 1855 } 1856 } 1857 } 1858 }, UserHandle.ALL, intentFilter, null, null); 1859 } 1860 1861 @Override 1862 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1863 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1864 != PackageManager.PERMISSION_GRANTED) { 1865 pw.println("Permission Denial: can't dump WifiService from from pid=" 1866 + Binder.getCallingPid() 1867 + ", uid=" + Binder.getCallingUid()); 1868 return; 1869 } 1870 if (args != null && args.length > 0 && WifiMetrics.PROTO_DUMP_ARG.equals(args[0])) { 1871 // WifiMetrics proto bytes were requested. Dump only these. 1872 mWifiStateMachine.updateWifiMetrics(); 1873 mWifiMetrics.dump(fd, pw, args); 1874 } else if (args != null && args.length > 0 && IpManager.DUMP_ARG.equals(args[0])) { 1875 // IpManager dump was requested. Pass it along and take no further action. 1876 String[] ipManagerArgs = new String[args.length - 1]; 1877 System.arraycopy(args, 1, ipManagerArgs, 0, ipManagerArgs.length); 1878 mWifiStateMachine.dumpIpManager(fd, pw, ipManagerArgs); 1879 } else if (args != null && args.length > 0 1880 && DUMP_ARG_SET_IPREACH_DISCONNECT.equals(args[0])) { 1881 if (args.length > 1) { 1882 if (DUMP_ARG_SET_IPREACH_DISCONNECT_ENABLED.equals(args[1])) { 1883 mWifiStateMachine.setIpReachabilityDisconnectEnabled(true); 1884 } else if (DUMP_ARG_SET_IPREACH_DISCONNECT_DISABLED.equals(args[1])) { 1885 mWifiStateMachine.setIpReachabilityDisconnectEnabled(false); 1886 } 1887 } 1888 pw.println("IPREACH_DISCONNECT state is " 1889 + mWifiStateMachine.getIpReachabilityDisconnectEnabled()); 1890 return; 1891 } else { 1892 pw.println("Wi-Fi is " + mWifiStateMachine.syncGetWifiStateByName()); 1893 pw.println("Stay-awake conditions: " + 1894 mFacade.getIntegerSetting(mContext, 1895 Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0)); 1896 pw.println("mInIdleMode " + mInIdleMode); 1897 pw.println("mScanPending " + mScanPending); 1898 mWifiController.dump(fd, pw, args); 1899 mSettingsStore.dump(fd, pw, args); 1900 mTrafficPoller.dump(fd, pw, args); 1901 pw.println(); 1902 pw.println("Locks held:"); 1903 mWifiLockManager.dump(pw); 1904 pw.println(); 1905 mWifiMulticastLockManager.dump(pw); 1906 pw.println(); 1907 mWifiStateMachine.dump(fd, pw, args); 1908 pw.println(); 1909 mWifiStateMachine.updateWifiMetrics(); 1910 mWifiMetrics.dump(fd, pw, args); 1911 pw.println(); 1912 mWifiBackupRestore.dump(fd, pw, args); 1913 pw.println(); 1914 } 1915 } 1916 1917 @Override 1918 public boolean acquireWifiLock(IBinder binder, int lockMode, String tag, WorkSource ws) { 1919 mLog.trace("acquireWifiLock uid=% lockMode=%") 1920 .c(Binder.getCallingUid()) 1921 .c(lockMode).flush(); 1922 if (mWifiLockManager.acquireWifiLock(lockMode, tag, binder, ws)) { 1923 mWifiController.sendMessage(CMD_LOCKS_CHANGED); 1924 return true; 1925 } 1926 return false; 1927 } 1928 1929 @Override 1930 public void updateWifiLockWorkSource(IBinder binder, WorkSource ws) { 1931 mLog.trace("updateWifiLockWorkSource uid=%").c(Binder.getCallingUid()).flush(); 1932 mWifiLockManager.updateWifiLockWorkSource(binder, ws); 1933 } 1934 1935 @Override 1936 public boolean releaseWifiLock(IBinder binder) { 1937 mLog.trace("releaseWifiLock uid=%").c(Binder.getCallingUid()).flush(); 1938 if (mWifiLockManager.releaseWifiLock(binder)) { 1939 mWifiController.sendMessage(CMD_LOCKS_CHANGED); 1940 return true; 1941 } 1942 return false; 1943 } 1944 1945 @Override 1946 public void initializeMulticastFiltering() { 1947 enforceMulticastChangePermission(); 1948 mLog.trace("initializeMulticastFiltering uid=%").c(Binder.getCallingUid()).flush(); 1949 mWifiMulticastLockManager.initializeFiltering(); 1950 } 1951 1952 @Override 1953 public void acquireMulticastLock(IBinder binder, String tag) { 1954 enforceMulticastChangePermission(); 1955 mLog.trace("acquireMulticastLock uid=%").c(Binder.getCallingUid()).flush(); 1956 mWifiMulticastLockManager.acquireLock(binder, tag); 1957 } 1958 1959 @Override 1960 public void releaseMulticastLock() { 1961 enforceMulticastChangePermission(); 1962 mLog.trace("releaseMulticastLock uid=%").c(Binder.getCallingUid()).flush(); 1963 mWifiMulticastLockManager.releaseLock(); 1964 } 1965 1966 @Override 1967 public boolean isMulticastEnabled() { 1968 enforceAccessPermission(); 1969 mLog.trace("isMulticastEnabled uid=%").c(Binder.getCallingUid()).flush(); 1970 return mWifiMulticastLockManager.isMulticastEnabled(); 1971 } 1972 1973 @Override 1974 public void enableVerboseLogging(int verbose) { 1975 enforceAccessPermission(); 1976 mLog.trace("enableVerboseLogging uid=% verbose=%") 1977 .c(Binder.getCallingUid()) 1978 .c(verbose).flush(); 1979 mFacade.setIntegerSetting( 1980 mContext, Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED, verbose); 1981 enableVerboseLoggingInternal(verbose); 1982 } 1983 1984 void enableVerboseLoggingInternal(int verbose) { 1985 mWifiStateMachine.enableVerboseLogging(verbose); 1986 mWifiLockManager.enableVerboseLogging(verbose); 1987 mWifiMulticastLockManager.enableVerboseLogging(verbose); 1988 mWifiInjector.getWifiLastResortWatchdog().enableVerboseLogging(verbose); 1989 mWifiInjector.getWifiBackupRestore().enableVerboseLogging(verbose); 1990 LogcatLog.enableVerboseLogging(verbose); 1991 } 1992 1993 @Override 1994 public int getVerboseLoggingLevel() { 1995 enforceAccessPermission(); 1996 mLog.trace("getVerboseLoggingLevel uid=%").c(Binder.getCallingUid()).flush(); 1997 return mFacade.getIntegerSetting( 1998 mContext, Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED, 0); 1999 } 2000 2001 @Override 2002 public void enableAggressiveHandover(int enabled) { 2003 enforceAccessPermission(); 2004 mLog.trace("enableAggressiveHandover uid=% enabled=%") 2005 .c(Binder.getCallingUid()) 2006 .c(enabled) 2007 .flush(); 2008 mWifiStateMachine.enableAggressiveHandover(enabled); 2009 } 2010 2011 @Override 2012 public int getAggressiveHandover() { 2013 enforceAccessPermission(); 2014 mLog.trace("getAggressiveHandover uid=%").c(Binder.getCallingUid()).flush(); 2015 return mWifiStateMachine.getAggressiveHandover(); 2016 } 2017 2018 @Override 2019 public void setAllowScansWithTraffic(int enabled) { 2020 enforceAccessPermission(); 2021 mLog.trace("setAllowScansWithTraffic uid=% enabled=%") 2022 .c(Binder.getCallingUid()) 2023 .c(enabled).flush(); 2024 mWifiStateMachine.setAllowScansWithTraffic(enabled); 2025 } 2026 2027 @Override 2028 public int getAllowScansWithTraffic() { 2029 enforceAccessPermission(); 2030 mLog.trace("getAllowScansWithTraffic uid=%").c(Binder.getCallingUid()).flush(); 2031 return mWifiStateMachine.getAllowScansWithTraffic(); 2032 } 2033 2034 @Override 2035 public boolean setEnableAutoJoinWhenAssociated(boolean enabled) { 2036 enforceChangePermission(); 2037 mLog.trace("setEnableAutoJoinWhenAssociated uid=% enabled=%") 2038 .c(Binder.getCallingUid()) 2039 .c(enabled).flush(); 2040 return mWifiStateMachine.setEnableAutoJoinWhenAssociated(enabled); 2041 } 2042 2043 @Override 2044 public boolean getEnableAutoJoinWhenAssociated() { 2045 enforceAccessPermission(); 2046 mLog.trace("getEnableAutoJoinWhenAssociated uid=%").c(Binder.getCallingUid()).flush(); 2047 return mWifiStateMachine.getEnableAutoJoinWhenAssociated(); 2048 } 2049 2050 /* Return the Wifi Connection statistics object */ 2051 @Override 2052 public WifiConnectionStatistics getConnectionStatistics() { 2053 enforceAccessPermission(); 2054 enforceReadCredentialPermission(); 2055 mLog.trace("getConnectionStatistics uid=%").c(Binder.getCallingUid()).flush(); 2056 if (mWifiStateMachineChannel != null) { 2057 return mWifiStateMachine.syncGetConnectionStatistics(mWifiStateMachineChannel); 2058 } else { 2059 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 2060 return null; 2061 } 2062 } 2063 2064 @Override 2065 public void factoryReset() { 2066 enforceConnectivityInternalPermission(); 2067 mLog.trace("factoryReset uid=%").c(Binder.getCallingUid()).flush(); 2068 if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) { 2069 return; 2070 } 2071 2072 if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING)) { 2073 // Turn mobile hotspot off 2074 setWifiApEnabled(null, false); 2075 } 2076 2077 if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_WIFI)) { 2078 // Enable wifi 2079 try { 2080 setWifiEnabled(mContext.getOpPackageName(), true); 2081 } catch (RemoteException e) { 2082 /* ignore - local call */ 2083 } 2084 // Delete all Wifi SSIDs 2085 if (mWifiStateMachineChannel != null) { 2086 List<WifiConfiguration> networks = mWifiStateMachine.syncGetConfiguredNetworks( 2087 Binder.getCallingUid(), mWifiStateMachineChannel); 2088 if (networks != null) { 2089 for (WifiConfiguration config : networks) { 2090 removeNetwork(config.networkId); 2091 } 2092 saveConfiguration(); 2093 } 2094 } 2095 } 2096 } 2097 2098 /* private methods */ 2099 static boolean logAndReturnFalse(String s) { 2100 Log.d(TAG, s); 2101 return false; 2102 } 2103 2104 public static boolean isValid(WifiConfiguration config) { 2105 String validity = checkValidity(config); 2106 return validity == null || logAndReturnFalse(validity); 2107 } 2108 2109 public static boolean isValidPasspoint(WifiConfiguration config) { 2110 String validity = checkPasspointValidity(config); 2111 return validity == null || logAndReturnFalse(validity); 2112 } 2113 2114 public static String checkValidity(WifiConfiguration config) { 2115 if (config.allowedKeyManagement == null) 2116 return "allowed kmgmt"; 2117 2118 if (config.allowedKeyManagement.cardinality() > 1) { 2119 if (config.allowedKeyManagement.cardinality() != 2) { 2120 return "cardinality != 2"; 2121 } 2122 if (!config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP)) { 2123 return "not WPA_EAP"; 2124 } 2125 if ((!config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X)) 2126 && (!config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK))) { 2127 return "not PSK or 8021X"; 2128 } 2129 } 2130 if (config.getIpAssignment() == IpConfiguration.IpAssignment.STATIC) { 2131 StaticIpConfiguration staticIpConf = config.getStaticIpConfiguration(); 2132 if (staticIpConf == null) { 2133 return "null StaticIpConfiguration"; 2134 } 2135 if (staticIpConf.ipAddress == null) { 2136 return "null static ip Address"; 2137 } 2138 } 2139 return null; 2140 } 2141 2142 public static String checkPasspointValidity(WifiConfiguration config) { 2143 if (!TextUtils.isEmpty(config.FQDN)) { 2144 /* this is passpoint configuration; it must not have an SSID */ 2145 if (!TextUtils.isEmpty(config.SSID)) { 2146 return "SSID not expected for Passpoint: '" + config.SSID + 2147 "' FQDN " + toHexString(config.FQDN); 2148 } 2149 /* this is passpoint configuration; it must have a providerFriendlyName */ 2150 if (TextUtils.isEmpty(config.providerFriendlyName)) { 2151 return "no provider friendly name"; 2152 } 2153 WifiEnterpriseConfig enterpriseConfig = config.enterpriseConfig; 2154 /* this is passpoint configuration; it must have enterprise config */ 2155 if (enterpriseConfig == null 2156 || enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.NONE ) { 2157 return "no enterprise config"; 2158 } 2159 if ((enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TLS || 2160 enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TTLS || 2161 enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.PEAP) && 2162 enterpriseConfig.getCaCertificate() == null) { 2163 return "no CA certificate"; 2164 } 2165 } 2166 return null; 2167 } 2168 2169 @Override 2170 public Network getCurrentNetwork() { 2171 enforceAccessPermission(); 2172 mLog.trace("getCurrentNetwork uid=%").c(Binder.getCallingUid()).flush(); 2173 return mWifiStateMachine.getCurrentNetwork(); 2174 } 2175 2176 public static String toHexString(String s) { 2177 if (s == null) { 2178 return "null"; 2179 } 2180 StringBuilder sb = new StringBuilder(); 2181 sb.append('\'').append(s).append('\''); 2182 for (int n = 0; n < s.length(); n++) { 2183 sb.append(String.format(" %02x", s.charAt(n) & 0xffff)); 2184 } 2185 return sb.toString(); 2186 } 2187 2188 public void hideCertFromUnaffiliatedUsers(String alias) { 2189 mCertManager.hideCertFromUnaffiliatedUsers(alias); 2190 } 2191 2192 public String[] listClientCertsForCurrentUser() { 2193 return mCertManager.listClientCertsForCurrentUser(); 2194 } 2195 2196 /** 2197 * Enable/disable WifiConnectivityManager at runtime 2198 * 2199 * @param enabled true-enable; false-disable 2200 */ 2201 @Override 2202 public void enableWifiConnectivityManager(boolean enabled) { 2203 enforceConnectivityInternalPermission(); 2204 mLog.trace("enableWifiConnectivityManager uid=% enabled=%") 2205 .c(Binder.getCallingUid()) 2206 .c(enabled).flush(); 2207 mWifiStateMachine.enableWifiConnectivityManager(enabled); 2208 } 2209 2210 /** 2211 * Retrieve the data to be backed to save the current state. 2212 * 2213 * @return Raw byte stream of the data to be backed up. 2214 */ 2215 @Override 2216 public byte[] retrieveBackupData() { 2217 enforceReadCredentialPermission(); 2218 enforceAccessPermission(); 2219 mLog.trace("retrieveBackupData uid=%").c(Binder.getCallingUid()).flush(); 2220 if (mWifiStateMachineChannel == null) { 2221 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 2222 return null; 2223 } 2224 2225 Slog.d(TAG, "Retrieving backup data"); 2226 List<WifiConfiguration> wifiConfigurations = 2227 mWifiStateMachine.syncGetPrivilegedConfiguredNetwork(mWifiStateMachineChannel); 2228 byte[] backupData = 2229 mWifiBackupRestore.retrieveBackupDataFromConfigurations(wifiConfigurations); 2230 Slog.d(TAG, "Retrieved backup data"); 2231 return backupData; 2232 } 2233 2234 /** 2235 * Helper method to restore networks retrieved from backup data. 2236 * 2237 * @param configurations list of WifiConfiguration objects parsed from the backup data. 2238 */ 2239 private void restoreNetworks(List<WifiConfiguration> configurations) { 2240 if (configurations == null) { 2241 Slog.e(TAG, "Backup data parse failed"); 2242 return; 2243 } 2244 for (WifiConfiguration configuration : configurations) { 2245 int networkId = mWifiStateMachine.syncAddOrUpdateNetwork( 2246 mWifiStateMachineChannel, configuration); 2247 if (networkId == WifiConfiguration.INVALID_NETWORK_ID) { 2248 Slog.e(TAG, "Restore network failed: " + configuration.configKey()); 2249 continue; 2250 } 2251 // Enable all networks restored. 2252 mWifiStateMachine.syncEnableNetwork(mWifiStateMachineChannel, networkId, false); 2253 } 2254 } 2255 2256 /** 2257 * Restore state from the backed up data. 2258 * 2259 * @param data Raw byte stream of the backed up data. 2260 */ 2261 @Override 2262 public void restoreBackupData(byte[] data) { 2263 enforceChangePermission(); 2264 mLog.trace("restoreBackupData uid=%").c(Binder.getCallingUid()).flush(); 2265 if (mWifiStateMachineChannel == null) { 2266 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 2267 return; 2268 } 2269 2270 Slog.d(TAG, "Restoring backup data"); 2271 List<WifiConfiguration> wifiConfigurations = 2272 mWifiBackupRestore.retrieveConfigurationsFromBackupData(data); 2273 restoreNetworks(wifiConfigurations); 2274 Slog.d(TAG, "Restored backup data"); 2275 } 2276 2277 /** 2278 * Restore state from the older supplicant back up data. 2279 * The old backup data was essentially a backup of wpa_supplicant.conf & ipconfig.txt file. 2280 * 2281 * @param supplicantData Raw byte stream of wpa_supplicant.conf 2282 * @param ipConfigData Raw byte stream of ipconfig.txt 2283 */ 2284 public void restoreSupplicantBackupData(byte[] supplicantData, byte[] ipConfigData) { 2285 enforceChangePermission(); 2286 mLog.trace("restoreSupplicantBackupData uid=%").c(Binder.getCallingUid()).flush(); 2287 if (mWifiStateMachineChannel == null) { 2288 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 2289 return; 2290 } 2291 2292 Slog.d(TAG, "Restoring supplicant backup data"); 2293 List<WifiConfiguration> wifiConfigurations = 2294 mWifiBackupRestore.retrieveConfigurationsFromSupplicantBackupData( 2295 supplicantData, ipConfigData); 2296 restoreNetworks(wifiConfigurations); 2297 Slog.d(TAG, "Restored supplicant backup data"); 2298 } 2299} 2300