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 17 package com.android.server.wifi; 18 19 import static android.app.AppOpsManager.MODE_ALLOWED; 20 import static android.net.wifi.WifiManager.EXTRA_PREVIOUS_WIFI_AP_STATE; 21 import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_FAILURE_REASON; 22 import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME; 23 import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE; 24 import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE; 25 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_GENERIC; 26 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_NO_CHANNEL; 27 import static android.net.wifi.WifiManager.SAP_START_FAILURE_NO_CHANNEL; 28 import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED; 29 import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING; 30 import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED; 31 32 import static com.android.server.wifi.LocalOnlyHotspotRequestInfo.HOTSPOT_NO_ERROR; 33 import static com.android.server.wifi.WifiController.CMD_AIRPLANE_TOGGLED; 34 import static com.android.server.wifi.WifiController.CMD_EMERGENCY_CALL_STATE_CHANGED; 35 import static com.android.server.wifi.WifiController.CMD_EMERGENCY_MODE_CHANGED; 36 import static com.android.server.wifi.WifiController.CMD_SCAN_ALWAYS_MODE_CHANGED; 37 import static com.android.server.wifi.WifiController.CMD_SET_AP; 38 import static com.android.server.wifi.WifiController.CMD_USER_PRESENT; 39 import static com.android.server.wifi.WifiController.CMD_WIFI_TOGGLED; 40 41 import android.Manifest; 42 import android.annotation.CheckResult; 43 import android.app.ActivityManager; 44 import android.app.ActivityManager.RunningAppProcessInfo; 45 import android.app.AppOpsManager; 46 import android.bluetooth.BluetoothAdapter; 47 import android.content.BroadcastReceiver; 48 import android.content.Context; 49 import android.content.Intent; 50 import android.content.IntentFilter; 51 import android.content.pm.ApplicationInfo; 52 import android.content.pm.PackageManager; 53 import android.content.pm.ParceledListSlice; 54 import android.database.ContentObserver; 55 import android.net.DhcpInfo; 56 import android.net.DhcpResults; 57 import android.net.Network; 58 import android.net.NetworkUtils; 59 import android.net.Uri; 60 import android.net.ip.IpClient; 61 import android.net.wifi.ISoftApCallback; 62 import android.net.wifi.IWifiManager; 63 import android.net.wifi.ScanResult; 64 import android.net.wifi.WifiActivityEnergyInfo; 65 import android.net.wifi.WifiConfiguration; 66 import android.net.wifi.WifiInfo; 67 import android.net.wifi.WifiManager; 68 import android.net.wifi.WifiManager.LocalOnlyHotspotCallback; 69 import android.net.wifi.WifiSsid; 70 import android.net.wifi.hotspot2.IProvisioningCallback; 71 import android.net.wifi.hotspot2.OsuProvider; 72 import android.net.wifi.hotspot2.PasspointConfiguration; 73 import android.os.AsyncTask; 74 import android.os.BatteryStats; 75 import android.os.Binder; 76 import android.os.Build; 77 import android.os.Bundle; 78 import android.os.HandlerThread; 79 import android.os.IBinder; 80 import android.os.Looper; 81 import android.os.Message; 82 import android.os.Messenger; 83 import android.os.PowerManager; 84 import android.os.Process; 85 import android.os.RemoteException; 86 import android.os.ResultReceiver; 87 import android.os.ShellCallback; 88 import android.os.UserHandle; 89 import android.os.UserManager; 90 import android.os.WorkSource; 91 import android.provider.Settings; 92 import android.util.Log; 93 import android.util.MutableInt; 94 import android.util.Slog; 95 96 import com.android.internal.annotations.GuardedBy; 97 import com.android.internal.annotations.VisibleForTesting; 98 import com.android.internal.os.PowerProfile; 99 import com.android.internal.telephony.IccCardConstants; 100 import com.android.internal.telephony.PhoneConstants; 101 import com.android.internal.telephony.TelephonyIntents; 102 import com.android.internal.util.AsyncChannel; 103 import com.android.server.wifi.hotspot2.PasspointProvider; 104 import com.android.server.wifi.util.GeneralUtil.Mutable; 105 import com.android.server.wifi.util.WifiHandler; 106 import com.android.server.wifi.util.WifiPermissionsUtil; 107 108 import java.io.BufferedReader; 109 import java.io.FileDescriptor; 110 import java.io.FileNotFoundException; 111 import java.io.FileReader; 112 import java.io.IOException; 113 import java.io.PrintWriter; 114 import java.net.Inet4Address; 115 import java.net.InetAddress; 116 import java.security.GeneralSecurityException; 117 import java.security.KeyStore; 118 import java.security.cert.CertPath; 119 import java.security.cert.CertPathValidator; 120 import java.security.cert.CertificateFactory; 121 import java.security.cert.PKIXParameters; 122 import java.security.cert.X509Certificate; 123 import java.util.ArrayList; 124 import java.util.Arrays; 125 import java.util.HashMap; 126 import java.util.Iterator; 127 import java.util.List; 128 import java.util.concurrent.ConcurrentHashMap; 129 130 /** 131 * WifiService handles remote WiFi operation requests by implementing 132 * the IWifiManager interface. 133 * 134 * @hide 135 */ 136 public class WifiServiceImpl extends IWifiManager.Stub { 137 private static final String TAG = "WifiService"; 138 private static final boolean VDBG = false; 139 140 // Default scan background throttling interval if not overriden in settings 141 private static final long DEFAULT_SCAN_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000; 142 143 // Apps with importance higher than this value is considered as background app. 144 private static final int BACKGROUND_IMPORTANCE_CUTOFF = 145 RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; 146 147 // Max wait time for posting blocking runnables 148 private static final int RUN_WITH_SCISSORS_TIMEOUT_MILLIS = 4000; 149 150 final WifiStateMachine mWifiStateMachine; 151 final WifiStateMachinePrime mWifiStateMachinePrime; 152 final ScanRequestProxy mScanRequestProxy; 153 154 private final Context mContext; 155 private final FrameworkFacade mFacade; 156 private final Clock mClock; 157 158 private final PowerManager mPowerManager; 159 private final AppOpsManager mAppOps; 160 private final UserManager mUserManager; 161 private final ActivityManager mActivityManager; 162 private final WifiCountryCode mCountryCode; 163 // Debug counter tracking scan requests sent by WifiManager 164 private int scanRequestCounter = 0; 165 166 /* Polls traffic stats and notifies clients */ 167 private WifiTrafficPoller mTrafficPoller; 168 /* Tracks the persisted states for wi-fi & airplane mode */ 169 final WifiSettingsStore mSettingsStore; 170 /* Logs connection events and some general router and scan stats */ 171 private final WifiMetrics mWifiMetrics; 172 173 private final WifiInjector mWifiInjector; 174 /* Backup/Restore Module */ 175 private final WifiBackupRestore mWifiBackupRestore; 176 177 private WifiLog mLog; 178 /** 179 * Verbose logging flag. Toggled by developer options. 180 */ 181 private boolean mVerboseLoggingEnabled = false; 182 183 /** 184 * Asynchronous channel to WifiStateMachine 185 */ 186 private AsyncChannel mWifiStateMachineChannel; 187 188 private final boolean mPermissionReviewRequired; 189 private final FrameworkFacade mFrameworkFacade; 190 191 private WifiPermissionsUtil mWifiPermissionsUtil; 192 193 @GuardedBy("mLocalOnlyHotspotRequests") 194 private final HashMap<Integer, LocalOnlyHotspotRequestInfo> mLocalOnlyHotspotRequests; 195 @GuardedBy("mLocalOnlyHotspotRequests") 196 private WifiConfiguration mLocalOnlyHotspotConfig = null; 197 @GuardedBy("mLocalOnlyHotspotRequests") 198 private final ConcurrentHashMap<String, Integer> mIfaceIpModes; 199 200 /* Limit on number of registered soft AP callbacks to track and prevent potential memory leak */ 201 private static final int NUM_SOFT_AP_CALLBACKS_WARN_LIMIT = 10; 202 private static final int NUM_SOFT_AP_CALLBACKS_WTF_LIMIT = 20; 203 private final HashMap<Integer, ISoftApCallback> mRegisteredSoftApCallbacks; 204 205 /** 206 * One of: {@link WifiManager#WIFI_AP_STATE_DISABLED}, 207 * {@link WifiManager#WIFI_AP_STATE_DISABLING}, 208 * {@link WifiManager#WIFI_AP_STATE_ENABLED}, 209 * {@link WifiManager#WIFI_AP_STATE_ENABLING}, 210 * {@link WifiManager#WIFI_AP_STATE_FAILED} 211 * 212 * Access/maintenance MUST be done on the wifi service thread 213 */ 214 // TODO: (b/71714381) Remove mWifiApState and broadcast mechanism, keep mSoftApState as the only 215 // field to store soft AP state. Then rename mSoftApState and mSoftApNumClients to 216 // mWifiApState and mWifiApNumClients, to match the constants (i.e. WIFI_AP_STATE_*) 217 private int mWifiApState = WifiManager.WIFI_AP_STATE_DISABLED; 218 private int mSoftApState = WifiManager.WIFI_AP_STATE_DISABLED; 219 private int mSoftApNumClients = 0; 220 221 /** 222 * Power profile 223 */ 224 PowerProfile mPowerProfile; 225 226 /** 227 * Callback for use with LocalOnlyHotspot to unregister requesting applications upon death. 228 * 229 * @hide 230 */ 231 public final class LocalOnlyRequestorCallback 232 implements LocalOnlyHotspotRequestInfo.RequestingApplicationDeathCallback { 233 /** 234 * Called with requesting app has died. 235 */ 236 @Override 237 public void onLocalOnlyHotspotRequestorDeath(LocalOnlyHotspotRequestInfo requestor) { 238 unregisterCallingAppAndStopLocalOnlyHotspot(requestor); 239 }; 240 } 241 242 /** 243 * Handles client connections 244 */ 245 private class ClientHandler extends WifiHandler { 246 247 ClientHandler(String tag, Looper looper) { 248 super(tag, looper); 249 } 250 251 @Override 252 public void handleMessage(Message msg) { 253 super.handleMessage(msg); 254 switch (msg.what) { 255 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: { 256 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 257 Slog.d(TAG, "New client listening to asynchronous messages"); 258 // We track the clients by the Messenger 259 // since it is expected to be always available 260 mTrafficPoller.addClient(msg.replyTo); 261 } else { 262 Slog.e(TAG, "Client connection failure, error=" + msg.arg1); 263 } 264 break; 265 } 266 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { 267 if (msg.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) { 268 Slog.w(TAG, "Send failed, client connection lost"); 269 } else { 270 Slog.w(TAG, "Client connection lost with reason: " + msg.arg1); 271 } 272 mTrafficPoller.removeClient(msg.replyTo); 273 break; 274 } 275 case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: { 276 AsyncChannel ac = mFrameworkFacade.makeWifiAsyncChannel(TAG); 277 ac.connect(mContext, this, msg.replyTo); 278 break; 279 } 280 case WifiManager.CONNECT_NETWORK: { 281 if (checkChangePermissionAndReplyIfNotAuthorized( 282 msg, WifiManager.CONNECT_NETWORK_FAILED)) { 283 WifiConfiguration config = (WifiConfiguration) msg.obj; 284 int networkId = msg.arg1; 285 Slog.d(TAG, "CONNECT " 286 + " nid=" + Integer.toString(networkId) 287 + " config=" + config 288 + " uid=" + msg.sendingUid 289 + " name=" 290 + mContext.getPackageManager().getNameForUid(msg.sendingUid)); 291 if (config != null) { 292 /* Command is forwarded to state machine */ 293 mWifiStateMachine.sendMessage(Message.obtain(msg)); 294 } else if (config == null 295 && networkId != WifiConfiguration.INVALID_NETWORK_ID) { 296 mWifiStateMachine.sendMessage(Message.obtain(msg)); 297 } else { 298 Slog.e(TAG, "ClientHandler.handleMessage ignoring invalid msg=" + msg); 299 replyFailed(msg, WifiManager.CONNECT_NETWORK_FAILED, 300 WifiManager.INVALID_ARGS); 301 } 302 } 303 break; 304 } 305 case WifiManager.SAVE_NETWORK: { 306 if (checkChangePermissionAndReplyIfNotAuthorized( 307 msg, WifiManager.SAVE_NETWORK_FAILED)) { 308 WifiConfiguration config = (WifiConfiguration) msg.obj; 309 int networkId = msg.arg1; 310 Slog.d(TAG, "SAVE" 311 + " nid=" + Integer.toString(networkId) 312 + " config=" + config 313 + " uid=" + msg.sendingUid 314 + " name=" 315 + mContext.getPackageManager().getNameForUid(msg.sendingUid)); 316 if (config != null) { 317 /* Command is forwarded to state machine */ 318 mWifiStateMachine.sendMessage(Message.obtain(msg)); 319 } else { 320 Slog.e(TAG, "ClientHandler.handleMessage ignoring invalid msg=" + msg); 321 replyFailed(msg, WifiManager.SAVE_NETWORK_FAILED, 322 WifiManager.INVALID_ARGS); 323 } 324 } 325 break; 326 } 327 case WifiManager.FORGET_NETWORK: 328 if (checkChangePermissionAndReplyIfNotAuthorized( 329 msg, WifiManager.FORGET_NETWORK_FAILED)) { 330 mWifiStateMachine.sendMessage(Message.obtain(msg)); 331 } 332 break; 333 case WifiManager.START_WPS: 334 if (checkChangePermissionAndReplyIfNotAuthorized(msg, WifiManager.WPS_FAILED)) { 335 // WPS support is deprecated, return an error 336 replyFailed(msg, WifiManager.WPS_FAILED, WifiManager.ERROR); 337 } 338 break; 339 case WifiManager.CANCEL_WPS: 340 if (checkChangePermissionAndReplyIfNotAuthorized( 341 msg, WifiManager.CANCEL_WPS_FAILED)) { 342 // WPS support is deprecated, return an error 343 replyFailed(msg, WifiManager.CANCEL_WPS_FAILED, WifiManager.ERROR); 344 } 345 break; 346 case WifiManager.DISABLE_NETWORK: 347 if (checkChangePermissionAndReplyIfNotAuthorized( 348 msg, WifiManager.DISABLE_NETWORK_FAILED)) { 349 mWifiStateMachine.sendMessage(Message.obtain(msg)); 350 } 351 break; 352 case WifiManager.RSSI_PKTCNT_FETCH: { 353 if (checkChangePermissionAndReplyIfNotAuthorized( 354 msg, WifiManager.RSSI_PKTCNT_FETCH_FAILED)) { 355 mWifiStateMachine.sendMessage(Message.obtain(msg)); 356 } 357 break; 358 } 359 default: { 360 Slog.d(TAG, "ClientHandler.handleMessage ignoring msg=" + msg); 361 break; 362 } 363 } 364 } 365 366 /** 367 * Helper method to check if the sender of the message holds the 368 * {@link Manifest.permission#CHANGE_WIFI_STATE} permission, and reply with a failure if it 369 * doesn't 370 * 371 * @param msg Incoming message. 372 * @param replyWhat Param to be filled in the {@link Message#what} field of the failure 373 * reply. 374 * @return true if the sender holds the permission, false otherwise. 375 */ 376 private boolean checkChangePermissionAndReplyIfNotAuthorized(Message msg, int replyWhat) { 377 if (!mWifiPermissionsUtil.checkChangePermission(msg.sendingUid)) { 378 Slog.e(TAG, "ClientHandler.handleMessage ignoring unauthorized msg=" + msg); 379 replyFailed(msg, replyWhat, WifiManager.NOT_AUTHORIZED); 380 return false; 381 } 382 return true; 383 } 384 385 private void replyFailed(Message msg, int what, int why) { 386 if (msg.replyTo == null) return; 387 Message reply = Message.obtain(); 388 reply.what = what; 389 reply.arg1 = why; 390 try { 391 msg.replyTo.send(reply); 392 } catch (RemoteException e) { 393 // There's not much we can do if reply can't be sent! 394 } 395 } 396 } 397 private ClientHandler mClientHandler; 398 399 /** 400 * Handles interaction with WifiStateMachine 401 */ 402 private class WifiStateMachineHandler extends WifiHandler { 403 private AsyncChannel mWsmChannel; 404 405 WifiStateMachineHandler(String tag, Looper looper, AsyncChannel asyncChannel) { 406 super(tag, looper); 407 mWsmChannel = asyncChannel; 408 mWsmChannel.connect(mContext, this, mWifiStateMachine.getHandler()); 409 } 410 411 @Override 412 public void handleMessage(Message msg) { 413 super.handleMessage(msg); 414 switch (msg.what) { 415 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: { 416 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 417 mWifiStateMachineChannel = mWsmChannel; 418 } else { 419 Slog.e(TAG, "WifiStateMachine connection failure, error=" + msg.arg1); 420 mWifiStateMachineChannel = null; 421 } 422 break; 423 } 424 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { 425 Slog.e(TAG, "WifiStateMachine channel lost, msg.arg1 =" + msg.arg1); 426 mWifiStateMachineChannel = null; 427 //Re-establish connection to state machine 428 mWsmChannel.connect(mContext, this, mWifiStateMachine.getHandler()); 429 break; 430 } 431 default: { 432 Slog.d(TAG, "WifiStateMachineHandler.handleMessage ignoring msg=" + msg); 433 break; 434 } 435 } 436 } 437 } 438 439 WifiStateMachineHandler mWifiStateMachineHandler; 440 private WifiController mWifiController; 441 private final WifiLockManager mWifiLockManager; 442 private final WifiMulticastLockManager mWifiMulticastLockManager; 443 444 private WifiApConfigStore mWifiApConfigStore; 445 446 public WifiServiceImpl(Context context, WifiInjector wifiInjector, AsyncChannel asyncChannel) { 447 mContext = context; 448 mWifiInjector = wifiInjector; 449 mClock = wifiInjector.getClock(); 450 451 mFacade = mWifiInjector.getFrameworkFacade(); 452 mWifiMetrics = mWifiInjector.getWifiMetrics(); 453 mTrafficPoller = mWifiInjector.getWifiTrafficPoller(); 454 mUserManager = mWifiInjector.getUserManager(); 455 mCountryCode = mWifiInjector.getWifiCountryCode(); 456 mWifiStateMachine = mWifiInjector.getWifiStateMachine(); 457 mWifiStateMachinePrime = mWifiInjector.getWifiStateMachinePrime(); 458 mWifiStateMachine.enableRssiPolling(true); 459 mScanRequestProxy = mWifiInjector.getScanRequestProxy(); 460 mSettingsStore = mWifiInjector.getWifiSettingsStore(); 461 mPowerManager = mContext.getSystemService(PowerManager.class); 462 mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 463 mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); 464 mWifiLockManager = mWifiInjector.getWifiLockManager(); 465 mWifiMulticastLockManager = mWifiInjector.getWifiMulticastLockManager(); 466 HandlerThread wifiServiceHandlerThread = mWifiInjector.getWifiServiceHandlerThread(); 467 mClientHandler = new ClientHandler(TAG, wifiServiceHandlerThread.getLooper()); 468 mWifiStateMachineHandler = new WifiStateMachineHandler(TAG, 469 wifiServiceHandlerThread.getLooper(), asyncChannel); 470 mWifiController = mWifiInjector.getWifiController(); 471 mWifiBackupRestore = mWifiInjector.getWifiBackupRestore(); 472 mWifiApConfigStore = mWifiInjector.getWifiApConfigStore(); 473 mPermissionReviewRequired = Build.PERMISSIONS_REVIEW_REQUIRED 474 || context.getResources().getBoolean( 475 com.android.internal.R.bool.config_permissionReviewRequired); 476 mWifiPermissionsUtil = mWifiInjector.getWifiPermissionsUtil(); 477 mLog = mWifiInjector.makeLog(TAG); 478 mFrameworkFacade = wifiInjector.getFrameworkFacade(); 479 mIfaceIpModes = new ConcurrentHashMap<>(); 480 mLocalOnlyHotspotRequests = new HashMap<>(); 481 enableVerboseLoggingInternal(getVerboseLoggingLevel()); 482 mRegisteredSoftApCallbacks = new HashMap<>(); 483 484 mWifiInjector.getWifiStateMachinePrime().registerSoftApCallback(new SoftApCallbackImpl()); 485 mPowerProfile = mWifiInjector.getPowerProfile(); 486 } 487 488 /** 489 * Provide a way for unit tests to set valid log object in the WifiHandler 490 * @param log WifiLog object to assign to the clientHandler 491 */ 492 @VisibleForTesting 493 public void setWifiHandlerLogForTest(WifiLog log) { 494 mClientHandler.setWifiLog(log); 495 } 496 497 /** 498 * Check if we are ready to start wifi. 499 * 500 * First check if we will be restarting system services to decrypt the device. If the device is 501 * not encrypted, check if Wi-Fi needs to be enabled and start if needed 502 * 503 * This function is used only at boot time. 504 */ 505 public void checkAndStartWifi() { 506 // First check if we will end up restarting WifiService 507 if (mFrameworkFacade.inStorageManagerCryptKeeperBounce()) { 508 Log.d(TAG, "Device still encrypted. Need to restart SystemServer. Do not start wifi."); 509 return; 510 } 511 512 // Check if wi-fi needs to be enabled 513 boolean wifiEnabled = mSettingsStore.isWifiToggleEnabled(); 514 Slog.i(TAG, "WifiService starting up with Wi-Fi " + 515 (wifiEnabled ? "enabled" : "disabled")); 516 517 registerForScanModeChange(); 518 mContext.registerReceiver( 519 new BroadcastReceiver() { 520 @Override 521 public void onReceive(Context context, Intent intent) { 522 if (mSettingsStore.handleAirplaneModeToggled()) { 523 mWifiController.sendMessage(CMD_AIRPLANE_TOGGLED); 524 } 525 if (mSettingsStore.isAirplaneModeOn()) { 526 Log.d(TAG, "resetting country code because Airplane mode is ON"); 527 mCountryCode.airplaneModeEnabled(); 528 } 529 } 530 }, 531 new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED)); 532 533 mContext.registerReceiver( 534 new BroadcastReceiver() { 535 @Override 536 public void onReceive(Context context, Intent intent) { 537 String state = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE); 538 if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(state)) { 539 Log.d(TAG, "resetting networks because SIM was removed"); 540 mWifiStateMachine.resetSimAuthNetworks(false); 541 } else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(state)) { 542 Log.d(TAG, "resetting networks because SIM was loaded"); 543 mWifiStateMachine.resetSimAuthNetworks(true); 544 } 545 } 546 }, 547 new IntentFilter(TelephonyIntents.ACTION_SIM_STATE_CHANGED)); 548 549 mContext.registerReceiver( 550 new BroadcastReceiver() { 551 @Override 552 public void onReceive(Context context, Intent intent) { 553 final int currState = intent.getIntExtra(EXTRA_WIFI_AP_STATE, 554 WIFI_AP_STATE_DISABLED); 555 final int prevState = intent.getIntExtra(EXTRA_PREVIOUS_WIFI_AP_STATE, 556 WIFI_AP_STATE_DISABLED); 557 final int errorCode = intent.getIntExtra(EXTRA_WIFI_AP_FAILURE_REASON, 558 HOTSPOT_NO_ERROR); 559 final String ifaceName = 560 intent.getStringExtra(EXTRA_WIFI_AP_INTERFACE_NAME); 561 final int mode = intent.getIntExtra(EXTRA_WIFI_AP_MODE, 562 WifiManager.IFACE_IP_MODE_UNSPECIFIED); 563 handleWifiApStateChange(currState, prevState, errorCode, ifaceName, mode); 564 } 565 }, 566 new IntentFilter(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)); 567 568 // Adding optimizations of only receiving broadcasts when wifi is enabled 569 // can result in race conditions when apps toggle wifi in the background 570 // without active user involvement. Always receive broadcasts. 571 registerForBroadcasts(); 572 mInIdleMode = mPowerManager.isDeviceIdleMode(); 573 574 if (!mWifiStateMachine.syncInitialize(mWifiStateMachineChannel)) { 575 Log.wtf(TAG, "Failed to initialize WifiStateMachine"); 576 } 577 mWifiController.start(); 578 579 // If we are already disabled (could be due to airplane mode), avoid changing persist 580 // state here 581 if (wifiEnabled) { 582 try { 583 setWifiEnabled(mContext.getPackageName(), wifiEnabled); 584 } catch (RemoteException e) { 585 /* ignore - local call */ 586 } 587 } 588 } 589 590 public void handleUserSwitch(int userId) { 591 mWifiStateMachine.handleUserSwitch(userId); 592 } 593 594 public void handleUserUnlock(int userId) { 595 mWifiStateMachine.handleUserUnlock(userId); 596 } 597 598 public void handleUserStop(int userId) { 599 mWifiStateMachine.handleUserStop(userId); 600 } 601 602 /** 603 * See {@link android.net.wifi.WifiManager#startScan} 604 * 605 * @param packageName Package name of the app that requests wifi scan. 606 */ 607 @Override 608 public boolean startScan(String packageName) { 609 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 610 return false; 611 } 612 613 int callingUid = Binder.getCallingUid(); 614 long ident = Binder.clearCallingIdentity(); 615 mLog.info("startScan uid=%").c(callingUid).flush(); 616 synchronized (this) { 617 if (mInIdleMode) { 618 // Need to send an immediate scan result broadcast in case the 619 // caller is waiting for a result .. 620 621 // TODO: investigate if the logic to cancel scans when idle can move to 622 // WifiScanningServiceImpl. This will 1 - clean up WifiServiceImpl and 2 - 623 // avoid plumbing an awkward path to report a cancelled/failed scan. This will 624 // be sent directly until b/31398592 is fixed. 625 sendFailedScanBroadcast(); 626 mScanPending = true; 627 return false; 628 } 629 } 630 try { 631 mWifiPermissionsUtil.enforceCanAccessScanResults(packageName, callingUid); 632 Mutable<Boolean> scanSuccess = new Mutable<>(); 633 boolean runWithScissorsSuccess = mWifiInjector.getWifiStateMachineHandler() 634 .runWithScissors(() -> { 635 scanSuccess.value = mScanRequestProxy.startScan(callingUid, packageName); 636 }, RUN_WITH_SCISSORS_TIMEOUT_MILLIS); 637 if (!runWithScissorsSuccess) { 638 Log.e(TAG, "Failed to post runnable to start scan"); 639 sendFailedScanBroadcast(); 640 return false; 641 } 642 if (!scanSuccess.value) { 643 Log.e(TAG, "Failed to start scan"); 644 return false; 645 } 646 } catch (SecurityException e) { 647 return false; 648 } finally { 649 Binder.restoreCallingIdentity(ident); 650 } 651 return true; 652 } 653 654 // Send a failed scan broadcast to indicate the current scan request failed. 655 private void sendFailedScanBroadcast() { 656 // clear calling identity to send broadcast 657 long callingIdentity = Binder.clearCallingIdentity(); 658 try { 659 Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); 660 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 661 intent.putExtra(WifiManager.EXTRA_RESULTS_UPDATED, false); 662 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 663 } finally { 664 // restore calling identity 665 Binder.restoreCallingIdentity(callingIdentity); 666 } 667 668 } 669 670 /** 671 * WPS support in Client mode is deprecated. Return null. 672 */ 673 @Override 674 public String getCurrentNetworkWpsNfcConfigurationToken() { 675 // while CLs are in flight, return null here, will be removed (b/72423090) 676 enforceConnectivityInternalPermission(); 677 if (mVerboseLoggingEnabled) { 678 mLog.info("getCurrentNetworkWpsNfcConfigurationToken uid=%") 679 .c(Binder.getCallingUid()).flush(); 680 } 681 return null; 682 } 683 684 boolean mInIdleMode; 685 boolean mScanPending; 686 687 void handleIdleModeChanged() { 688 boolean doScan = false; 689 synchronized (this) { 690 boolean idle = mPowerManager.isDeviceIdleMode(); 691 if (mInIdleMode != idle) { 692 mInIdleMode = idle; 693 if (!idle) { 694 if (mScanPending) { 695 mScanPending = false; 696 doScan = true; 697 } 698 } 699 } 700 } 701 if (doScan) { 702 // Someone requested a scan while we were idle; do a full scan now. 703 // A security check of the caller's identity was made when the request arrived via 704 // Binder. Now we'll pass the current process's identity to startScan(). 705 startScan(mContext.getOpPackageName()); 706 } 707 } 708 709 private boolean checkNetworkSettingsPermission(int pid, int uid) { 710 return mContext.checkPermission(android.Manifest.permission.NETWORK_SETTINGS, pid, uid) 711 == PackageManager.PERMISSION_GRANTED; 712 } 713 714 private void enforceNetworkSettingsPermission() { 715 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.NETWORK_SETTINGS, 716 "WifiService"); 717 } 718 719 private void enforceNetworkStackPermission() { 720 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.NETWORK_STACK, 721 "WifiService"); 722 } 723 724 private void enforceAccessPermission() { 725 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE, 726 "WifiService"); 727 } 728 729 /** 730 * Checks whether the caller can change the wifi state. 731 * Possible results: 732 * 1. Operation is allowed. No exception thrown, and AppOpsManager.MODE_ALLOWED returned. 733 * 2. Operation is not allowed, and caller must be told about this. SecurityException is thrown. 734 * 3. Operation is not allowed, and caller must not be told about this (i.e. must silently 735 * ignore the operation). No exception is thrown, and AppOpsManager.MODE_IGNORED returned. 736 */ 737 @CheckResult 738 private int enforceChangePermission(String callingPackage) { 739 if (checkNetworkSettingsPermission(Binder.getCallingPid(), Binder.getCallingUid())) { 740 return MODE_ALLOWED; 741 } 742 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE, 743 "WifiService"); 744 745 return mAppOps.noteOp( 746 AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Binder.getCallingUid(), callingPackage); 747 } 748 749 private void enforceLocationHardwarePermission() { 750 mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, 751 "LocationHardware"); 752 } 753 754 private void enforceReadCredentialPermission() { 755 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.READ_WIFI_CREDENTIAL, 756 "WifiService"); 757 } 758 759 private void enforceWorkSourcePermission() { 760 mContext.enforceCallingPermission(android.Manifest.permission.UPDATE_DEVICE_STATS, 761 "WifiService"); 762 763 } 764 765 private void enforceMulticastChangePermission() { 766 mContext.enforceCallingOrSelfPermission( 767 android.Manifest.permission.CHANGE_WIFI_MULTICAST_STATE, 768 "WifiService"); 769 } 770 771 private void enforceConnectivityInternalPermission() { 772 mContext.enforceCallingOrSelfPermission( 773 android.Manifest.permission.CONNECTIVITY_INTERNAL, 774 "ConnectivityService"); 775 } 776 777 private void enforceLocationPermission(String pkgName, int uid) { 778 mWifiPermissionsUtil.enforceLocationPermission(pkgName, uid); 779 } 780 781 /** 782 * Check if the caller must still pass permission check or if the caller is exempted 783 * from the consent UI via the MANAGE_WIFI_WHEN_PERMISSION_REVIEW_REQUIRED check. 784 * 785 * Commands from some callers may be exempted from triggering the consent UI when 786 * enabling wifi. This exemption is checked via the MANAGE_WIFI_WHEN_PERMISSION_REVIEW_REQUIRED 787 * and allows calls to skip the consent UI where it may otherwise be required. 788 * 789 * @hide 790 */ 791 private boolean checkWifiPermissionWhenPermissionReviewRequired() { 792 if (!mPermissionReviewRequired) { 793 return false; 794 } 795 int result = mContext.checkCallingPermission( 796 android.Manifest.permission.MANAGE_WIFI_WHEN_PERMISSION_REVIEW_REQUIRED); 797 return result == PackageManager.PERMISSION_GRANTED; 798 } 799 800 /** 801 * see {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)} 802 * @param enable {@code true} to enable, {@code false} to disable. 803 * @return {@code true} if the enable/disable operation was 804 * started or is already in the queue. 805 */ 806 @Override 807 public synchronized boolean setWifiEnabled(String packageName, boolean enable) 808 throws RemoteException { 809 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 810 return false; 811 } 812 813 Slog.d(TAG, "setWifiEnabled: " + enable + " pid=" + Binder.getCallingPid() 814 + ", uid=" + Binder.getCallingUid() + ", package=" + packageName); 815 mLog.info("setWifiEnabled package=% uid=% enable=%").c(packageName) 816 .c(Binder.getCallingUid()).c(enable).flush(); 817 818 boolean isFromSettings = checkNetworkSettingsPermission( 819 Binder.getCallingPid(), Binder.getCallingUid()); 820 821 // If Airplane mode is enabled, only Settings is allowed to toggle Wifi 822 if (mSettingsStore.isAirplaneModeOn() && !isFromSettings) { 823 mLog.info("setWifiEnabled in Airplane mode: only Settings can enable wifi").flush(); 824 return false; 825 } 826 827 // If SoftAp is enabled, only Settings is allowed to toggle wifi 828 boolean apEnabled = mWifiApState == WifiManager.WIFI_AP_STATE_ENABLED; 829 830 if (apEnabled && !isFromSettings) { 831 mLog.info("setWifiEnabled SoftAp not disabled: only Settings can enable wifi").flush(); 832 return false; 833 } 834 835 /* 836 * Caller might not have WRITE_SECURE_SETTINGS, 837 * only CHANGE_WIFI_STATE is enforced 838 */ 839 long ident = Binder.clearCallingIdentity(); 840 try { 841 if (! mSettingsStore.handleWifiToggled(enable)) { 842 // Nothing to do if wifi cannot be toggled 843 return true; 844 } 845 } finally { 846 Binder.restoreCallingIdentity(ident); 847 } 848 849 850 if (mPermissionReviewRequired) { 851 final int wiFiEnabledState = getWifiEnabledState(); 852 if (enable) { 853 if (wiFiEnabledState == WifiManager.WIFI_STATE_DISABLING 854 || wiFiEnabledState == WifiManager.WIFI_STATE_DISABLED) { 855 if (startConsentUi(packageName, Binder.getCallingUid(), 856 WifiManager.ACTION_REQUEST_ENABLE)) { 857 return true; 858 } 859 } 860 } else if (wiFiEnabledState == WifiManager.WIFI_STATE_ENABLING 861 || wiFiEnabledState == WifiManager.WIFI_STATE_ENABLED) { 862 if (startConsentUi(packageName, Binder.getCallingUid(), 863 WifiManager.ACTION_REQUEST_DISABLE)) { 864 return true; 865 } 866 } 867 } 868 869 mWifiController.sendMessage(CMD_WIFI_TOGGLED); 870 return true; 871 } 872 873 /** 874 * see {@link WifiManager#getWifiState()} 875 * @return One of {@link WifiManager#WIFI_STATE_DISABLED}, 876 * {@link WifiManager#WIFI_STATE_DISABLING}, 877 * {@link WifiManager#WIFI_STATE_ENABLED}, 878 * {@link WifiManager#WIFI_STATE_ENABLING}, 879 * {@link WifiManager#WIFI_STATE_UNKNOWN} 880 */ 881 @Override 882 public int getWifiEnabledState() { 883 enforceAccessPermission(); 884 if (mVerboseLoggingEnabled) { 885 mLog.info("getWifiEnabledState uid=%").c(Binder.getCallingUid()).flush(); 886 } 887 return mWifiStateMachine.syncGetWifiState(); 888 } 889 890 /** 891 * see {@link WifiManager#getWifiApState()} 892 * @return One of {@link WifiManager#WIFI_AP_STATE_DISABLED}, 893 * {@link WifiManager#WIFI_AP_STATE_DISABLING}, 894 * {@link WifiManager#WIFI_AP_STATE_ENABLED}, 895 * {@link WifiManager#WIFI_AP_STATE_ENABLING}, 896 * {@link WifiManager#WIFI_AP_STATE_FAILED} 897 */ 898 @Override 899 public int getWifiApEnabledState() { 900 enforceAccessPermission(); 901 if (mVerboseLoggingEnabled) { 902 mLog.info("getWifiApEnabledState uid=%").c(Binder.getCallingUid()).flush(); 903 } 904 905 // hand off work to our handler thread 906 MutableInt apState = new MutableInt(WifiManager.WIFI_AP_STATE_DISABLED); 907 mClientHandler.runWithScissors(() -> { 908 apState.value = mWifiApState; 909 }, RUN_WITH_SCISSORS_TIMEOUT_MILLIS); 910 return apState.value; 911 } 912 913 /** 914 * see {@link android.net.wifi.WifiManager#updateInterfaceIpState(String, int)} 915 * 916 * The possible modes include: {@link WifiManager#IFACE_IP_MODE_TETHERED}, 917 * {@link WifiManager#IFACE_IP_MODE_LOCAL_ONLY}, 918 * {@link WifiManager#IFACE_IP_MODE_CONFIGURATION_ERROR} 919 * 920 * @param ifaceName String name of the updated interface 921 * @param mode new operating mode of the interface 922 * 923 * @throws SecurityException if the caller does not have permission to call update 924 */ 925 @Override 926 public void updateInterfaceIpState(String ifaceName, int mode) { 927 // NETWORK_STACK is a signature only permission. 928 enforceNetworkStackPermission(); 929 mLog.info("updateInterfaceIpState uid=%").c(Binder.getCallingUid()).flush(); 930 931 // hand off the work to our handler thread 932 mClientHandler.post(() -> { 933 updateInterfaceIpStateInternal(ifaceName, mode); 934 }); 935 } 936 937 private void updateInterfaceIpStateInternal(String ifaceName, int mode) { 938 // update interface IP state related to tethering and hotspot 939 synchronized (mLocalOnlyHotspotRequests) { 940 // update the mode tracker here - we clear out state below 941 Integer previousMode = WifiManager.IFACE_IP_MODE_UNSPECIFIED; 942 if (ifaceName != null) { 943 previousMode = mIfaceIpModes.put(ifaceName, mode); 944 } 945 Slog.d(TAG, "updateInterfaceIpState: ifaceName=" + ifaceName + " mode=" + mode 946 + " previous mode= " + previousMode); 947 948 switch (mode) { 949 case WifiManager.IFACE_IP_MODE_LOCAL_ONLY: 950 // first make sure we have registered requests.. otherwise clean up 951 if (mLocalOnlyHotspotRequests.isEmpty()) { 952 // we don't have requests... stop the hotspot 953 stopSoftAp(); 954 updateInterfaceIpStateInternal(null, WifiManager.IFACE_IP_MODE_UNSPECIFIED); 955 return; 956 } 957 // LOHS is ready to go! Call our registered requestors! 958 sendHotspotStartedMessageToAllLOHSRequestInfoEntriesLocked(); 959 break; 960 case WifiManager.IFACE_IP_MODE_TETHERED: 961 // we have tethered an interface. we don't really act on this now other than if 962 // we have LOHS requests, and this is an issue. return incompatible mode for 963 // onFailed for the registered requestors since this can result from a race 964 // between a tether request and a hotspot request (tethering wins). 965 sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked( 966 LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE); 967 break; 968 case WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR: 969 Slog.d(TAG, "IP mode config error - need to clean up"); 970 if (mLocalOnlyHotspotRequests.isEmpty()) { 971 Slog.d(TAG, "no LOHS requests, stop softap"); 972 stopSoftAp(); 973 } else { 974 Slog.d(TAG, "we have LOHS requests, clean them up"); 975 // there was an error setting up the hotspot... trigger onFailed for the 976 // registered LOHS requestors 977 sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked( 978 LocalOnlyHotspotCallback.ERROR_GENERIC); 979 } 980 updateInterfaceIpStateInternal(null, WifiManager.IFACE_IP_MODE_UNSPECIFIED); 981 break; 982 case WifiManager.IFACE_IP_MODE_UNSPECIFIED: 983 if (ifaceName == null) { 984 // interface name is null, this is due to softap teardown. clear all 985 // entries for now. 986 // TODO: Deal with individual interfaces when we receive updates for them 987 mIfaceIpModes.clear(); 988 return; 989 } 990 break; 991 default: 992 mLog.warn("updateInterfaceIpStateInternal: unknown mode %").c(mode).flush(); 993 } 994 } 995 } 996 997 /** 998 * see {@link android.net.wifi.WifiManager#startSoftAp(WifiConfiguration)} 999 * @param wifiConfig SSID, security and channel details as part of WifiConfiguration 1000 * @return {@code true} if softap start was triggered 1001 * @throws SecurityException if the caller does not have permission to start softap 1002 */ 1003 @Override 1004 public boolean startSoftAp(WifiConfiguration wifiConfig) { 1005 // NETWORK_STACK is a signature only permission. 1006 enforceNetworkStackPermission(); 1007 1008 mLog.info("startSoftAp uid=%").c(Binder.getCallingUid()).flush(); 1009 1010 synchronized (mLocalOnlyHotspotRequests) { 1011 // If a tethering request comes in while we have LOHS running (or requested), call stop 1012 // for softap mode and restart softap with the tethering config. 1013 if (!mLocalOnlyHotspotRequests.isEmpty()) { 1014 stopSoftApInternal(); 1015 } 1016 return startSoftApInternal(wifiConfig, WifiManager.IFACE_IP_MODE_TETHERED); 1017 } 1018 } 1019 1020 /** 1021 * Internal method to start softap mode. Callers of this method should have already checked 1022 * proper permissions beyond the NetworkStack permission. 1023 */ 1024 private boolean startSoftApInternal(WifiConfiguration wifiConfig, int mode) { 1025 mLog.trace("startSoftApInternal uid=% mode=%") 1026 .c(Binder.getCallingUid()).c(mode).flush(); 1027 1028 // null wifiConfig is a meaningful input for CMD_SET_AP 1029 if (wifiConfig == null || WifiApConfigStore.validateApWifiConfiguration(wifiConfig)) { 1030 SoftApModeConfiguration softApConfig = new SoftApModeConfiguration(mode, wifiConfig); 1031 mWifiController.sendMessage(CMD_SET_AP, 1, 0, softApConfig); 1032 return true; 1033 } 1034 Slog.e(TAG, "Invalid WifiConfiguration"); 1035 return false; 1036 } 1037 1038 /** 1039 * see {@link android.net.wifi.WifiManager#stopSoftAp()} 1040 * @return {@code true} if softap stop was triggered 1041 * @throws SecurityException if the caller does not have permission to stop softap 1042 */ 1043 @Override 1044 public boolean stopSoftAp() { 1045 // NETWORK_STACK is a signature only permission. 1046 enforceNetworkStackPermission(); 1047 1048 // only permitted callers are allowed to this point - they must have gone through 1049 // connectivity service since this method is protected with the NETWORK_STACK PERMISSION 1050 1051 mLog.info("stopSoftAp uid=%").c(Binder.getCallingUid()).flush(); 1052 1053 synchronized (mLocalOnlyHotspotRequests) { 1054 // If a tethering request comes in while we have LOHS running (or requested), call stop 1055 // for softap mode and restart softap with the tethering config. 1056 if (!mLocalOnlyHotspotRequests.isEmpty()) { 1057 mLog.trace("Call to stop Tethering while LOHS is active," 1058 + " Registered LOHS callers will be updated when softap stopped.").flush(); 1059 } 1060 1061 return stopSoftApInternal(); 1062 } 1063 } 1064 1065 /** 1066 * Internal method to stop softap mode. Callers of this method should have already checked 1067 * proper permissions beyond the NetworkStack permission. 1068 */ 1069 private boolean stopSoftApInternal() { 1070 mLog.trace("stopSoftApInternal uid=%").c(Binder.getCallingUid()).flush(); 1071 1072 mWifiController.sendMessage(CMD_SET_AP, 0, 0); 1073 return true; 1074 } 1075 1076 /** 1077 * Callback to use with WifiStateMachine to receive events from WifiStateMachine 1078 * 1079 * @hide 1080 */ 1081 private final class SoftApCallbackImpl implements WifiManager.SoftApCallback { 1082 /** 1083 * Called when soft AP state changes. 1084 * 1085 * @param state new new AP state. One of {@link #WIFI_AP_STATE_DISABLED}, 1086 * {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED}, 1087 * {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED} 1088 * @param failureReason reason when in failed state. One of 1089 * {@link #SAP_START_FAILURE_GENERAL}, {@link #SAP_START_FAILURE_NO_CHANNEL} 1090 */ 1091 @Override 1092 public void onStateChanged(int state, int failureReason) { 1093 mSoftApState = state; 1094 1095 Iterator<ISoftApCallback> iterator = mRegisteredSoftApCallbacks.values().iterator(); 1096 while (iterator.hasNext()) { 1097 ISoftApCallback callback = iterator.next(); 1098 try { 1099 callback.onStateChanged(state, failureReason); 1100 } catch (RemoteException e) { 1101 Log.e(TAG, "onStateChanged: remote exception -- " + e); 1102 iterator.remove(); 1103 } 1104 } 1105 } 1106 1107 /** 1108 * Called when number of connected clients to soft AP changes. 1109 * 1110 * @param numClients number of connected clients to soft AP 1111 */ 1112 @Override 1113 public void onNumClientsChanged(int numClients) { 1114 mSoftApNumClients = numClients; 1115 1116 Iterator<ISoftApCallback> iterator = mRegisteredSoftApCallbacks.values().iterator(); 1117 while (iterator.hasNext()) { 1118 ISoftApCallback callback = iterator.next(); 1119 try { 1120 callback.onNumClientsChanged(numClients); 1121 } catch (RemoteException e) { 1122 Log.e(TAG, "onNumClientsChanged: remote exception -- " + e); 1123 iterator.remove(); 1124 } 1125 } 1126 } 1127 } 1128 1129 /** 1130 * see {@link android.net.wifi.WifiManager#registerSoftApCallback(SoftApCallback, Handler)} 1131 * 1132 * @param binder IBinder instance to allow cleanup if the app dies 1133 * @param callback Soft AP callback to register 1134 * @param callbackIdentifier Unique ID of the registering callback. This ID will be used to 1135 * unregister the callback. See {@link unregisterSoftApCallback(int)} 1136 * 1137 * @throws SecurityException if the caller does not have permission to register a callback 1138 * @throws RemoteException if remote exception happens 1139 * @throws IllegalArgumentException if the arguments are null or invalid 1140 */ 1141 @Override 1142 public void registerSoftApCallback(IBinder binder, ISoftApCallback callback, 1143 int callbackIdentifier) { 1144 // verify arguments 1145 if (binder == null) { 1146 throw new IllegalArgumentException("Binder must not be null"); 1147 } 1148 if (callback == null) { 1149 throw new IllegalArgumentException("Callback must not be null"); 1150 } 1151 1152 enforceNetworkSettingsPermission(); 1153 if (mVerboseLoggingEnabled) { 1154 mLog.info("registerSoftApCallback uid=%").c(Binder.getCallingUid()).flush(); 1155 } 1156 1157 // register for binder death 1158 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() { 1159 @Override 1160 public void binderDied() { 1161 binder.unlinkToDeath(this, 0); 1162 mClientHandler.post(() -> { 1163 mRegisteredSoftApCallbacks.remove(callbackIdentifier); 1164 }); 1165 } 1166 }; 1167 try { 1168 binder.linkToDeath(dr, 0); 1169 } catch (RemoteException e) { 1170 Log.e(TAG, "Error on linkToDeath - " + e); 1171 return; 1172 } 1173 1174 // post operation to handler thread 1175 mClientHandler.post(() -> { 1176 mRegisteredSoftApCallbacks.put(callbackIdentifier, callback); 1177 1178 if (mRegisteredSoftApCallbacks.size() > NUM_SOFT_AP_CALLBACKS_WTF_LIMIT) { 1179 Log.wtf(TAG, "Too many soft AP callbacks: " + mRegisteredSoftApCallbacks.size()); 1180 } else if (mRegisteredSoftApCallbacks.size() > NUM_SOFT_AP_CALLBACKS_WARN_LIMIT) { 1181 Log.w(TAG, "Too many soft AP callbacks: " + mRegisteredSoftApCallbacks.size()); 1182 } 1183 1184 // Update the client about the current state immediately after registering the callback 1185 try { 1186 callback.onStateChanged(mSoftApState, 0); 1187 callback.onNumClientsChanged(mSoftApNumClients); 1188 } catch (RemoteException e) { 1189 Log.e(TAG, "registerSoftApCallback: remote exception -- " + e); 1190 } 1191 1192 }); 1193 } 1194 1195 /** 1196 * see {@link android.net.wifi.WifiManager#unregisterSoftApCallback(SoftApCallback)} 1197 * 1198 * @param callbackIdentifier Unique ID of the callback to be unregistered. 1199 * 1200 * @throws SecurityException if the caller does not have permission to register a callback 1201 */ 1202 @Override 1203 public void unregisterSoftApCallback(int callbackIdentifier) { 1204 1205 enforceNetworkSettingsPermission(); 1206 if (mVerboseLoggingEnabled) { 1207 mLog.info("unregisterSoftApCallback uid=%").c(Binder.getCallingUid()).flush(); 1208 } 1209 1210 // post operation to handler thread 1211 mClientHandler.post(() -> { 1212 mRegisteredSoftApCallbacks.remove(callbackIdentifier); 1213 }); 1214 } 1215 1216 /** 1217 * Private method to handle SoftAp state changes 1218 * 1219 * <p> MUST be called from the WifiStateMachine thread. 1220 */ 1221 private void handleWifiApStateChange( 1222 int currentState, int previousState, int errorCode, String ifaceName, int mode) { 1223 // The AP state update from WifiStateMachine for softap 1224 Slog.d(TAG, "handleWifiApStateChange: currentState=" + currentState 1225 + " previousState=" + previousState + " errorCode= " + errorCode 1226 + " ifaceName=" + ifaceName + " mode=" + mode); 1227 1228 // update the tracking ap state variable 1229 mWifiApState = currentState; 1230 1231 // check if we have a failure - since it is possible (worst case scenario where 1232 // WifiController and WifiStateMachine are out of sync wrt modes) to get two FAILED 1233 // notifications in a row, we need to handle this first. 1234 if (currentState == WIFI_AP_STATE_FAILED) { 1235 // update registered LOHS callbacks if we see a failure 1236 synchronized (mLocalOnlyHotspotRequests) { 1237 int errorToReport = ERROR_GENERIC; 1238 if (errorCode == SAP_START_FAILURE_NO_CHANNEL) { 1239 errorToReport = ERROR_NO_CHANNEL; 1240 } 1241 // holding the required lock: send message to requestors and clear the list 1242 sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked( 1243 errorToReport); 1244 // also need to clear interface ip state - send null for now since we don't know 1245 // what interface (and we have one anyway) 1246 updateInterfaceIpStateInternal(null, WifiManager.IFACE_IP_MODE_UNSPECIFIED); 1247 } 1248 return; 1249 } 1250 1251 if (currentState == WIFI_AP_STATE_DISABLING || currentState == WIFI_AP_STATE_DISABLED) { 1252 // softap is shutting down or is down... let requestors know via the onStopped call 1253 synchronized (mLocalOnlyHotspotRequests) { 1254 // if we are currently in hotspot mode, then trigger onStopped for registered 1255 // requestors, otherwise something odd happened and we should clear state 1256 if (mIfaceIpModes.contains(WifiManager.IFACE_IP_MODE_LOCAL_ONLY)) { 1257 // holding the required lock: send message to requestors and clear the list 1258 sendHotspotStoppedMessageToAllLOHSRequestInfoEntriesLocked(); 1259 } else { 1260 // LOHS not active: report an error (still holding the required lock) 1261 sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked(ERROR_GENERIC); 1262 } 1263 // also clear interface ip state - send null for now since we don't know what 1264 // interface (and we only have one anyway) 1265 updateInterfaceIpState(null, WifiManager.IFACE_IP_MODE_UNSPECIFIED); 1266 } 1267 return; 1268 } 1269 1270 // remaining states are enabling or enabled... those are not used for the callbacks 1271 } 1272 1273 /** 1274 * Helper method to send a HOTSPOT_FAILED message to all registered LocalOnlyHotspotRequest 1275 * callers and clear the registrations. 1276 * 1277 * Callers should already hold the mLocalOnlyHotspotRequests lock. 1278 */ 1279 @GuardedBy("mLocalOnlyHotspotRequests") 1280 private void sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked(int arg1) { 1281 for (LocalOnlyHotspotRequestInfo requestor : mLocalOnlyHotspotRequests.values()) { 1282 try { 1283 requestor.sendHotspotFailedMessage(arg1); 1284 requestor.unlinkDeathRecipient(); 1285 } catch (RemoteException e) { 1286 // This will be cleaned up by binder death handling 1287 } 1288 } 1289 1290 // Since all callers were notified, now clear the registrations. 1291 mLocalOnlyHotspotRequests.clear(); 1292 } 1293 1294 /** 1295 * Helper method to send a HOTSPOT_STOPPED message to all registered LocalOnlyHotspotRequest 1296 * callers and clear the registrations. 1297 * 1298 * Callers should already hold the mLocalOnlyHotspotRequests lock. 1299 */ 1300 @GuardedBy("mLocalOnlyHotspotRequests") 1301 private void sendHotspotStoppedMessageToAllLOHSRequestInfoEntriesLocked() { 1302 for (LocalOnlyHotspotRequestInfo requestor : mLocalOnlyHotspotRequests.values()) { 1303 try { 1304 requestor.sendHotspotStoppedMessage(); 1305 requestor.unlinkDeathRecipient(); 1306 } catch (RemoteException e) { 1307 // This will be cleaned up by binder death handling 1308 } 1309 } 1310 1311 // Since all callers were notified, now clear the registrations. 1312 mLocalOnlyHotspotRequests.clear(); 1313 } 1314 1315 /** 1316 * Helper method to send a HOTSPOT_STARTED message to all registered LocalOnlyHotspotRequest 1317 * callers. 1318 * 1319 * Callers should already hold the mLocalOnlyHotspotRequests lock. 1320 */ 1321 @GuardedBy("mLocalOnlyHotspotRequests") 1322 private void sendHotspotStartedMessageToAllLOHSRequestInfoEntriesLocked() { 1323 for (LocalOnlyHotspotRequestInfo requestor : mLocalOnlyHotspotRequests.values()) { 1324 try { 1325 requestor.sendHotspotStartedMessage(mLocalOnlyHotspotConfig); 1326 } catch (RemoteException e) { 1327 // This will be cleaned up by binder death handling 1328 } 1329 } 1330 } 1331 1332 /** 1333 * Temporary method used for testing while startLocalOnlyHotspot is not fully implemented. This 1334 * method allows unit tests to register callbacks directly for testing mechanisms triggered by 1335 * softap mode changes. 1336 */ 1337 @VisibleForTesting 1338 void registerLOHSForTest(int pid, LocalOnlyHotspotRequestInfo request) { 1339 mLocalOnlyHotspotRequests.put(pid, request); 1340 } 1341 1342 /** 1343 * Method to start LocalOnlyHotspot. In this method, permissions, settings and modes are 1344 * checked to verify that we can enter softapmode. This method returns 1345 * {@link LocalOnlyHotspotCallback#REQUEST_REGISTERED} if we will attempt to start, otherwise, 1346 * possible startup erros may include tethering being disallowed failure reason {@link 1347 * LocalOnlyHotspotCallback#ERROR_TETHERING_DISALLOWED} or an incompatible mode failure reason 1348 * {@link LocalOnlyHotspotCallback#ERROR_INCOMPATIBLE_MODE}. 1349 * 1350 * see {@link WifiManager#startLocalOnlyHotspot(LocalOnlyHotspotCallback)} 1351 * 1352 * @param messenger Messenger to send messages to the corresponding WifiManager. 1353 * @param binder IBinder instance to allow cleanup if the app dies 1354 * @param packageName String name of the calling package 1355 * 1356 * @return int return code for attempt to start LocalOnlyHotspot. 1357 * 1358 * @throws SecurityException if the caller does not have permission to start a Local Only 1359 * Hotspot. 1360 * @throws IllegalStateException if the caller attempts to start the LocalOnlyHotspot while they 1361 * have an outstanding request. 1362 */ 1363 @Override 1364 public int startLocalOnlyHotspot(Messenger messenger, IBinder binder, String packageName) { 1365 // first check if the caller has permission to start a local only hotspot 1366 // need to check for WIFI_STATE_CHANGE and location permission 1367 final int uid = Binder.getCallingUid(); 1368 final int pid = Binder.getCallingPid(); 1369 1370 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 1371 return LocalOnlyHotspotCallback.ERROR_GENERIC; 1372 } 1373 enforceLocationPermission(packageName, uid); 1374 // also need to verify that Locations services are enabled. 1375 if (mSettingsStore.getLocationModeSetting(mContext) == Settings.Secure.LOCATION_MODE_OFF) { 1376 throw new SecurityException("Location mode is not enabled."); 1377 } 1378 1379 // verify that tethering is not disabled 1380 if (mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING)) { 1381 return LocalOnlyHotspotCallback.ERROR_TETHERING_DISALLOWED; 1382 } 1383 1384 // the app should be in the foreground 1385 try { 1386 if (!mFrameworkFacade.isAppForeground(uid)) { 1387 return LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE; 1388 } 1389 } catch (RemoteException e) { 1390 mLog.warn("RemoteException during isAppForeground when calling startLOHS").flush(); 1391 return LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE; 1392 } 1393 1394 mLog.info("startLocalOnlyHotspot uid=% pid=%").c(uid).c(pid).flush(); 1395 1396 synchronized (mLocalOnlyHotspotRequests) { 1397 // check if we are currently tethering 1398 if (mIfaceIpModes.contains(WifiManager.IFACE_IP_MODE_TETHERED)) { 1399 // Tethering is enabled, cannot start LocalOnlyHotspot 1400 mLog.info("Cannot start localOnlyHotspot when WiFi Tethering is active.").flush(); 1401 return LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE; 1402 } 1403 1404 // does this caller already have a request? 1405 LocalOnlyHotspotRequestInfo request = mLocalOnlyHotspotRequests.get(pid); 1406 if (request != null) { 1407 mLog.trace("caller already has an active request").flush(); 1408 throw new IllegalStateException( 1409 "Caller already has an active LocalOnlyHotspot request"); 1410 } 1411 1412 // now create the new LOHS request info object 1413 request = new LocalOnlyHotspotRequestInfo(binder, messenger, 1414 new LocalOnlyRequestorCallback()); 1415 1416 // check current operating state and take action if needed 1417 if (mIfaceIpModes.contains(WifiManager.IFACE_IP_MODE_LOCAL_ONLY)) { 1418 // LOHS is already active, send out what is running 1419 try { 1420 mLog.trace("LOHS already up, trigger onStarted callback").flush(); 1421 request.sendHotspotStartedMessage(mLocalOnlyHotspotConfig); 1422 } catch (RemoteException e) { 1423 return LocalOnlyHotspotCallback.ERROR_GENERIC; 1424 } 1425 } else if (mLocalOnlyHotspotRequests.isEmpty()) { 1426 // this is the first request, then set up our config and start LOHS 1427 mLocalOnlyHotspotConfig = 1428 WifiApConfigStore.generateLocalOnlyHotspotConfig(mContext); 1429 startSoftApInternal(mLocalOnlyHotspotConfig, WifiManager.IFACE_IP_MODE_LOCAL_ONLY); 1430 } 1431 1432 mLocalOnlyHotspotRequests.put(pid, request); 1433 return LocalOnlyHotspotCallback.REQUEST_REGISTERED; 1434 } 1435 } 1436 1437 /** 1438 * see {@link WifiManager#stopLocalOnlyHotspot()} 1439 * 1440 * @throws SecurityException if the caller does not have permission to stop a Local Only 1441 * Hotspot. 1442 */ 1443 @Override 1444 public void stopLocalOnlyHotspot() { 1445 // don't do a permission check here. if the app's permission to change the wifi state is 1446 // revoked, we still want them to be able to stop a previously created hotspot (otherwise 1447 // it could cost the user money). When the app created the hotspot, its permission was 1448 // checked. 1449 final int uid = Binder.getCallingUid(); 1450 final int pid = Binder.getCallingPid(); 1451 1452 mLog.info("stopLocalOnlyHotspot uid=% pid=%").c(uid).c(pid).flush(); 1453 1454 synchronized (mLocalOnlyHotspotRequests) { 1455 // was the caller already registered? check request tracker - return false if not 1456 LocalOnlyHotspotRequestInfo requestInfo = mLocalOnlyHotspotRequests.get(pid); 1457 if (requestInfo == null) { 1458 return; 1459 } 1460 requestInfo.unlinkDeathRecipient(); 1461 unregisterCallingAppAndStopLocalOnlyHotspot(requestInfo); 1462 } // end synchronized 1463 } 1464 1465 /** 1466 * Helper method to unregister LocalOnlyHotspot requestors and stop the hotspot if needed. 1467 */ 1468 private void unregisterCallingAppAndStopLocalOnlyHotspot(LocalOnlyHotspotRequestInfo request) { 1469 mLog.trace("unregisterCallingAppAndStopLocalOnlyHotspot pid=%").c(request.getPid()).flush(); 1470 1471 synchronized (mLocalOnlyHotspotRequests) { 1472 if (mLocalOnlyHotspotRequests.remove(request.getPid()) == null) { 1473 mLog.trace("LocalOnlyHotspotRequestInfo not found to remove").flush(); 1474 return; 1475 } 1476 1477 if (mLocalOnlyHotspotRequests.isEmpty()) { 1478 mLocalOnlyHotspotConfig = null; 1479 updateInterfaceIpStateInternal(null, WifiManager.IFACE_IP_MODE_UNSPECIFIED); 1480 // if that was the last caller, then call stopSoftAp as WifiService 1481 long identity = Binder.clearCallingIdentity(); 1482 try { 1483 stopSoftApInternal(); 1484 } finally { 1485 Binder.restoreCallingIdentity(identity); 1486 } 1487 } 1488 } 1489 } 1490 1491 /** 1492 * see {@link WifiManager#watchLocalOnlyHotspot(LocalOnlyHotspotObserver)} 1493 * 1494 * This call requires the android.permission.NETWORK_SETTINGS permission. 1495 * 1496 * @param messenger Messenger to send messages to the corresponding WifiManager. 1497 * @param binder IBinder instance to allow cleanup if the app dies 1498 * 1499 * @throws SecurityException if the caller does not have permission to watch Local Only Hotspot 1500 * status updates. 1501 * @throws IllegalStateException if the caller attempts to watch LocalOnlyHotspot updates with 1502 * an existing subscription. 1503 */ 1504 @Override 1505 public void startWatchLocalOnlyHotspot(Messenger messenger, IBinder binder) { 1506 // NETWORK_SETTINGS is a signature only permission. 1507 enforceNetworkSettingsPermission(); 1508 1509 throw new UnsupportedOperationException("LocalOnlyHotspot is still in development"); 1510 } 1511 1512 /** 1513 * see {@link WifiManager#unregisterLocalOnlyHotspotObserver()} 1514 */ 1515 @Override 1516 public void stopWatchLocalOnlyHotspot() { 1517 // NETWORK_STACK is a signature only permission. 1518 enforceNetworkSettingsPermission(); 1519 throw new UnsupportedOperationException("LocalOnlyHotspot is still in development"); 1520 } 1521 1522 /** 1523 * see {@link WifiManager#getWifiApConfiguration()} 1524 * @return soft access point configuration 1525 * @throws SecurityException if the caller does not have permission to retrieve the softap 1526 * config 1527 */ 1528 @Override 1529 public WifiConfiguration getWifiApConfiguration() { 1530 enforceAccessPermission(); 1531 int uid = Binder.getCallingUid(); 1532 // only allow Settings UI to get the saved SoftApConfig 1533 if (!mWifiPermissionsUtil.checkConfigOverridePermission(uid)) { 1534 // random apps should not be allowed to read the user specified config 1535 throw new SecurityException("App not allowed to read or update stored WiFi Ap config " 1536 + "(uid = " + uid + ")"); 1537 } 1538 mLog.info("getWifiApConfiguration uid=%").c(uid).flush(); 1539 1540 // hand off work to the WSM handler thread to sync work between calls and SoftApManager 1541 // starting up softap 1542 final Mutable<WifiConfiguration> config = new Mutable(); 1543 boolean success = mWifiInjector.getWifiStateMachineHandler().runWithScissors(() -> { 1544 config.value = mWifiApConfigStore.getApConfiguration(); 1545 }, RUN_WITH_SCISSORS_TIMEOUT_MILLIS); 1546 if (success) { 1547 return config.value; 1548 } 1549 Log.e(TAG, "Failed to post runnable to fetch ap config"); 1550 return new WifiConfiguration(); 1551 } 1552 1553 /** 1554 * see {@link WifiManager#setWifiApConfiguration(WifiConfiguration)} 1555 * @param wifiConfig WifiConfiguration details for soft access point 1556 * @return boolean indicating success or failure of the operation 1557 * @throws SecurityException if the caller does not have permission to write the softap config 1558 */ 1559 @Override 1560 public boolean setWifiApConfiguration(WifiConfiguration wifiConfig, String packageName) { 1561 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 1562 return false; 1563 } 1564 int uid = Binder.getCallingUid(); 1565 // only allow Settings UI to write the stored SoftApConfig 1566 if (!mWifiPermissionsUtil.checkConfigOverridePermission(uid)) { 1567 // random apps should not be allowed to read the user specified config 1568 throw new SecurityException("App not allowed to read or update stored WiFi AP config " 1569 + "(uid = " + uid + ")"); 1570 } 1571 mLog.info("setWifiApConfiguration uid=%").c(uid).flush(); 1572 if (wifiConfig == null) 1573 return false; 1574 if (WifiApConfigStore.validateApWifiConfiguration(wifiConfig)) { 1575 mWifiStateMachineHandler.post(() -> { 1576 mWifiApConfigStore.setApConfiguration(wifiConfig); 1577 }); 1578 return true; 1579 } else { 1580 Slog.e(TAG, "Invalid WifiConfiguration"); 1581 return false; 1582 } 1583 } 1584 1585 /** 1586 * see {@link android.net.wifi.WifiManager#isScanAlwaysAvailable()} 1587 */ 1588 @Override 1589 public boolean isScanAlwaysAvailable() { 1590 enforceAccessPermission(); 1591 if (mVerboseLoggingEnabled) { 1592 mLog.info("isScanAlwaysAvailable uid=%").c(Binder.getCallingUid()).flush(); 1593 } 1594 return mSettingsStore.isScanAlwaysAvailable(); 1595 } 1596 1597 /** 1598 * see {@link android.net.wifi.WifiManager#disconnect()} 1599 */ 1600 @Override 1601 public void disconnect(String packageName) { 1602 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 1603 return; 1604 } 1605 mLog.info("disconnect uid=%").c(Binder.getCallingUid()).flush(); 1606 mWifiStateMachine.disconnectCommand(); 1607 } 1608 1609 /** 1610 * see {@link android.net.wifi.WifiManager#reconnect()} 1611 */ 1612 @Override 1613 public void reconnect(String packageName) { 1614 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 1615 return; 1616 } 1617 mLog.info("reconnect uid=%").c(Binder.getCallingUid()).flush(); 1618 mWifiStateMachine.reconnectCommand(new WorkSource(Binder.getCallingUid())); 1619 } 1620 1621 /** 1622 * see {@link android.net.wifi.WifiManager#reassociate()} 1623 */ 1624 @Override 1625 public void reassociate(String packageName) { 1626 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 1627 return; 1628 } 1629 mLog.info("reassociate uid=%").c(Binder.getCallingUid()).flush(); 1630 mWifiStateMachine.reassociateCommand(); 1631 } 1632 1633 /** 1634 * see {@link android.net.wifi.WifiManager#getSupportedFeatures} 1635 */ 1636 @Override 1637 public int getSupportedFeatures() { 1638 enforceAccessPermission(); 1639 if (mVerboseLoggingEnabled) { 1640 mLog.info("getSupportedFeatures uid=%").c(Binder.getCallingUid()).flush(); 1641 } 1642 if (mWifiStateMachineChannel != null) { 1643 return mWifiStateMachine.syncGetSupportedFeatures(mWifiStateMachineChannel); 1644 } else { 1645 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1646 return 0; 1647 } 1648 } 1649 1650 @Override 1651 public void requestActivityInfo(ResultReceiver result) { 1652 Bundle bundle = new Bundle(); 1653 if (mVerboseLoggingEnabled) { 1654 mLog.info("requestActivityInfo uid=%").c(Binder.getCallingUid()).flush(); 1655 } 1656 bundle.putParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY, reportActivityInfo()); 1657 result.send(0, bundle); 1658 } 1659 1660 /** 1661 * see {@link android.net.wifi.WifiManager#getControllerActivityEnergyInfo(int)} 1662 */ 1663 @Override 1664 public WifiActivityEnergyInfo reportActivityInfo() { 1665 enforceAccessPermission(); 1666 if (mVerboseLoggingEnabled) { 1667 mLog.info("reportActivityInfo uid=%").c(Binder.getCallingUid()).flush(); 1668 } 1669 if ((getSupportedFeatures() & WifiManager.WIFI_FEATURE_LINK_LAYER_STATS) == 0) { 1670 return null; 1671 } 1672 WifiLinkLayerStats stats; 1673 WifiActivityEnergyInfo energyInfo = null; 1674 if (mWifiStateMachineChannel != null) { 1675 stats = mWifiStateMachine.syncGetLinkLayerStats(mWifiStateMachineChannel); 1676 if (stats != null) { 1677 final double rxIdleCurrent = mPowerProfile.getAveragePower( 1678 PowerProfile.POWER_WIFI_CONTROLLER_IDLE); 1679 final double rxCurrent = mPowerProfile.getAveragePower( 1680 PowerProfile.POWER_WIFI_CONTROLLER_RX); 1681 final double txCurrent = mPowerProfile.getAveragePower( 1682 PowerProfile.POWER_WIFI_CONTROLLER_TX); 1683 final double voltage = mPowerProfile.getAveragePower( 1684 PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0; 1685 final long rxIdleTime = stats.on_time - stats.tx_time - stats.rx_time; 1686 final long[] txTimePerLevel; 1687 if (stats.tx_time_per_level != null) { 1688 txTimePerLevel = new long[stats.tx_time_per_level.length]; 1689 for (int i = 0; i < txTimePerLevel.length; i++) { 1690 txTimePerLevel[i] = stats.tx_time_per_level[i]; 1691 // TODO(b/27227497): Need to read the power consumed per level from config 1692 } 1693 } else { 1694 // This will happen if the HAL get link layer API returned null. 1695 txTimePerLevel = new long[0]; 1696 } 1697 final long energyUsed = (long)((stats.tx_time * txCurrent + 1698 stats.rx_time * rxCurrent + 1699 rxIdleTime * rxIdleCurrent) * voltage); 1700 if (VDBG || rxIdleTime < 0 || stats.on_time < 0 || stats.tx_time < 0 || 1701 stats.rx_time < 0 || stats.on_time_scan < 0 || energyUsed < 0) { 1702 StringBuilder sb = new StringBuilder(); 1703 sb.append(" rxIdleCur=" + rxIdleCurrent); 1704 sb.append(" rxCur=" + rxCurrent); 1705 sb.append(" txCur=" + txCurrent); 1706 sb.append(" voltage=" + voltage); 1707 sb.append(" on_time=" + stats.on_time); 1708 sb.append(" tx_time=" + stats.tx_time); 1709 sb.append(" tx_time_per_level=" + Arrays.toString(txTimePerLevel)); 1710 sb.append(" rx_time=" + stats.rx_time); 1711 sb.append(" rxIdleTime=" + rxIdleTime); 1712 sb.append(" scan_time=" + stats.on_time_scan); 1713 sb.append(" energy=" + energyUsed); 1714 Log.d(TAG, " reportActivityInfo: " + sb.toString()); 1715 } 1716 1717 // Convert the LinkLayerStats into EnergyActivity 1718 energyInfo = new WifiActivityEnergyInfo(mClock.getElapsedSinceBootMillis(), 1719 WifiActivityEnergyInfo.STACK_STATE_STATE_IDLE, stats.tx_time, 1720 txTimePerLevel, stats.rx_time, stats.on_time_scan, rxIdleTime, energyUsed); 1721 } 1722 if (energyInfo != null && energyInfo.isValid()) { 1723 return energyInfo; 1724 } else { 1725 return null; 1726 } 1727 } else { 1728 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1729 return null; 1730 } 1731 } 1732 1733 /** 1734 * see {@link android.net.wifi.WifiManager#getConfiguredNetworks()} 1735 * @return the list of configured networks 1736 */ 1737 @Override 1738 public ParceledListSlice<WifiConfiguration> getConfiguredNetworks() { 1739 enforceAccessPermission(); 1740 if (mVerboseLoggingEnabled) { 1741 mLog.info("getConfiguredNetworks uid=%").c(Binder.getCallingUid()).flush(); 1742 } 1743 if (mWifiStateMachineChannel != null) { 1744 List<WifiConfiguration> configs = mWifiStateMachine.syncGetConfiguredNetworks( 1745 Binder.getCallingUid(), mWifiStateMachineChannel); 1746 if (configs != null) { 1747 return new ParceledListSlice<WifiConfiguration>(configs); 1748 } 1749 } else { 1750 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1751 } 1752 return null; 1753 } 1754 1755 /** 1756 * see {@link android.net.wifi.WifiManager#getPrivilegedConfiguredNetworks()} 1757 * @return the list of configured networks with real preSharedKey 1758 */ 1759 @Override 1760 public ParceledListSlice<WifiConfiguration> getPrivilegedConfiguredNetworks() { 1761 enforceReadCredentialPermission(); 1762 enforceAccessPermission(); 1763 if (mVerboseLoggingEnabled) { 1764 mLog.info("getPrivilegedConfiguredNetworks uid=%").c(Binder.getCallingUid()).flush(); 1765 } 1766 if (mWifiStateMachineChannel != null) { 1767 List<WifiConfiguration> configs = 1768 mWifiStateMachine.syncGetPrivilegedConfiguredNetwork(mWifiStateMachineChannel); 1769 if (configs != null) { 1770 return new ParceledListSlice<WifiConfiguration>(configs); 1771 } 1772 } else { 1773 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1774 } 1775 return null; 1776 } 1777 1778 /** 1779 * Returns a WifiConfiguration for a Passpoint network matching this ScanResult. 1780 * 1781 * @param scanResult scanResult that represents the BSSID 1782 * @return {@link WifiConfiguration} that matches this BSSID or null 1783 */ 1784 @Override 1785 public WifiConfiguration getMatchingWifiConfig(ScanResult scanResult) { 1786 enforceAccessPermission(); 1787 if (mVerboseLoggingEnabled) { 1788 mLog.info("getMatchingWifiConfig uid=%").c(Binder.getCallingUid()).flush(); 1789 } 1790 if (!mContext.getPackageManager().hasSystemFeature( 1791 PackageManager.FEATURE_WIFI_PASSPOINT)) { 1792 throw new UnsupportedOperationException("Passpoint not enabled"); 1793 } 1794 return mWifiStateMachine.syncGetMatchingWifiConfig(scanResult, mWifiStateMachineChannel); 1795 } 1796 1797 /** 1798 * Return the list of all matching Wifi configurations for this ScanResult. 1799 * 1800 * An empty list will be returned when no configurations are installed or if no configurations 1801 * match the ScanResult. 1802 * 1803 * @param scanResult scanResult that represents the BSSID 1804 * @return A list of {@link WifiConfiguration} 1805 */ 1806 @Override 1807 public List<WifiConfiguration> getAllMatchingWifiConfigs(ScanResult scanResult) { 1808 enforceAccessPermission(); 1809 if (mVerboseLoggingEnabled) { 1810 mLog.info("getMatchingPasspointConfigurations uid=%").c(Binder.getCallingUid()).flush(); 1811 } 1812 if (!mContext.getPackageManager().hasSystemFeature( 1813 PackageManager.FEATURE_WIFI_PASSPOINT)) { 1814 throw new UnsupportedOperationException("Passpoint not enabled"); 1815 } 1816 return mWifiStateMachine.getAllMatchingWifiConfigs(scanResult, mWifiStateMachineChannel); 1817 } 1818 1819 /** 1820 * Returns list of OSU (Online Sign-Up) providers associated with the given Passpoint network. 1821 * 1822 * @param scanResult scanResult of the Passpoint AP 1823 * @return List of {@link OsuProvider} 1824 */ 1825 @Override 1826 public List<OsuProvider> getMatchingOsuProviders(ScanResult scanResult) { 1827 enforceAccessPermission(); 1828 if (mVerboseLoggingEnabled) { 1829 mLog.info("getMatchingOsuProviders uid=%").c(Binder.getCallingUid()).flush(); 1830 } 1831 if (!mContext.getPackageManager().hasSystemFeature( 1832 PackageManager.FEATURE_WIFI_PASSPOINT)) { 1833 throw new UnsupportedOperationException("Passpoint not enabled"); 1834 } 1835 return mWifiStateMachine.syncGetMatchingOsuProviders(scanResult, mWifiStateMachineChannel); 1836 } 1837 1838 /** 1839 * see {@link android.net.wifi.WifiManager#addOrUpdateNetwork(WifiConfiguration)} 1840 * @return the supplicant-assigned identifier for the new or updated 1841 * network if the operation succeeds, or {@code -1} if it fails 1842 */ 1843 @Override 1844 public int addOrUpdateNetwork(WifiConfiguration config, String packageName) { 1845 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 1846 return -1; 1847 } 1848 mLog.info("addOrUpdateNetwork uid=%").c(Binder.getCallingUid()).flush(); 1849 1850 // Previously, this API is overloaded for installing Passpoint profiles. Now 1851 // that we have a dedicated API for doing it, redirect the call to the dedicated API. 1852 if (config.isPasspoint()) { 1853 PasspointConfiguration passpointConfig = 1854 PasspointProvider.convertFromWifiConfig(config); 1855 if (passpointConfig.getCredential() == null) { 1856 Slog.e(TAG, "Missing credential for Passpoint profile"); 1857 return -1; 1858 } 1859 // Copy over certificates and keys. 1860 passpointConfig.getCredential().setCaCertificate( 1861 config.enterpriseConfig.getCaCertificate()); 1862 passpointConfig.getCredential().setClientCertificateChain( 1863 config.enterpriseConfig.getClientCertificateChain()); 1864 passpointConfig.getCredential().setClientPrivateKey( 1865 config.enterpriseConfig.getClientPrivateKey()); 1866 if (!addOrUpdatePasspointConfiguration(passpointConfig, packageName)) { 1867 Slog.e(TAG, "Failed to add Passpoint profile"); 1868 return -1; 1869 } 1870 // There is no network ID associated with a Passpoint profile. 1871 return 0; 1872 } 1873 1874 if (config != null) { 1875 //TODO: pass the Uid the WifiStateMachine as a message parameter 1876 Slog.i("addOrUpdateNetwork", " uid = " + Integer.toString(Binder.getCallingUid()) 1877 + " SSID " + config.SSID 1878 + " nid=" + Integer.toString(config.networkId)); 1879 if (config.networkId == WifiConfiguration.INVALID_NETWORK_ID) { 1880 config.creatorUid = Binder.getCallingUid(); 1881 } else { 1882 config.lastUpdateUid = Binder.getCallingUid(); 1883 } 1884 if (mWifiStateMachineChannel != null) { 1885 return mWifiStateMachine.syncAddOrUpdateNetwork(mWifiStateMachineChannel, config); 1886 } else { 1887 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1888 return -1; 1889 } 1890 } else { 1891 Slog.e(TAG, "bad network configuration"); 1892 return -1; 1893 } 1894 } 1895 1896 public static void verifyCert(X509Certificate caCert) 1897 throws GeneralSecurityException, IOException { 1898 CertificateFactory factory = CertificateFactory.getInstance("X.509"); 1899 CertPathValidator validator = 1900 CertPathValidator.getInstance(CertPathValidator.getDefaultType()); 1901 CertPath path = factory.generateCertPath( 1902 Arrays.asList(caCert)); 1903 KeyStore ks = KeyStore.getInstance("AndroidCAStore"); 1904 ks.load(null, null); 1905 PKIXParameters params = new PKIXParameters(ks); 1906 params.setRevocationEnabled(false); 1907 validator.validate(path, params); 1908 } 1909 1910 /** 1911 * See {@link android.net.wifi.WifiManager#removeNetwork(int)} 1912 * @param netId the integer that identifies the network configuration 1913 * to the supplicant 1914 * @return {@code true} if the operation succeeded 1915 */ 1916 @Override 1917 public boolean removeNetwork(int netId, String packageName) { 1918 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 1919 return false; 1920 } 1921 mLog.info("removeNetwork uid=%").c(Binder.getCallingUid()).flush(); 1922 // TODO Add private logging for netId b/33807876 1923 if (mWifiStateMachineChannel != null) { 1924 return mWifiStateMachine.syncRemoveNetwork(mWifiStateMachineChannel, netId); 1925 } else { 1926 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1927 return false; 1928 } 1929 } 1930 1931 /** 1932 * See {@link android.net.wifi.WifiManager#enableNetwork(int, boolean)} 1933 * @param netId the integer that identifies the network configuration 1934 * to the supplicant 1935 * @param disableOthers if true, disable all other networks. 1936 * @return {@code true} if the operation succeeded 1937 */ 1938 @Override 1939 public boolean enableNetwork(int netId, boolean disableOthers, String packageName) { 1940 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 1941 return false; 1942 } 1943 // TODO b/33807876 Log netId 1944 mLog.info("enableNetwork uid=% disableOthers=%") 1945 .c(Binder.getCallingUid()) 1946 .c(disableOthers).flush(); 1947 1948 if (mWifiStateMachineChannel != null) { 1949 return mWifiStateMachine.syncEnableNetwork(mWifiStateMachineChannel, netId, 1950 disableOthers); 1951 } else { 1952 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1953 return false; 1954 } 1955 } 1956 1957 /** 1958 * See {@link android.net.wifi.WifiManager#disableNetwork(int)} 1959 * @param netId the integer that identifies the network configuration 1960 * to the supplicant 1961 * @return {@code true} if the operation succeeded 1962 */ 1963 @Override 1964 public boolean disableNetwork(int netId, String packageName) { 1965 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 1966 return false; 1967 } 1968 // TODO b/33807876 Log netId 1969 mLog.info("disableNetwork uid=%").c(Binder.getCallingUid()).flush(); 1970 1971 if (mWifiStateMachineChannel != null) { 1972 return mWifiStateMachine.syncDisableNetwork(mWifiStateMachineChannel, netId); 1973 } else { 1974 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1975 return false; 1976 } 1977 } 1978 1979 /** 1980 * See {@link android.net.wifi.WifiManager#getConnectionInfo()} 1981 * @return the Wi-Fi information, contained in {@link WifiInfo}. 1982 */ 1983 @Override 1984 public WifiInfo getConnectionInfo(String callingPackage) { 1985 enforceAccessPermission(); 1986 int uid = Binder.getCallingUid(); 1987 if (mVerboseLoggingEnabled) { 1988 mLog.info("getConnectionInfo uid=%").c(uid).flush(); 1989 } 1990 long ident = Binder.clearCallingIdentity(); 1991 try { 1992 WifiInfo result = mWifiStateMachine.syncRequestConnectionInfo(); 1993 boolean hideDefaultMacAddress = true; 1994 boolean hideBssidAndSsid = true; 1995 1996 try { 1997 if (mWifiInjector.getWifiPermissionsWrapper().getLocalMacAddressPermission(uid) 1998 == PackageManager.PERMISSION_GRANTED) { 1999 hideDefaultMacAddress = false; 2000 } 2001 mWifiPermissionsUtil.enforceCanAccessScanResults(callingPackage, uid); 2002 hideBssidAndSsid = false; 2003 } catch (RemoteException e) { 2004 Log.e(TAG, "Error checking receiver permission", e); 2005 } catch (SecurityException e) { 2006 } 2007 if (hideDefaultMacAddress) { 2008 result.setMacAddress(WifiInfo.DEFAULT_MAC_ADDRESS); 2009 } 2010 if (hideBssidAndSsid) { 2011 result.setBSSID(WifiInfo.DEFAULT_MAC_ADDRESS); 2012 result.setSSID(WifiSsid.createFromHex(null)); 2013 } 2014 if (mVerboseLoggingEnabled && (hideBssidAndSsid || hideDefaultMacAddress)) { 2015 mLog.v("getConnectionInfo: hideBssidAndSSid=" + hideBssidAndSsid 2016 + ", hideDefaultMacAddress=" + hideDefaultMacAddress); 2017 } 2018 return result; 2019 } finally { 2020 Binder.restoreCallingIdentity(ident); 2021 } 2022 } 2023 2024 /** 2025 * Return the results of the most recent access point scan, in the form of 2026 * a list of {@link ScanResult} objects. 2027 * @return the list of results 2028 */ 2029 @Override 2030 public List<ScanResult> getScanResults(String callingPackage) { 2031 enforceAccessPermission(); 2032 int uid = Binder.getCallingUid(); 2033 long ident = Binder.clearCallingIdentity(); 2034 if (mVerboseLoggingEnabled) { 2035 mLog.info("getScanResults uid=%").c(uid).flush(); 2036 } 2037 try { 2038 mWifiPermissionsUtil.enforceCanAccessScanResults(callingPackage, uid); 2039 final List<ScanResult> scanResults = new ArrayList<>(); 2040 boolean success = mWifiInjector.getWifiStateMachineHandler().runWithScissors(() -> { 2041 scanResults.addAll(mScanRequestProxy.getScanResults()); 2042 }, RUN_WITH_SCISSORS_TIMEOUT_MILLIS); 2043 if (!success) { 2044 Log.e(TAG, "Failed to post runnable to fetch scan results"); 2045 } 2046 return scanResults; 2047 } catch (SecurityException e) { 2048 return new ArrayList<ScanResult>(); 2049 } finally { 2050 Binder.restoreCallingIdentity(ident); 2051 } 2052 } 2053 2054 /** 2055 * Add or update a Passpoint configuration. 2056 * 2057 * @param config The Passpoint configuration to be added 2058 * @return true on success or false on failure 2059 */ 2060 @Override 2061 public boolean addOrUpdatePasspointConfiguration( 2062 PasspointConfiguration config, String packageName) { 2063 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 2064 return false; 2065 } 2066 mLog.info("addorUpdatePasspointConfiguration uid=%").c(Binder.getCallingUid()).flush(); 2067 if (!mContext.getPackageManager().hasSystemFeature( 2068 PackageManager.FEATURE_WIFI_PASSPOINT)) { 2069 throw new UnsupportedOperationException("Passpoint not enabled"); 2070 } 2071 return mWifiStateMachine.syncAddOrUpdatePasspointConfig(mWifiStateMachineChannel, config, 2072 Binder.getCallingUid()); 2073 } 2074 2075 /** 2076 * Remove the Passpoint configuration identified by its FQDN (Fully Qualified Domain Name). 2077 * 2078 * @param fqdn The FQDN of the Passpoint configuration to be removed 2079 * @return true on success or false on failure 2080 */ 2081 @Override 2082 public boolean removePasspointConfiguration(String fqdn, String packageName) { 2083 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 2084 return false; 2085 } 2086 mLog.info("removePasspointConfiguration uid=%").c(Binder.getCallingUid()).flush(); 2087 if (!mContext.getPackageManager().hasSystemFeature( 2088 PackageManager.FEATURE_WIFI_PASSPOINT)) { 2089 throw new UnsupportedOperationException("Passpoint not enabled"); 2090 } 2091 return mWifiStateMachine.syncRemovePasspointConfig(mWifiStateMachineChannel, fqdn); 2092 } 2093 2094 /** 2095 * Return the list of the installed Passpoint configurations. 2096 * 2097 * An empty list will be returned when no configuration is installed. 2098 * 2099 * @return A list of {@link PasspointConfiguration} 2100 */ 2101 @Override 2102 public List<PasspointConfiguration> getPasspointConfigurations() { 2103 enforceAccessPermission(); 2104 if (mVerboseLoggingEnabled) { 2105 mLog.info("getPasspointConfigurations uid=%").c(Binder.getCallingUid()).flush(); 2106 } 2107 if (!mContext.getPackageManager().hasSystemFeature( 2108 PackageManager.FEATURE_WIFI_PASSPOINT)) { 2109 throw new UnsupportedOperationException("Passpoint not enabled"); 2110 } 2111 return mWifiStateMachine.syncGetPasspointConfigs(mWifiStateMachineChannel); 2112 } 2113 2114 /** 2115 * Query for a Hotspot 2.0 release 2 OSU icon 2116 * @param bssid The BSSID of the AP 2117 * @param fileName Icon file name 2118 */ 2119 @Override 2120 public void queryPasspointIcon(long bssid, String fileName) { 2121 enforceAccessPermission(); 2122 mLog.info("queryPasspointIcon uid=%").c(Binder.getCallingUid()).flush(); 2123 if (!mContext.getPackageManager().hasSystemFeature( 2124 PackageManager.FEATURE_WIFI_PASSPOINT)) { 2125 throw new UnsupportedOperationException("Passpoint not enabled"); 2126 } 2127 mWifiStateMachine.syncQueryPasspointIcon(mWifiStateMachineChannel, bssid, fileName); 2128 } 2129 2130 /** 2131 * Match the currently associated network against the SP matching the given FQDN 2132 * @param fqdn FQDN of the SP 2133 * @return ordinal [HomeProvider, RoamingProvider, Incomplete, None, Declined] 2134 */ 2135 @Override 2136 public int matchProviderWithCurrentNetwork(String fqdn) { 2137 mLog.info("matchProviderWithCurrentNetwork uid=%").c(Binder.getCallingUid()).flush(); 2138 return mWifiStateMachine.matchProviderWithCurrentNetwork(mWifiStateMachineChannel, fqdn); 2139 } 2140 2141 /** 2142 * Deauthenticate and set the re-authentication hold off time for the current network 2143 * @param holdoff hold off time in milliseconds 2144 * @param ess set if the hold off pertains to an ESS rather than a BSS 2145 */ 2146 @Override 2147 public void deauthenticateNetwork(long holdoff, boolean ess) { 2148 mLog.info("deauthenticateNetwork uid=%").c(Binder.getCallingUid()).flush(); 2149 mWifiStateMachine.deauthenticateNetwork(mWifiStateMachineChannel, holdoff, ess); 2150 } 2151 2152 /** 2153 * Set the country code 2154 * @param countryCode ISO 3166 country code. 2155 * 2156 */ 2157 @Override 2158 public void setCountryCode(String countryCode) { 2159 Slog.i(TAG, "WifiService trying to set country code to " + countryCode); 2160 enforceConnectivityInternalPermission(); 2161 mLog.info("setCountryCode uid=%").c(Binder.getCallingUid()).flush(); 2162 final long token = Binder.clearCallingIdentity(); 2163 mCountryCode.setCountryCode(countryCode); 2164 Binder.restoreCallingIdentity(token); 2165 } 2166 2167 /** 2168 * Get the country code 2169 * @return Get the best choice country code for wifi, regardless of if it was set or 2170 * not. 2171 * Returns null when there is no country code available. 2172 */ 2173 @Override 2174 public String getCountryCode() { 2175 enforceConnectivityInternalPermission(); 2176 if (mVerboseLoggingEnabled) { 2177 mLog.info("getCountryCode uid=%").c(Binder.getCallingUid()).flush(); 2178 } 2179 String country = mCountryCode.getCountryCode(); 2180 return country; 2181 } 2182 2183 @Override 2184 public boolean isDualBandSupported() { 2185 //TODO (b/80552904): Should move towards adding a driver API that checks at runtime 2186 if (mVerboseLoggingEnabled) { 2187 mLog.info("isDualBandSupported uid=%").c(Binder.getCallingUid()).flush(); 2188 } 2189 2190 return mContext.getResources().getBoolean( 2191 com.android.internal.R.bool.config_wifi_dual_band_support); 2192 } 2193 2194 /** 2195 * Method allowing callers with NETWORK_SETTINGS permission to check if this is a dual mode 2196 * capable device (STA+AP). 2197 * 2198 * @return true if a dual mode capable device 2199 */ 2200 @Override 2201 public boolean needs5GHzToAnyApBandConversion() { 2202 enforceNetworkSettingsPermission(); 2203 2204 if (mVerboseLoggingEnabled) { 2205 mLog.info("needs5GHzToAnyApBandConversion uid=%").c(Binder.getCallingUid()).flush(); 2206 } 2207 return mContext.getResources().getBoolean( 2208 com.android.internal.R.bool.config_wifi_convert_apband_5ghz_to_any); 2209 } 2210 2211 /** 2212 * Return the DHCP-assigned addresses from the last successful DHCP request, 2213 * if any. 2214 * @return the DHCP information 2215 * @deprecated 2216 */ 2217 @Override 2218 @Deprecated 2219 public DhcpInfo getDhcpInfo() { 2220 enforceAccessPermission(); 2221 if (mVerboseLoggingEnabled) { 2222 mLog.info("getDhcpInfo uid=%").c(Binder.getCallingUid()).flush(); 2223 } 2224 DhcpResults dhcpResults = mWifiStateMachine.syncGetDhcpResults(); 2225 2226 DhcpInfo info = new DhcpInfo(); 2227 2228 if (dhcpResults.ipAddress != null && 2229 dhcpResults.ipAddress.getAddress() instanceof Inet4Address) { 2230 info.ipAddress = NetworkUtils.inetAddressToInt( 2231 (Inet4Address) dhcpResults.ipAddress.getAddress()); 2232 } 2233 2234 if (dhcpResults.gateway != null) { 2235 info.gateway = NetworkUtils.inetAddressToInt((Inet4Address) dhcpResults.gateway); 2236 } 2237 2238 int dnsFound = 0; 2239 for (InetAddress dns : dhcpResults.dnsServers) { 2240 if (dns instanceof Inet4Address) { 2241 if (dnsFound == 0) { 2242 info.dns1 = NetworkUtils.inetAddressToInt((Inet4Address)dns); 2243 } else { 2244 info.dns2 = NetworkUtils.inetAddressToInt((Inet4Address)dns); 2245 } 2246 if (++dnsFound > 1) break; 2247 } 2248 } 2249 Inet4Address serverAddress = dhcpResults.serverAddress; 2250 if (serverAddress != null) { 2251 info.serverAddress = NetworkUtils.inetAddressToInt(serverAddress); 2252 } 2253 info.leaseDuration = dhcpResults.leaseDuration; 2254 2255 return info; 2256 } 2257 2258 /** 2259 * enable TDLS for the local NIC to remote NIC 2260 * The APPs don't know the remote MAC address to identify NIC though, 2261 * so we need to do additional work to find it from remote IP address 2262 */ 2263 2264 class TdlsTaskParams { 2265 public String remoteIpAddress; 2266 public boolean enable; 2267 } 2268 2269 class TdlsTask extends AsyncTask<TdlsTaskParams, Integer, Integer> { 2270 @Override 2271 protected Integer doInBackground(TdlsTaskParams... params) { 2272 2273 // Retrieve parameters for the call 2274 TdlsTaskParams param = params[0]; 2275 String remoteIpAddress = param.remoteIpAddress.trim(); 2276 boolean enable = param.enable; 2277 2278 // Get MAC address of Remote IP 2279 String macAddress = null; 2280 2281 BufferedReader reader = null; 2282 2283 try { 2284 reader = new BufferedReader(new FileReader("/proc/net/arp")); 2285 2286 // Skip over the line bearing colum titles 2287 String line = reader.readLine(); 2288 2289 while ((line = reader.readLine()) != null) { 2290 String[] tokens = line.split("[ ]+"); 2291 if (tokens.length < 6) { 2292 continue; 2293 } 2294 2295 // ARP column format is 2296 // Address HWType HWAddress Flags Mask IFace 2297 String ip = tokens[0]; 2298 String mac = tokens[3]; 2299 2300 if (remoteIpAddress.equals(ip)) { 2301 macAddress = mac; 2302 break; 2303 } 2304 } 2305 2306 if (macAddress == null) { 2307 Slog.w(TAG, "Did not find remoteAddress {" + remoteIpAddress + "} in " + 2308 "/proc/net/arp"); 2309 } else { 2310 enableTdlsWithMacAddress(macAddress, enable); 2311 } 2312 2313 } catch (FileNotFoundException e) { 2314 Slog.e(TAG, "Could not open /proc/net/arp to lookup mac address"); 2315 } catch (IOException e) { 2316 Slog.e(TAG, "Could not read /proc/net/arp to lookup mac address"); 2317 } finally { 2318 try { 2319 if (reader != null) { 2320 reader.close(); 2321 } 2322 } 2323 catch (IOException e) { 2324 // Do nothing 2325 } 2326 } 2327 2328 return 0; 2329 } 2330 } 2331 2332 @Override 2333 public void enableTdls(String remoteAddress, boolean enable) { 2334 if (remoteAddress == null) { 2335 throw new IllegalArgumentException("remoteAddress cannot be null"); 2336 } 2337 mLog.info("enableTdls uid=% enable=%").c(Binder.getCallingUid()).c(enable).flush(); 2338 TdlsTaskParams params = new TdlsTaskParams(); 2339 params.remoteIpAddress = remoteAddress; 2340 params.enable = enable; 2341 new TdlsTask().execute(params); 2342 } 2343 2344 2345 @Override 2346 public void enableTdlsWithMacAddress(String remoteMacAddress, boolean enable) { 2347 mLog.info("enableTdlsWithMacAddress uid=% enable=%") 2348 .c(Binder.getCallingUid()) 2349 .c(enable) 2350 .flush(); 2351 if (remoteMacAddress == null) { 2352 throw new IllegalArgumentException("remoteMacAddress cannot be null"); 2353 } 2354 2355 mWifiStateMachine.enableTdls(remoteMacAddress, enable); 2356 } 2357 2358 /** 2359 * Get a reference to handler. This is used by a client to establish 2360 * an AsyncChannel communication with WifiService 2361 */ 2362 @Override 2363 public Messenger getWifiServiceMessenger(String packageName) throws RemoteException { 2364 enforceAccessPermission(); 2365 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 2366 // We don't have a good way of creating a fake Messenger, and returning null would 2367 // immediately break callers. 2368 throw new SecurityException("Could not create wifi service messenger"); 2369 } 2370 mLog.info("getWifiServiceMessenger uid=%").c(Binder.getCallingUid()).flush(); 2371 return new Messenger(mClientHandler); 2372 } 2373 2374 /** 2375 * Disable an ephemeral network, i.e. network that is created thru a WiFi Scorer 2376 */ 2377 @Override 2378 public void disableEphemeralNetwork(String SSID, String packageName) { 2379 enforceAccessPermission(); 2380 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 2381 return; 2382 } 2383 mLog.info("disableEphemeralNetwork uid=%").c(Binder.getCallingUid()).flush(); 2384 mWifiStateMachine.disableEphemeralNetwork(SSID); 2385 } 2386 2387 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 2388 @Override 2389 public void onReceive(Context context, Intent intent) { 2390 String action = intent.getAction(); 2391 if (action.equals(Intent.ACTION_USER_PRESENT)) { 2392 mWifiController.sendMessage(CMD_USER_PRESENT); 2393 } else if (action.equals(Intent.ACTION_USER_REMOVED)) { 2394 int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); 2395 mWifiStateMachine.removeUserConfigs(userHandle); 2396 } else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) { 2397 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, 2398 BluetoothAdapter.STATE_DISCONNECTED); 2399 mWifiStateMachine.sendBluetoothAdapterStateChange(state); 2400 } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) { 2401 boolean emergencyMode = intent.getBooleanExtra("phoneinECMState", false); 2402 mWifiController.sendMessage(CMD_EMERGENCY_MODE_CHANGED, emergencyMode ? 1 : 0, 0); 2403 } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED)) { 2404 boolean inCall = intent.getBooleanExtra(PhoneConstants.PHONE_IN_EMERGENCY_CALL, false); 2405 mWifiController.sendMessage(CMD_EMERGENCY_CALL_STATE_CHANGED, inCall ? 1 : 0, 0); 2406 } else if (action.equals(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED)) { 2407 handleIdleModeChanged(); 2408 } 2409 } 2410 }; 2411 2412 private boolean startConsentUi(String packageName, 2413 int callingUid, String intentAction) throws RemoteException { 2414 if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID 2415 || checkWifiPermissionWhenPermissionReviewRequired()) { 2416 return false; 2417 } 2418 try { 2419 // Validate the package only if we are going to use it 2420 ApplicationInfo applicationInfo = mContext.getPackageManager() 2421 .getApplicationInfoAsUser(packageName, 2422 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, 2423 UserHandle.getUserId(callingUid)); 2424 if (applicationInfo.uid != callingUid) { 2425 throw new SecurityException("Package " + packageName 2426 + " not in uid " + callingUid); 2427 } 2428 2429 // Permission review mode, trigger a user prompt 2430 Intent intent = new Intent(intentAction); 2431 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK 2432 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 2433 intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName); 2434 mContext.startActivity(intent); 2435 return true; 2436 } catch (PackageManager.NameNotFoundException e) { 2437 throw new RemoteException(e.getMessage()); 2438 } 2439 } 2440 2441 /** 2442 * Observes settings changes to scan always mode. 2443 */ 2444 private void registerForScanModeChange() { 2445 ContentObserver contentObserver = new ContentObserver(null) { 2446 @Override 2447 public void onChange(boolean selfChange) { 2448 mSettingsStore.handleWifiScanAlwaysAvailableToggled(); 2449 mWifiController.sendMessage(CMD_SCAN_ALWAYS_MODE_CHANGED); 2450 } 2451 }; 2452 mFrameworkFacade.registerContentObserver(mContext, 2453 Settings.Global.getUriFor(Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE), 2454 false, contentObserver); 2455 2456 } 2457 2458 private void registerForBroadcasts() { 2459 IntentFilter intentFilter = new IntentFilter(); 2460 intentFilter.addAction(Intent.ACTION_USER_PRESENT); 2461 intentFilter.addAction(Intent.ACTION_USER_REMOVED); 2462 intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); 2463 intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); 2464 intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED); 2465 intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); 2466 2467 boolean trackEmergencyCallState = mContext.getResources().getBoolean( 2468 com.android.internal.R.bool.config_wifi_turn_off_during_emergency_call); 2469 if (trackEmergencyCallState) { 2470 intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED); 2471 } 2472 mContext.registerReceiver(mReceiver, intentFilter); 2473 2474 intentFilter = new IntentFilter(); 2475 intentFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED); 2476 intentFilter.addDataScheme("package"); 2477 mContext.registerReceiver(new BroadcastReceiver() { 2478 @Override 2479 public void onReceive(Context context, Intent intent) { 2480 String action = intent.getAction(); 2481 if (action.equals(Intent.ACTION_PACKAGE_FULLY_REMOVED)) { 2482 int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); 2483 Uri uri = intent.getData(); 2484 if (uid == -1 || uri == null) { 2485 return; 2486 } 2487 String pkgName = uri.getSchemeSpecificPart(); 2488 mWifiStateMachine.removeAppConfigs(pkgName, uid); 2489 // Call the method in WSM thread. 2490 mWifiStateMachineHandler.post(() -> { 2491 mScanRequestProxy.clearScanRequestTimestampsForApp(pkgName, uid); 2492 }); 2493 } 2494 } 2495 }, intentFilter); 2496 } 2497 2498 @Override 2499 public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, 2500 String[] args, ShellCallback callback, ResultReceiver resultReceiver) { 2501 (new WifiShellCommand(mWifiStateMachine)).exec(this, in, out, err, args, callback, 2502 resultReceiver); 2503 } 2504 2505 @Override 2506 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2507 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 2508 != PackageManager.PERMISSION_GRANTED) { 2509 pw.println("Permission Denial: can't dump WifiService from from pid=" 2510 + Binder.getCallingPid() 2511 + ", uid=" + Binder.getCallingUid()); 2512 return; 2513 } 2514 if (args != null && args.length > 0 && WifiMetrics.PROTO_DUMP_ARG.equals(args[0])) { 2515 // WifiMetrics proto bytes were requested. Dump only these. 2516 mWifiStateMachine.updateWifiMetrics(); 2517 mWifiMetrics.dump(fd, pw, args); 2518 } else if (args != null && args.length > 0 && IpClient.DUMP_ARG.equals(args[0])) { 2519 // IpClient dump was requested. Pass it along and take no further action. 2520 String[] ipClientArgs = new String[args.length - 1]; 2521 System.arraycopy(args, 1, ipClientArgs, 0, ipClientArgs.length); 2522 mWifiStateMachine.dumpIpClient(fd, pw, ipClientArgs); 2523 } else if (args != null && args.length > 0 && WifiScoreReport.DUMP_ARG.equals(args[0])) { 2524 WifiScoreReport wifiScoreReport = mWifiStateMachine.getWifiScoreReport(); 2525 if (wifiScoreReport != null) wifiScoreReport.dump(fd, pw, args); 2526 } else { 2527 pw.println("Wi-Fi is " + mWifiStateMachine.syncGetWifiStateByName()); 2528 pw.println("Verbose logging is " + (mVerboseLoggingEnabled ? "on" : "off")); 2529 pw.println("Stay-awake conditions: " + 2530 mFacade.getIntegerSetting(mContext, 2531 Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0)); 2532 pw.println("mInIdleMode " + mInIdleMode); 2533 pw.println("mScanPending " + mScanPending); 2534 mWifiController.dump(fd, pw, args); 2535 mSettingsStore.dump(fd, pw, args); 2536 mTrafficPoller.dump(fd, pw, args); 2537 pw.println(); 2538 pw.println("Locks held:"); 2539 mWifiLockManager.dump(pw); 2540 pw.println(); 2541 mWifiMulticastLockManager.dump(pw); 2542 pw.println(); 2543 mWifiStateMachinePrime.dump(fd, pw, args); 2544 pw.println(); 2545 mWifiStateMachine.dump(fd, pw, args); 2546 pw.println(); 2547 mWifiStateMachine.updateWifiMetrics(); 2548 mWifiMetrics.dump(fd, pw, args); 2549 pw.println(); 2550 mWifiBackupRestore.dump(fd, pw, args); 2551 pw.println(); 2552 pw.println("ScoringParams: settings put global " + Settings.Global.WIFI_SCORE_PARAMS 2553 + " " + mWifiInjector.getScoringParams()); 2554 pw.println(); 2555 WifiScoreReport wifiScoreReport = mWifiStateMachine.getWifiScoreReport(); 2556 if (wifiScoreReport != null) { 2557 pw.println("WifiScoreReport:"); 2558 wifiScoreReport.dump(fd, pw, args); 2559 } 2560 pw.println(); 2561 } 2562 } 2563 2564 /** 2565 * NOTE: WifiLocks do not serve a useful purpose in their current impl and will be removed 2566 * (including the methods below). 2567 * 2568 * TODO: b/71548157 2569 */ 2570 @Override 2571 public boolean acquireWifiLock(IBinder binder, int lockMode, String tag, WorkSource ws) { 2572 mLog.info("acquireWifiLock uid=% lockMode=%") 2573 .c(Binder.getCallingUid()) 2574 .c(lockMode).flush(); 2575 if (mWifiLockManager.acquireWifiLock(lockMode, tag, binder, ws)) { 2576 return true; 2577 } 2578 return false; 2579 } 2580 2581 @Override 2582 public void updateWifiLockWorkSource(IBinder binder, WorkSource ws) { 2583 mLog.info("updateWifiLockWorkSource uid=%").c(Binder.getCallingUid()).flush(); 2584 mWifiLockManager.updateWifiLockWorkSource(binder, ws); 2585 } 2586 2587 @Override 2588 public boolean releaseWifiLock(IBinder binder) { 2589 mLog.info("releaseWifiLock uid=%").c(Binder.getCallingUid()).flush(); 2590 if (mWifiLockManager.releaseWifiLock(binder)) { 2591 return true; 2592 } 2593 return false; 2594 } 2595 2596 @Override 2597 public void initializeMulticastFiltering() { 2598 enforceMulticastChangePermission(); 2599 mLog.info("initializeMulticastFiltering uid=%").c(Binder.getCallingUid()).flush(); 2600 mWifiMulticastLockManager.initializeFiltering(); 2601 } 2602 2603 @Override 2604 public void acquireMulticastLock(IBinder binder, String tag) { 2605 enforceMulticastChangePermission(); 2606 mLog.info("acquireMulticastLock uid=%").c(Binder.getCallingUid()).flush(); 2607 mWifiMulticastLockManager.acquireLock(binder, tag); 2608 } 2609 2610 @Override 2611 public void releaseMulticastLock() { 2612 enforceMulticastChangePermission(); 2613 mLog.info("releaseMulticastLock uid=%").c(Binder.getCallingUid()).flush(); 2614 mWifiMulticastLockManager.releaseLock(); 2615 } 2616 2617 @Override 2618 public boolean isMulticastEnabled() { 2619 enforceAccessPermission(); 2620 if (mVerboseLoggingEnabled) { 2621 mLog.info("isMulticastEnabled uid=%").c(Binder.getCallingUid()).flush(); 2622 } 2623 return mWifiMulticastLockManager.isMulticastEnabled(); 2624 } 2625 2626 @Override 2627 public void enableVerboseLogging(int verbose) { 2628 enforceAccessPermission(); 2629 enforceNetworkSettingsPermission(); 2630 mLog.info("enableVerboseLogging uid=% verbose=%") 2631 .c(Binder.getCallingUid()) 2632 .c(verbose).flush(); 2633 mFacade.setIntegerSetting( 2634 mContext, Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED, verbose); 2635 enableVerboseLoggingInternal(verbose); 2636 } 2637 2638 void enableVerboseLoggingInternal(int verbose) { 2639 mVerboseLoggingEnabled = verbose > 0; 2640 mWifiStateMachine.enableVerboseLogging(verbose); 2641 mWifiLockManager.enableVerboseLogging(verbose); 2642 mWifiMulticastLockManager.enableVerboseLogging(verbose); 2643 mWifiInjector.enableVerboseLogging(verbose); 2644 } 2645 2646 @Override 2647 public int getVerboseLoggingLevel() { 2648 enforceAccessPermission(); 2649 if (mVerboseLoggingEnabled) { 2650 mLog.info("getVerboseLoggingLevel uid=%").c(Binder.getCallingUid()).flush(); 2651 } 2652 return mFacade.getIntegerSetting( 2653 mContext, Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED, 0); 2654 } 2655 2656 @Override 2657 public void factoryReset(String packageName) { 2658 enforceConnectivityInternalPermission(); 2659 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 2660 return; 2661 } 2662 mLog.info("factoryReset uid=%").c(Binder.getCallingUid()).flush(); 2663 if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) { 2664 return; 2665 } 2666 2667 if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING)) { 2668 // Turn mobile hotspot off - will also clear any registered LOHS requests when it is 2669 // shut down 2670 stopSoftApInternal(); 2671 } 2672 2673 if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_WIFI)) { 2674 // Delete all Wifi SSIDs 2675 if (mWifiStateMachineChannel != null) { 2676 List<WifiConfiguration> networks = mWifiStateMachine.syncGetConfiguredNetworks( 2677 Binder.getCallingUid(), mWifiStateMachineChannel); 2678 if (networks != null) { 2679 for (WifiConfiguration config : networks) { 2680 removeNetwork(config.networkId, packageName); 2681 } 2682 } 2683 } 2684 } 2685 } 2686 2687 /* private methods */ 2688 static boolean logAndReturnFalse(String s) { 2689 Log.d(TAG, s); 2690 return false; 2691 } 2692 2693 @Override 2694 public Network getCurrentNetwork() { 2695 enforceAccessPermission(); 2696 if (mVerboseLoggingEnabled) { 2697 mLog.info("getCurrentNetwork uid=%").c(Binder.getCallingUid()).flush(); 2698 } 2699 return mWifiStateMachine.getCurrentNetwork(); 2700 } 2701 2702 public static String toHexString(String s) { 2703 if (s == null) { 2704 return "null"; 2705 } 2706 StringBuilder sb = new StringBuilder(); 2707 sb.append('\'').append(s).append('\''); 2708 for (int n = 0; n < s.length(); n++) { 2709 sb.append(String.format(" %02x", s.charAt(n) & 0xffff)); 2710 } 2711 return sb.toString(); 2712 } 2713 2714 /** 2715 * Enable/disable WifiConnectivityManager at runtime 2716 * 2717 * @param enabled true-enable; false-disable 2718 */ 2719 @Override 2720 public void enableWifiConnectivityManager(boolean enabled) { 2721 enforceConnectivityInternalPermission(); 2722 mLog.info("enableWifiConnectivityManager uid=% enabled=%") 2723 .c(Binder.getCallingUid()) 2724 .c(enabled).flush(); 2725 mWifiStateMachine.enableWifiConnectivityManager(enabled); 2726 } 2727 2728 /** 2729 * Retrieve the data to be backed to save the current state. 2730 * 2731 * @return Raw byte stream of the data to be backed up. 2732 */ 2733 @Override 2734 public byte[] retrieveBackupData() { 2735 enforceNetworkSettingsPermission(); 2736 mLog.info("retrieveBackupData uid=%").c(Binder.getCallingUid()).flush(); 2737 if (mWifiStateMachineChannel == null) { 2738 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 2739 return null; 2740 } 2741 2742 Slog.d(TAG, "Retrieving backup data"); 2743 List<WifiConfiguration> wifiConfigurations = 2744 mWifiStateMachine.syncGetPrivilegedConfiguredNetwork(mWifiStateMachineChannel); 2745 byte[] backupData = 2746 mWifiBackupRestore.retrieveBackupDataFromConfigurations(wifiConfigurations); 2747 Slog.d(TAG, "Retrieved backup data"); 2748 return backupData; 2749 } 2750 2751 /** 2752 * Helper method to restore networks retrieved from backup data. 2753 * 2754 * @param configurations list of WifiConfiguration objects parsed from the backup data. 2755 */ 2756 private void restoreNetworks(List<WifiConfiguration> configurations) { 2757 if (configurations == null) { 2758 Slog.e(TAG, "Backup data parse failed"); 2759 return; 2760 } 2761 for (WifiConfiguration configuration : configurations) { 2762 int networkId = mWifiStateMachine.syncAddOrUpdateNetwork( 2763 mWifiStateMachineChannel, configuration); 2764 if (networkId == WifiConfiguration.INVALID_NETWORK_ID) { 2765 Slog.e(TAG, "Restore network failed: " + configuration.configKey()); 2766 continue; 2767 } 2768 // Enable all networks restored. 2769 mWifiStateMachine.syncEnableNetwork(mWifiStateMachineChannel, networkId, false); 2770 } 2771 } 2772 2773 /** 2774 * Restore state from the backed up data. 2775 * 2776 * @param data Raw byte stream of the backed up data. 2777 */ 2778 @Override 2779 public void restoreBackupData(byte[] data) { 2780 enforceNetworkSettingsPermission(); 2781 mLog.info("restoreBackupData uid=%").c(Binder.getCallingUid()).flush(); 2782 if (mWifiStateMachineChannel == null) { 2783 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 2784 return; 2785 } 2786 2787 Slog.d(TAG, "Restoring backup data"); 2788 List<WifiConfiguration> wifiConfigurations = 2789 mWifiBackupRestore.retrieveConfigurationsFromBackupData(data); 2790 restoreNetworks(wifiConfigurations); 2791 Slog.d(TAG, "Restored backup data"); 2792 } 2793 2794 /** 2795 * Restore state from the older supplicant back up data. 2796 * The old backup data was essentially a backup of wpa_supplicant.conf & ipconfig.txt file. 2797 * 2798 * @param supplicantData Raw byte stream of wpa_supplicant.conf 2799 * @param ipConfigData Raw byte stream of ipconfig.txt 2800 */ 2801 public void restoreSupplicantBackupData(byte[] supplicantData, byte[] ipConfigData) { 2802 enforceNetworkSettingsPermission(); 2803 mLog.trace("restoreSupplicantBackupData uid=%").c(Binder.getCallingUid()).flush(); 2804 if (mWifiStateMachineChannel == null) { 2805 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 2806 return; 2807 } 2808 2809 Slog.d(TAG, "Restoring supplicant backup data"); 2810 List<WifiConfiguration> wifiConfigurations = 2811 mWifiBackupRestore.retrieveConfigurationsFromSupplicantBackupData( 2812 supplicantData, ipConfigData); 2813 restoreNetworks(wifiConfigurations); 2814 Slog.d(TAG, "Restored supplicant backup data"); 2815 } 2816 2817 /** 2818 * Starts subscription provisioning with a provider 2819 * 2820 * @param provider {@link OsuProvider} the provider to provision with 2821 * @param callback {@link IProvisoningCallback} the callback object to inform status 2822 */ 2823 @Override 2824 public void startSubscriptionProvisioning(OsuProvider provider, 2825 IProvisioningCallback callback) { 2826 if (provider == null) { 2827 throw new IllegalArgumentException("Provider must not be null"); 2828 } 2829 if (callback == null) { 2830 throw new IllegalArgumentException("Callback must not be null"); 2831 } 2832 enforceNetworkSettingsPermission(); 2833 if (!mContext.getPackageManager().hasSystemFeature( 2834 PackageManager.FEATURE_WIFI_PASSPOINT)) { 2835 throw new UnsupportedOperationException("Passpoint not enabled"); 2836 } 2837 final int uid = Binder.getCallingUid(); 2838 mLog.trace("startSubscriptionProvisioning uid=%").c(uid).flush(); 2839 if (mWifiStateMachine.syncStartSubscriptionProvisioning(uid, provider, 2840 callback, mWifiStateMachineChannel)) { 2841 mLog.trace("Subscription provisioning started with %") 2842 .c(provider.toString()).flush(); 2843 } 2844 } 2845 } 2846