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