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