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