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