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