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