WifiServiceImpl.java revision c9aab08c8e0eb78f8da4e1ffe962b09a9cf0a8a1
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 com.android.server.connectivity.tethering.IControlsTethering.STATE_TETHERED; 20import static com.android.server.wifi.WifiController.CMD_AIRPLANE_TOGGLED; 21import static com.android.server.wifi.WifiController.CMD_BATTERY_CHANGED; 22import static com.android.server.wifi.WifiController.CMD_EMERGENCY_CALL_STATE_CHANGED; 23import static com.android.server.wifi.WifiController.CMD_EMERGENCY_MODE_CHANGED; 24import static com.android.server.wifi.WifiController.CMD_LOCKS_CHANGED; 25import static com.android.server.wifi.WifiController.CMD_SCAN_ALWAYS_MODE_CHANGED; 26import static com.android.server.wifi.WifiController.CMD_SCREEN_OFF; 27import static com.android.server.wifi.WifiController.CMD_SCREEN_ON; 28import static com.android.server.wifi.WifiController.CMD_SET_AP; 29import static com.android.server.wifi.WifiController.CMD_USER_PRESENT; 30import static com.android.server.wifi.WifiController.CMD_WIFI_TOGGLED; 31 32import android.Manifest; 33import android.app.AppOpsManager; 34import android.bluetooth.BluetoothAdapter; 35import android.content.BroadcastReceiver; 36import android.content.Context; 37import android.content.Intent; 38import android.content.IntentFilter; 39import android.content.pm.ApplicationInfo; 40import android.content.pm.PackageManager; 41import android.content.pm.ParceledListSlice; 42import android.database.ContentObserver; 43import android.net.DhcpInfo; 44import android.net.DhcpResults; 45import android.net.IpConfiguration; 46import android.net.Network; 47import android.net.NetworkUtils; 48import android.net.StaticIpConfiguration; 49import android.net.Uri; 50import android.net.ip.IpManager; 51import android.net.wifi.IWifiManager; 52import android.net.wifi.ScanResult; 53import android.net.wifi.ScanSettings; 54import android.net.wifi.WifiActivityEnergyInfo; 55import android.net.wifi.WifiConfiguration; 56import android.net.wifi.WifiConnectionStatistics; 57import android.net.wifi.WifiEnterpriseConfig; 58import android.net.wifi.WifiInfo; 59import android.net.wifi.WifiLinkLayerStats; 60import android.net.wifi.WifiManager; 61import android.net.wifi.WifiScanner; 62import android.net.wifi.hotspot2.PasspointConfiguration; 63import android.os.AsyncTask; 64import android.os.BatteryStats; 65import android.os.Binder; 66import android.os.Build; 67import android.os.Bundle; 68import android.os.HandlerThread; 69import android.os.IBinder; 70import android.os.Looper; 71import android.os.Message; 72import android.os.Messenger; 73import android.os.PowerManager; 74import android.os.Process; 75import android.os.RemoteException; 76import android.os.ResultReceiver; 77import android.os.SystemClock; 78import android.os.UserHandle; 79import android.os.UserManager; 80import android.os.WorkSource; 81import android.provider.Settings; 82import android.text.TextUtils; 83import android.util.Log; 84import android.util.Slog; 85 86import com.android.internal.annotations.VisibleForTesting; 87import com.android.internal.telephony.IccCardConstants; 88import com.android.internal.telephony.PhoneConstants; 89import com.android.internal.telephony.TelephonyIntents; 90import com.android.internal.util.AsyncChannel; 91import com.android.server.wifi.util.WifiHandler; 92import com.android.server.wifi.util.WifiPermissionsUtil; 93 94import java.io.BufferedReader; 95import java.io.FileDescriptor; 96import java.io.FileNotFoundException; 97import java.io.FileReader; 98import java.io.IOException; 99import java.io.PrintWriter; 100import java.net.Inet4Address; 101import java.net.InetAddress; 102import java.security.GeneralSecurityException; 103import java.security.KeyStore; 104import java.security.cert.CertPath; 105import java.security.cert.CertPathValidator; 106import java.security.cert.CertPathValidatorException; 107import java.security.cert.CertificateFactory; 108import java.security.cert.PKIXParameters; 109import java.security.cert.X509Certificate; 110import java.util.ArrayList; 111import java.util.Arrays; 112import java.util.List; 113 114/** 115 * WifiService handles remote WiFi operation requests by implementing 116 * the IWifiManager interface. 117 * 118 * @hide 119 */ 120public class WifiServiceImpl extends IWifiManager.Stub { 121 private static final String TAG = "WifiService"; 122 private static final boolean DBG = true; 123 private static final boolean VDBG = false; 124 125 // Package names for Settings, QuickSettings and QuickQuickSettings 126 private static final String SYSUI_PACKAGE_NAME = "com.android.systemui"; 127 private static final String SETTINGS_PACKAGE_NAME = "com.android.settings"; 128 129 // Dumpsys argument to enable/disable disconnect on IP reachability failures. 130 private static final String DUMP_ARG_SET_IPREACH_DISCONNECT = "set-ipreach-disconnect"; 131 private static final String DUMP_ARG_SET_IPREACH_DISCONNECT_ENABLED = "enabled"; 132 private static final String DUMP_ARG_SET_IPREACH_DISCONNECT_DISABLED = "disabled"; 133 134 final WifiStateMachine mWifiStateMachine; 135 136 private final Context mContext; 137 private final FrameworkFacade mFacade; 138 139 private final PowerManager mPowerManager; 140 private final AppOpsManager mAppOps; 141 private final UserManager mUserManager; 142 private final WifiCountryCode mCountryCode; 143 // Debug counter tracking scan requests sent by WifiManager 144 private int scanRequestCounter = 0; 145 146 /* Polls traffic stats and notifies clients */ 147 private WifiTrafficPoller mTrafficPoller; 148 /* Tracks the persisted states for wi-fi & airplane mode */ 149 final WifiSettingsStore mSettingsStore; 150 /* Logs connection events and some general router and scan stats */ 151 private final WifiMetrics mWifiMetrics; 152 /* Manages affiliated certificates for current user */ 153 private final WifiCertManager mCertManager; 154 155 private final WifiInjector mWifiInjector; 156 /* Backup/Restore Module */ 157 private final WifiBackupRestore mWifiBackupRestore; 158 159 private WifiScanner mWifiScanner; 160 161 private WifiLog mLog; 162 /** 163 * Asynchronous channel to WifiStateMachine 164 */ 165 private AsyncChannel mWifiStateMachineChannel; 166 167 private final boolean mPermissionReviewRequired; 168 private final FrameworkFacade mFrameworkFacade; 169 170 private WifiPermissionsUtil mWifiPermissionsUtil; 171 172 /** 173 * Handles client connections 174 */ 175 private class ClientHandler extends WifiHandler { 176 177 ClientHandler(String tag, Looper looper) { 178 super(tag, looper); 179 } 180 181 @Override 182 public void handleMessage(Message msg) { 183 super.handleMessage(msg); 184 switch (msg.what) { 185 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: { 186 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 187 if (DBG) Slog.d(TAG, "New client listening to asynchronous messages"); 188 // We track the clients by the Messenger 189 // since it is expected to be always available 190 mTrafficPoller.addClient(msg.replyTo); 191 } else { 192 Slog.e(TAG, "Client connection failure, error=" + msg.arg1); 193 } 194 break; 195 } 196 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { 197 if (msg.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) { 198 if (DBG) Slog.d(TAG, "Send failed, client connection lost"); 199 } else { 200 if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1); 201 } 202 mTrafficPoller.removeClient(msg.replyTo); 203 break; 204 } 205 case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: { 206 AsyncChannel ac = mFrameworkFacade.makeWifiAsyncChannel(TAG); 207 ac.connect(mContext, this, msg.replyTo); 208 break; 209 } 210 case WifiManager.CONNECT_NETWORK: { 211 WifiConfiguration config = (WifiConfiguration) msg.obj; 212 int networkId = msg.arg1; 213 Slog.d("WiFiServiceImpl ", "CONNECT " 214 + " nid=" + Integer.toString(networkId) 215 + " uid=" + msg.sendingUid 216 + " name=" 217 + mContext.getPackageManager().getNameForUid(msg.sendingUid)); 218 if (config != null && isValid(config)) { 219 if (DBG) Slog.d(TAG, "Connect with config " + config); 220 /* Command is forwarded to state machine */ 221 mWifiStateMachine.sendMessage(Message.obtain(msg)); 222 } else if (config == null 223 && networkId != WifiConfiguration.INVALID_NETWORK_ID) { 224 if (DBG) Slog.d(TAG, "Connect with networkId " + networkId); 225 mWifiStateMachine.sendMessage(Message.obtain(msg)); 226 } else { 227 Slog.e(TAG, "ClientHandler.handleMessage ignoring invalid msg=" + msg); 228 replyFailed(msg, WifiManager.CONNECT_NETWORK_FAILED, 229 WifiManager.INVALID_ARGS); 230 } 231 break; 232 } 233 case WifiManager.SAVE_NETWORK: { 234 WifiConfiguration config = (WifiConfiguration) msg.obj; 235 int networkId = msg.arg1; 236 Slog.d("WiFiServiceImpl ", "SAVE" 237 + " nid=" + Integer.toString(networkId) 238 + " uid=" + msg.sendingUid 239 + " name=" 240 + mContext.getPackageManager().getNameForUid(msg.sendingUid)); 241 if (config != null && isValid(config)) { 242 if (DBG) Slog.d(TAG, "Save network with config " + config); 243 /* Command is forwarded to state machine */ 244 mWifiStateMachine.sendMessage(Message.obtain(msg)); 245 } else { 246 Slog.e(TAG, "ClientHandler.handleMessage ignoring invalid msg=" + msg); 247 replyFailed(msg, WifiManager.SAVE_NETWORK_FAILED, 248 WifiManager.INVALID_ARGS); 249 } 250 break; 251 } 252 case WifiManager.FORGET_NETWORK: 253 mWifiStateMachine.sendMessage(Message.obtain(msg)); 254 break; 255 case WifiManager.START_WPS: 256 case WifiManager.CANCEL_WPS: 257 case WifiManager.DISABLE_NETWORK: 258 case WifiManager.RSSI_PKTCNT_FETCH: { 259 mWifiStateMachine.sendMessage(Message.obtain(msg)); 260 break; 261 } 262 default: { 263 Slog.d(TAG, "ClientHandler.handleMessage ignoring msg=" + msg); 264 break; 265 } 266 } 267 } 268 269 private void replyFailed(Message msg, int what, int why) { 270 if (msg.replyTo == null) return; 271 Message reply = Message.obtain(); 272 reply.what = what; 273 reply.arg1 = why; 274 try { 275 msg.replyTo.send(reply); 276 } catch (RemoteException e) { 277 // There's not much we can do if reply can't be sent! 278 } 279 } 280 } 281 private ClientHandler mClientHandler; 282 283 /** 284 * Handles interaction with WifiStateMachine 285 */ 286 private class WifiStateMachineHandler extends WifiHandler { 287 private AsyncChannel mWsmChannel; 288 289 WifiStateMachineHandler(String tag, Looper looper, AsyncChannel asyncChannel) { 290 super(tag, looper); 291 mWsmChannel = asyncChannel; 292 mWsmChannel.connect(mContext, this, mWifiStateMachine.getHandler()); 293 } 294 295 @Override 296 public void handleMessage(Message msg) { 297 super.handleMessage(msg); 298 switch (msg.what) { 299 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: { 300 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 301 mWifiStateMachineChannel = mWsmChannel; 302 } else { 303 Slog.e(TAG, "WifiStateMachine connection failure, error=" + msg.arg1); 304 mWifiStateMachineChannel = null; 305 } 306 break; 307 } 308 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { 309 Slog.e(TAG, "WifiStateMachine channel lost, msg.arg1 =" + msg.arg1); 310 mWifiStateMachineChannel = null; 311 //Re-establish connection to state machine 312 mWsmChannel.connect(mContext, this, mWifiStateMachine.getHandler()); 313 break; 314 } 315 default: { 316 Slog.d(TAG, "WifiStateMachineHandler.handleMessage ignoring msg=" + msg); 317 break; 318 } 319 } 320 } 321 } 322 323 WifiStateMachineHandler mWifiStateMachineHandler; 324 private WifiController mWifiController; 325 private final WifiLockManager mWifiLockManager; 326 private final WifiMulticastLockManager mWifiMulticastLockManager; 327 328 public WifiServiceImpl(Context context, WifiInjector wifiInjector, AsyncChannel asyncChannel) { 329 mContext = context; 330 mWifiInjector = wifiInjector; 331 332 mFacade = mWifiInjector.getFrameworkFacade(); 333 mWifiMetrics = mWifiInjector.getWifiMetrics(); 334 mTrafficPoller = mWifiInjector.getWifiTrafficPoller(); 335 mUserManager = mWifiInjector.getUserManager(); 336 mCountryCode = mWifiInjector.getWifiCountryCode(); 337 mWifiStateMachine = mWifiInjector.getWifiStateMachine(); 338 mWifiStateMachine.enableRssiPolling(true); 339 mSettingsStore = mWifiInjector.getWifiSettingsStore(); 340 mPowerManager = mContext.getSystemService(PowerManager.class); 341 mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 342 mCertManager = mWifiInjector.getWifiCertManager(); 343 mWifiLockManager = mWifiInjector.getWifiLockManager(); 344 mWifiMulticastLockManager = mWifiInjector.getWifiMulticastLockManager(); 345 HandlerThread wifiServiceHandlerThread = mWifiInjector.getWifiServiceHandlerThread(); 346 mClientHandler = new ClientHandler(TAG, wifiServiceHandlerThread.getLooper()); 347 mWifiStateMachineHandler = new WifiStateMachineHandler(TAG, 348 wifiServiceHandlerThread.getLooper(), asyncChannel); 349 mWifiController = mWifiInjector.getWifiController(); 350 mWifiBackupRestore = mWifiInjector.getWifiBackupRestore(); 351 mPermissionReviewRequired = Build.PERMISSIONS_REVIEW_REQUIRED 352 || context.getResources().getBoolean( 353 com.android.internal.R.bool.config_permissionReviewRequired); 354 mWifiPermissionsUtil = mWifiInjector.getWifiPermissionsUtil(); 355 mLog = mWifiInjector.makeLog(TAG); 356 mFrameworkFacade = wifiInjector.getFrameworkFacade(); 357 enableVerboseLoggingInternal(getVerboseLoggingLevel()); 358 } 359 360 /** 361 * Provide a way for unit tests to set valid log object in the WifiHandler 362 * @param log WifiLog object to assign to the clientHandler 363 */ 364 @VisibleForTesting 365 public void setWifiHandlerLogForTest(WifiLog log) { 366 mClientHandler.setWifiLog(log); 367 } 368 369 /** 370 * Check if we are ready to start wifi. 371 * 372 * First check if we will be restarting system services to decrypt the device. If the device is 373 * not encrypted, check if Wi-Fi needs to be enabled and start if needed 374 * 375 * This function is used only at boot time. 376 */ 377 public void checkAndStartWifi() { 378 // First check if we will end up restarting WifiService 379 if (mFrameworkFacade.inStorageManagerCryptKeeperBounce()) { 380 Log.d(TAG, "Device still encrypted. Need to restart SystemServer. Do not start wifi."); 381 return; 382 } 383 384 // Check if wi-fi needs to be enabled 385 boolean wifiEnabled = mSettingsStore.isWifiToggleEnabled(); 386 Slog.i(TAG, "WifiService starting up with Wi-Fi " + 387 (wifiEnabled ? "enabled" : "disabled")); 388 389 registerForScanModeChange(); 390 mContext.registerReceiver( 391 new BroadcastReceiver() { 392 @Override 393 public void onReceive(Context context, Intent intent) { 394 if (mSettingsStore.handleAirplaneModeToggled()) { 395 mWifiController.sendMessage(CMD_AIRPLANE_TOGGLED); 396 } 397 if (mSettingsStore.isAirplaneModeOn()) { 398 Log.d(TAG, "resetting country code because Airplane mode is ON"); 399 mCountryCode.airplaneModeEnabled(); 400 } 401 } 402 }, 403 new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED)); 404 405 mContext.registerReceiver( 406 new BroadcastReceiver() { 407 @Override 408 public void onReceive(Context context, Intent intent) { 409 String state = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE); 410 if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(state)) { 411 Log.d(TAG, "resetting networks because SIM was removed"); 412 mWifiStateMachine.resetSimAuthNetworks(false); 413 Log.d(TAG, "resetting country code because SIM is removed"); 414 mCountryCode.simCardRemoved(); 415 } else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(state)) { 416 Log.d(TAG, "resetting networks because SIM was loaded"); 417 mWifiStateMachine.resetSimAuthNetworks(true); 418 } 419 } 420 }, 421 new IntentFilter(TelephonyIntents.ACTION_SIM_STATE_CHANGED)); 422 423 // Adding optimizations of only receiving broadcasts when wifi is enabled 424 // can result in race conditions when apps toggle wifi in the background 425 // without active user involvement. Always receive broadcasts. 426 registerForBroadcasts(); 427 registerForPackageOrUserRemoval(); 428 mInIdleMode = mPowerManager.isDeviceIdleMode(); 429 430 if (!mWifiStateMachine.syncInitialize(mWifiStateMachineChannel)) { 431 Log.wtf(TAG, "Failed to initialize WifiStateMachine"); 432 } 433 mWifiController.start(); 434 435 // If we are already disabled (could be due to airplane mode), avoid changing persist 436 // state here 437 if (wifiEnabled) { 438 try { 439 setWifiEnabled(mContext.getPackageName(), wifiEnabled); 440 } catch (RemoteException e) { 441 /* ignore - local call */ 442 } 443 } 444 } 445 446 public void handleUserSwitch(int userId) { 447 mWifiStateMachine.handleUserSwitch(userId); 448 } 449 450 public void handleUserUnlock(int userId) { 451 mWifiStateMachine.handleUserUnlock(userId); 452 } 453 454 public void handleUserStop(int userId) { 455 mWifiStateMachine.handleUserStop(userId); 456 } 457 458 /** 459 * see {@link android.net.wifi.WifiManager#startScan} 460 * and {@link android.net.wifi.WifiManager#startCustomizedScan} 461 * 462 * @param settings If null, use default parameter, i.e. full scan. 463 * @param workSource If null, all blame is given to the calling uid. 464 */ 465 @Override 466 public void startScan(ScanSettings settings, WorkSource workSource) { 467 enforceChangePermission(); 468 mLog.trace("startScan uid=%").c(Binder.getCallingUid()).flush(); 469 synchronized (this) { 470 if (mWifiScanner == null) { 471 mWifiScanner = mWifiInjector.getWifiScanner(); 472 } 473 if (mInIdleMode) { 474 // Need to send an immediate scan result broadcast in case the 475 // caller is waiting for a result .. 476 477 // clear calling identity to send broadcast 478 long callingIdentity = Binder.clearCallingIdentity(); 479 try { 480 // TODO: investigate if the logic to cancel scans when idle can move to 481 // WifiScanningServiceImpl. This will 1 - clean up WifiServiceImpl and 2 - 482 // avoid plumbing an awkward path to report a cancelled/failed scan. This will 483 // be sent directly until b/31398592 is fixed. 484 Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); 485 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 486 intent.putExtra(WifiManager.EXTRA_RESULTS_UPDATED, false); 487 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 488 } finally { 489 // restore calling identity 490 Binder.restoreCallingIdentity(callingIdentity); 491 } 492 mScanPending = true; 493 return; 494 } 495 } 496 if (settings != null) { 497 settings = new ScanSettings(settings); 498 if (!settings.isValid()) { 499 Slog.e(TAG, "invalid scan setting"); 500 return; 501 } 502 } 503 if (workSource != null) { 504 enforceWorkSourcePermission(); 505 // WifiManager currently doesn't use names, so need to clear names out of the 506 // supplied WorkSource to allow future WorkSource combining. 507 workSource.clearNames(); 508 } 509 if (workSource == null && Binder.getCallingUid() >= 0) { 510 workSource = new WorkSource(Binder.getCallingUid()); 511 } 512 mWifiStateMachine.startScan(Binder.getCallingUid(), scanRequestCounter++, 513 settings, workSource); 514 } 515 516 @Override 517 public String getCurrentNetworkWpsNfcConfigurationToken() { 518 enforceConnectivityInternalPermission(); 519 mLog.trace("getCurrentNetworkWpsNfcConfigurationToken uid=%") 520 .c(Binder.getCallingUid()).flush(); 521 // TODO Add private logging for netId b/33807876 522 return mWifiStateMachine.syncGetCurrentNetworkWpsNfcConfigurationToken(); 523 } 524 525 boolean mInIdleMode; 526 boolean mScanPending; 527 528 void handleIdleModeChanged() { 529 boolean doScan = false; 530 synchronized (this) { 531 boolean idle = mPowerManager.isDeviceIdleMode(); 532 if (mInIdleMode != idle) { 533 mInIdleMode = idle; 534 if (!idle) { 535 if (mScanPending) { 536 mScanPending = false; 537 doScan = true; 538 } 539 } 540 } 541 } 542 if (doScan) { 543 // Someone requested a scan while we were idle; do a full scan now. 544 startScan(null, null); 545 } 546 } 547 548 private void enforceNetworkStackPermission() { 549 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.NETWORK_STACK, 550 "WifiService"); 551 } 552 553 private void enforceAccessPermission() { 554 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE, 555 "WifiService"); 556 } 557 558 private void enforceChangePermission() { 559 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE, 560 "WifiService"); 561 } 562 563 private void enforceLocationHardwarePermission() { 564 mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, 565 "LocationHardware"); 566 } 567 568 private void enforceReadCredentialPermission() { 569 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.READ_WIFI_CREDENTIAL, 570 "WifiService"); 571 } 572 573 private void enforceWorkSourcePermission() { 574 mContext.enforceCallingPermission(android.Manifest.permission.UPDATE_DEVICE_STATS, 575 "WifiService"); 576 577 } 578 579 private void enforceMulticastChangePermission() { 580 mContext.enforceCallingOrSelfPermission( 581 android.Manifest.permission.CHANGE_WIFI_MULTICAST_STATE, 582 "WifiService"); 583 } 584 585 private void enforceConnectivityInternalPermission() { 586 mContext.enforceCallingOrSelfPermission( 587 android.Manifest.permission.CONNECTIVITY_INTERNAL, 588 "ConnectivityService"); 589 } 590 591 /** 592 * see {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)} 593 * @param enable {@code true} to enable, {@code false} to disable. 594 * @return {@code true} if the enable/disable operation was 595 * started or is already in the queue. 596 */ 597 @Override 598 public synchronized boolean setWifiEnabled(String packageName, boolean enable) 599 throws RemoteException { 600 enforceChangePermission(); 601 Slog.d(TAG, "setWifiEnabled: " + enable + " pid=" + Binder.getCallingPid() 602 + ", uid=" + Binder.getCallingUid() + ", package=" + packageName); 603 mLog.trace("setWifiEnabled package=% uid=% enable=%").c(packageName) 604 .c(Binder.getCallingUid()).c(enable).flush(); 605 606 // If SoftAp is enabled, only Settings is allowed to toggle wifi 607 boolean apEnabled = 608 mWifiStateMachine.syncGetWifiApState() != WifiManager.WIFI_AP_STATE_DISABLED; 609 boolean isFromSettings = 610 packageName.equals(SYSUI_PACKAGE_NAME) || packageName.equals(SETTINGS_PACKAGE_NAME); 611 if (apEnabled && !isFromSettings) { 612 mLog.trace("setWifiEnabled SoftAp not disabled: only Settings can enable wifi").flush(); 613 return false; 614 } 615 616 /* 617 * Caller might not have WRITE_SECURE_SETTINGS, 618 * only CHANGE_WIFI_STATE is enforced 619 */ 620 long ident = Binder.clearCallingIdentity(); 621 try { 622 if (! mSettingsStore.handleWifiToggled(enable)) { 623 // Nothing to do if wifi cannot be toggled 624 return true; 625 } 626 } finally { 627 Binder.restoreCallingIdentity(ident); 628 } 629 630 631 if (mPermissionReviewRequired) { 632 final int wiFiEnabledState = getWifiEnabledState(); 633 if (enable) { 634 if (wiFiEnabledState == WifiManager.WIFI_STATE_DISABLING 635 || wiFiEnabledState == WifiManager.WIFI_STATE_DISABLED) { 636 if (startConsentUi(packageName, Binder.getCallingUid(), 637 WifiManager.ACTION_REQUEST_ENABLE)) { 638 return true; 639 } 640 } 641 } else if (wiFiEnabledState == WifiManager.WIFI_STATE_ENABLING 642 || wiFiEnabledState == WifiManager.WIFI_STATE_ENABLED) { 643 if (startConsentUi(packageName, Binder.getCallingUid(), 644 WifiManager.ACTION_REQUEST_DISABLE)) { 645 return true; 646 } 647 } 648 } 649 650 mWifiController.sendMessage(CMD_WIFI_TOGGLED); 651 return true; 652 } 653 654 /** 655 * see {@link WifiManager#getWifiState()} 656 * @return One of {@link WifiManager#WIFI_STATE_DISABLED}, 657 * {@link WifiManager#WIFI_STATE_DISABLING}, 658 * {@link WifiManager#WIFI_STATE_ENABLED}, 659 * {@link WifiManager#WIFI_STATE_ENABLING}, 660 * {@link WifiManager#WIFI_STATE_UNKNOWN} 661 */ 662 @Override 663 public int getWifiEnabledState() { 664 enforceAccessPermission(); 665 mLog.trace("getWifiEnabledState uid=%").c(Binder.getCallingUid()).flush(); 666 return mWifiStateMachine.syncGetWifiState(); 667 } 668 669 /** 670 * see {@link android.net.wifi.WifiManager#setWifiApEnabled(WifiConfiguration, boolean)} 671 * @param wifiConfig SSID, security and channel details as 672 * part of WifiConfiguration 673 * @param enabled true to enable and false to disable 674 */ 675 @Override 676 public void setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) { 677 enforceChangePermission(); 678 mWifiPermissionsUtil.enforceTetherChangePermission(mContext); 679 680 mLog.trace("setWifiApEnabled uid=% enable=%").c(Binder.getCallingUid()).c(enabled).flush(); 681 682 if (mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING)) { 683 throw new SecurityException("DISALLOW_CONFIG_TETHERING is enabled for this user."); 684 } 685 // null wifiConfig is a meaningful input for CMD_SET_AP 686 if (wifiConfig == null || isValid(wifiConfig)) { 687 mWifiController.sendMessage(CMD_SET_AP, enabled ? 1 : 0, 0, wifiConfig); 688 } else { 689 Slog.e(TAG, "Invalid WifiConfiguration"); 690 } 691 } 692 693 /** 694 * see {@link WifiManager#getWifiApState()} 695 * @return One of {@link WifiManager#WIFI_AP_STATE_DISABLED}, 696 * {@link WifiManager#WIFI_AP_STATE_DISABLING}, 697 * {@link WifiManager#WIFI_AP_STATE_ENABLED}, 698 * {@link WifiManager#WIFI_AP_STATE_ENABLING}, 699 * {@link WifiManager#WIFI_AP_STATE_FAILED} 700 */ 701 @Override 702 public int getWifiApEnabledState() { 703 enforceAccessPermission(); 704 mLog.trace("getWifiApEnabledState uid=%").c(Binder.getCallingUid()).flush(); 705 return mWifiStateMachine.syncGetWifiApState(); 706 } 707 708 /** 709 * see {@link android.net.wifi.WifiManager#updateInterfaceIpState(String, int)} 710 * 711 * The possible modes include: {@link WifiManager#IFACE_IP_MODE_TETHERED}, 712 * {@link WifiManager#IFACE_IP_MODE_LOCAL_ONLY}, 713 * {@link WifiManager#IFACE_IP_MODE_CONFIGURATION_ERROR} 714 * 715 * @param ifaceName String name of the updated interface 716 * @param mode new operating mode of the interface 717 * 718 * @throws SecurityException if the caller does not have permission to call update 719 */ 720 @Override 721 public void updateInterfaceIpState(String ifaceName, int mode) { 722 // NETWORK_STACK is a signature only permission. 723 enforceNetworkStackPermission(); 724 725 Slog.d(TAG, "updateInterfaceIpState: ifaceName=" + ifaceName + " mode=" + mode); 726 // TODO: keep track of modes in a datastructure - protect it with a lock of some sort. 727 // TODO: check the mode when startLOHS comes in in case it is already active 728 // TODO: if mode == LOCAL_ONLY, trigger onStarted callbacks 729 } 730 731 /** 732 * see {@link android.net.wifi.WifiManager#startSoftAp(WifiConfiguration)} 733 * @param wifiConfig SSID, security and channel details as 734 * part of WifiConfiguration 735 * @return {@code true} if softap start was triggered 736 * @throws SecurityException if the caller does not have permission to start softap 737 */ 738 @Override 739 public boolean startSoftAp(WifiConfiguration wifiConfig) { 740 // NETWORK_STACK is a signature only permission. 741 enforceNetworkStackPermission(); 742 743 mLog.trace("startSoftAp uid=%").c(Binder.getCallingUid()).flush(); 744 745 return startSoftApInternal(wifiConfig, STATE_TETHERED); 746 } 747 748 private boolean startSoftApInternal(WifiConfiguration wifiConfig, int mode) { 749 mLog.trace("startSoftApInternal uid=% mode=%") 750 .c(Binder.getCallingUid()).c(mode).flush(); 751 752 // null wifiConfig is a meaningful input for CMD_SET_AP 753 if (wifiConfig == null || isValid(wifiConfig)) { 754 // TODO: need a way to set the mode 755 mWifiController.sendMessage(CMD_SET_AP, 1, 0, wifiConfig); 756 return true; 757 } 758 Slog.e(TAG, "Invalid WifiConfiguration"); 759 return false; 760 } 761 762 /** 763 * see {@link android.net.wifi.WifiManager#stopSoftAp()} 764 * @return {@code true} if softap stop was triggered 765 * @throws SecurityException if the caller does not have permission to stop softap 766 */ 767 @Override 768 public boolean stopSoftAp() { 769 // NETWORK_STACK is a signature only permission. 770 enforceNetworkStackPermission(); 771 772 mLog.trace("stopSoftAp uid=%").c(Binder.getCallingUid()).flush(); 773 774 // add checks here to make sure this is the proper caller - apps can't disable tethering or 775 // instances of local only hotspot that they didn't start. return false for those cases 776 777 return stopSoftApInternal(); 778 } 779 780 /** 781 * Internal method to stop softap mode. Callers of this method should have already checked 782 * proper permissions beyond the NetworkStack permission. 783 */ 784 private boolean stopSoftApInternal() { 785 mLog.trace("stopSoftApInternal uid=%").c(Binder.getCallingUid()).flush(); 786 787 mWifiController.sendMessage(CMD_SET_AP, 0, 0); 788 return true; 789 } 790 791 /** 792 * see {@link WifiManager#getWifiApConfiguration()} 793 * @return soft access point configuration 794 * @throws SecurityException if the caller does not have permission to retrieve the softap 795 * config 796 */ 797 @Override 798 public WifiConfiguration getWifiApConfiguration() { 799 enforceAccessPermission(); 800 int uid = Binder.getCallingUid(); 801 // only allow Settings UI to get the saved SoftApConfig 802 if (!mWifiPermissionsUtil.checkConfigOverridePermission(uid)) { 803 // random apps should not be allowed to read the user specified config 804 throw new SecurityException("App not allowed to read or update stored WiFi Ap config " 805 + "(uid = " + uid + ")"); 806 } 807 mLog.trace("getWifiApConfiguration uid=%").c(uid).flush(); 808 return mWifiStateMachine.syncGetWifiApConfiguration(); 809 } 810 811 /** 812 * see {@link WifiManager#setWifiApConfiguration(WifiConfiguration)} 813 * @param wifiConfig WifiConfiguration details for soft access point 814 * @throws SecurityException if the caller does not have permission to write the sotap config 815 */ 816 @Override 817 public void setWifiApConfiguration(WifiConfiguration wifiConfig) { 818 enforceChangePermission(); 819 int uid = Binder.getCallingUid(); 820 // only allow Settings UI to write the stored SoftApConfig 821 if (!mWifiPermissionsUtil.checkConfigOverridePermission(uid)) { 822 // random apps should not be allowed to read the user specified config 823 throw new SecurityException("App not allowed to read or update stored WiFi AP config " 824 + "(uid = " + uid + ")"); 825 } 826 mLog.trace("setWifiApConfiguration uid=%").c(uid).flush(); 827 if (wifiConfig == null) 828 return; 829 if (isValid(wifiConfig)) { 830 mWifiStateMachine.setWifiApConfiguration(wifiConfig); 831 } else { 832 Slog.e(TAG, "Invalid WifiConfiguration"); 833 } 834 } 835 836 /** 837 * see {@link android.net.wifi.WifiManager#isScanAlwaysAvailable()} 838 */ 839 @Override 840 public boolean isScanAlwaysAvailable() { 841 enforceAccessPermission(); 842 mLog.trace("isScanAlwaysAvailable uid=%").c(Binder.getCallingUid()).flush(); 843 return mSettingsStore.isScanAlwaysAvailable(); 844 } 845 846 /** 847 * see {@link android.net.wifi.WifiManager#disconnect()} 848 */ 849 @Override 850 public void disconnect() { 851 enforceChangePermission(); 852 mLog.trace("disconnect uid=%").c(Binder.getCallingUid()).flush(); 853 mWifiStateMachine.disconnectCommand(); 854 } 855 856 /** 857 * see {@link android.net.wifi.WifiManager#reconnect()} 858 */ 859 @Override 860 public void reconnect() { 861 enforceChangePermission(); 862 mLog.trace("reconnect uid=%").c(Binder.getCallingUid()).flush(); 863 mWifiStateMachine.reconnectCommand(); 864 } 865 866 /** 867 * see {@link android.net.wifi.WifiManager#reassociate()} 868 */ 869 @Override 870 public void reassociate() { 871 enforceChangePermission(); 872 mLog.trace("reassociate uid=%").c(Binder.getCallingUid()).flush(); 873 mWifiStateMachine.reassociateCommand(); 874 } 875 876 /** 877 * see {@link android.net.wifi.WifiManager#getSupportedFeatures} 878 */ 879 @Override 880 public int getSupportedFeatures() { 881 enforceAccessPermission(); 882 mLog.trace("getSupportedFeatures uid=%").c(Binder.getCallingUid()).flush(); 883 if (mWifiStateMachineChannel != null) { 884 return mWifiStateMachine.syncGetSupportedFeatures(mWifiStateMachineChannel); 885 } else { 886 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 887 return 0; 888 } 889 } 890 891 @Override 892 public void requestActivityInfo(ResultReceiver result) { 893 Bundle bundle = new Bundle(); 894 mLog.trace("requestActivityInfo uid=%").c(Binder.getCallingUid()).flush(); 895 bundle.putParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY, reportActivityInfo()); 896 result.send(0, bundle); 897 } 898 899 /** 900 * see {@link android.net.wifi.WifiManager#getControllerActivityEnergyInfo(int)} 901 */ 902 @Override 903 public WifiActivityEnergyInfo reportActivityInfo() { 904 enforceAccessPermission(); 905 mLog.trace("reportActivityInfo uid=%").c(Binder.getCallingUid()).flush(); 906 if ((getSupportedFeatures() & WifiManager.WIFI_FEATURE_LINK_LAYER_STATS) == 0) { 907 return null; 908 } 909 WifiLinkLayerStats stats; 910 WifiActivityEnergyInfo energyInfo = null; 911 if (mWifiStateMachineChannel != null) { 912 stats = mWifiStateMachine.syncGetLinkLayerStats(mWifiStateMachineChannel); 913 if (stats != null) { 914 final long rxIdleCurrent = mContext.getResources().getInteger( 915 com.android.internal.R.integer.config_wifi_idle_receive_cur_ma); 916 final long rxCurrent = mContext.getResources().getInteger( 917 com.android.internal.R.integer.config_wifi_active_rx_cur_ma); 918 final long txCurrent = mContext.getResources().getInteger( 919 com.android.internal.R.integer.config_wifi_tx_cur_ma); 920 final double voltage = mContext.getResources().getInteger( 921 com.android.internal.R.integer.config_wifi_operating_voltage_mv) 922 / 1000.0; 923 924 final long rxIdleTime = stats.on_time - stats.tx_time - stats.rx_time; 925 final long[] txTimePerLevel; 926 if (stats.tx_time_per_level != null) { 927 txTimePerLevel = new long[stats.tx_time_per_level.length]; 928 for (int i = 0; i < txTimePerLevel.length; i++) { 929 txTimePerLevel[i] = stats.tx_time_per_level[i]; 930 // TODO(b/27227497): Need to read the power consumed per level from config 931 } 932 } else { 933 // This will happen if the HAL get link layer API returned null. 934 txTimePerLevel = new long[0]; 935 } 936 final long energyUsed = (long)((stats.tx_time * txCurrent + 937 stats.rx_time * rxCurrent + 938 rxIdleTime * rxIdleCurrent) * voltage); 939 if (VDBG || rxIdleTime < 0 || stats.on_time < 0 || stats.tx_time < 0 || 940 stats.rx_time < 0 || energyUsed < 0) { 941 StringBuilder sb = new StringBuilder(); 942 sb.append(" rxIdleCur=" + rxIdleCurrent); 943 sb.append(" rxCur=" + rxCurrent); 944 sb.append(" txCur=" + txCurrent); 945 sb.append(" voltage=" + voltage); 946 sb.append(" on_time=" + stats.on_time); 947 sb.append(" tx_time=" + stats.tx_time); 948 sb.append(" tx_time_per_level=" + Arrays.toString(txTimePerLevel)); 949 sb.append(" rx_time=" + stats.rx_time); 950 sb.append(" rxIdleTime=" + rxIdleTime); 951 sb.append(" energy=" + energyUsed); 952 Log.d(TAG, " reportActivityInfo: " + sb.toString()); 953 } 954 955 // Convert the LinkLayerStats into EnergyActivity 956 energyInfo = new WifiActivityEnergyInfo(SystemClock.elapsedRealtime(), 957 WifiActivityEnergyInfo.STACK_STATE_STATE_IDLE, stats.tx_time, 958 txTimePerLevel, stats.rx_time, rxIdleTime, energyUsed); 959 } 960 if (energyInfo != null && energyInfo.isValid()) { 961 return energyInfo; 962 } else { 963 return null; 964 } 965 } else { 966 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 967 return null; 968 } 969 } 970 971 /** 972 * see {@link android.net.wifi.WifiManager#getConfiguredNetworks()} 973 * @return the list of configured networks 974 */ 975 @Override 976 public ParceledListSlice<WifiConfiguration> getConfiguredNetworks() { 977 enforceAccessPermission(); 978 mLog.trace("getConfiguredNetworks uid=%").c(Binder.getCallingUid()).flush(); 979 if (mWifiStateMachineChannel != null) { 980 List<WifiConfiguration> configs = mWifiStateMachine.syncGetConfiguredNetworks( 981 Binder.getCallingUid(), mWifiStateMachineChannel); 982 if (configs != null) { 983 return new ParceledListSlice<WifiConfiguration>(configs); 984 } 985 } else { 986 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 987 } 988 return null; 989 } 990 991 /** 992 * see {@link android.net.wifi.WifiManager#getPrivilegedConfiguredNetworks()} 993 * @return the list of configured networks with real preSharedKey 994 */ 995 @Override 996 public ParceledListSlice<WifiConfiguration> getPrivilegedConfiguredNetworks() { 997 enforceReadCredentialPermission(); 998 enforceAccessPermission(); 999 mLog.trace("getPrivilegedConfiguredNetworks uid=%").c(Binder.getCallingUid()).flush(); 1000 if (mWifiStateMachineChannel != null) { 1001 List<WifiConfiguration> configs = 1002 mWifiStateMachine.syncGetPrivilegedConfiguredNetwork(mWifiStateMachineChannel); 1003 if (configs != null) { 1004 return new ParceledListSlice<WifiConfiguration>(configs); 1005 } 1006 } else { 1007 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1008 } 1009 return null; 1010 } 1011 1012 /** 1013 * Returns a WifiConfiguration for a Passpoint network matching this ScanResult. 1014 * 1015 * @param scanResult scanResult that represents the BSSID 1016 * @return {@link WifiConfiguration} that matches this BSSID or null 1017 */ 1018 @Override 1019 public WifiConfiguration getMatchingWifiConfig(ScanResult scanResult) { 1020 enforceAccessPermission(); 1021 mLog.trace("getMatchingWifiConfig uid=%").c(Binder.getCallingUid()).flush(); 1022 if (!mContext.getResources().getBoolean( 1023 com.android.internal.R.bool.config_wifi_hotspot2_enabled)) { 1024 throw new UnsupportedOperationException("Passpoint not enabled"); 1025 } 1026 return mWifiStateMachine.syncGetMatchingWifiConfig(scanResult, mWifiStateMachineChannel); 1027 } 1028 1029 /** 1030 * see {@link android.net.wifi.WifiManager#addOrUpdateNetwork(WifiConfiguration)} 1031 * @return the supplicant-assigned identifier for the new or updated 1032 * network if the operation succeeds, or {@code -1} if it fails 1033 */ 1034 @Override 1035 public int addOrUpdateNetwork(WifiConfiguration config) { 1036 enforceChangePermission(); 1037 mLog.trace("addOrUpdateNetwork uid=%").c(Binder.getCallingUid()).flush(); 1038 if (isValid(config) && isValidPasspoint(config)) { 1039 1040 WifiEnterpriseConfig enterpriseConfig = config.enterpriseConfig; 1041 1042 if (config.isPasspoint() && 1043 (enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TLS || 1044 enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TTLS)) { 1045 if (config.updateIdentifier != null) { 1046 enforceAccessPermission(); 1047 } 1048 else { 1049 try { 1050 verifyCert(enterpriseConfig.getCaCertificate()); 1051 } catch (CertPathValidatorException cpve) { 1052 Slog.e(TAG, "CA Cert " + 1053 enterpriseConfig.getCaCertificate().getSubjectX500Principal() + 1054 " untrusted: " + cpve.getMessage()); 1055 return -1; 1056 } catch (GeneralSecurityException | IOException e) { 1057 Slog.e(TAG, "Failed to verify certificate" + 1058 enterpriseConfig.getCaCertificate().getSubjectX500Principal() + 1059 ": " + e); 1060 return -1; 1061 } 1062 } 1063 } 1064 1065 //TODO: pass the Uid the WifiStateMachine as a message parameter 1066 Slog.i("addOrUpdateNetwork", " uid = " + Integer.toString(Binder.getCallingUid()) 1067 + " SSID " + config.SSID 1068 + " nid=" + Integer.toString(config.networkId)); 1069 if (config.networkId == WifiConfiguration.INVALID_NETWORK_ID) { 1070 config.creatorUid = Binder.getCallingUid(); 1071 } else { 1072 config.lastUpdateUid = Binder.getCallingUid(); 1073 } 1074 if (mWifiStateMachineChannel != null) { 1075 return mWifiStateMachine.syncAddOrUpdateNetwork(mWifiStateMachineChannel, config); 1076 } else { 1077 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1078 return -1; 1079 } 1080 } else { 1081 Slog.e(TAG, "bad network configuration"); 1082 return -1; 1083 } 1084 } 1085 1086 public static void verifyCert(X509Certificate caCert) 1087 throws GeneralSecurityException, IOException { 1088 CertificateFactory factory = CertificateFactory.getInstance("X.509"); 1089 CertPathValidator validator = 1090 CertPathValidator.getInstance(CertPathValidator.getDefaultType()); 1091 CertPath path = factory.generateCertPath( 1092 Arrays.asList(caCert)); 1093 KeyStore ks = KeyStore.getInstance("AndroidCAStore"); 1094 ks.load(null, null); 1095 PKIXParameters params = new PKIXParameters(ks); 1096 params.setRevocationEnabled(false); 1097 validator.validate(path, params); 1098 } 1099 1100 /** 1101 * See {@link android.net.wifi.WifiManager#removeNetwork(int)} 1102 * @param netId the integer that identifies the network configuration 1103 * to the supplicant 1104 * @return {@code true} if the operation succeeded 1105 */ 1106 @Override 1107 public boolean removeNetwork(int netId) { 1108 enforceChangePermission(); 1109 mLog.trace("removeNetwork uid=%").c(Binder.getCallingUid()).flush(); 1110 // TODO Add private logging for netId b/33807876 1111 if (mWifiStateMachineChannel != null) { 1112 return mWifiStateMachine.syncRemoveNetwork(mWifiStateMachineChannel, netId); 1113 } else { 1114 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1115 return false; 1116 } 1117 } 1118 1119 /** 1120 * See {@link android.net.wifi.WifiManager#enableNetwork(int, boolean)} 1121 * @param netId the integer that identifies the network configuration 1122 * to the supplicant 1123 * @param disableOthers if true, disable all other networks. 1124 * @return {@code true} if the operation succeeded 1125 */ 1126 @Override 1127 public boolean enableNetwork(int netId, boolean disableOthers) { 1128 enforceChangePermission(); 1129 // TODO b/33807876 Log netId 1130 mLog.trace("enableNetwork uid=% disableOthers=%") 1131 .c(Binder.getCallingUid()) 1132 .c(disableOthers).flush(); 1133 1134 if (mWifiStateMachineChannel != null) { 1135 return mWifiStateMachine.syncEnableNetwork(mWifiStateMachineChannel, netId, 1136 disableOthers); 1137 } else { 1138 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1139 return false; 1140 } 1141 } 1142 1143 /** 1144 * See {@link android.net.wifi.WifiManager#disableNetwork(int)} 1145 * @param netId the integer that identifies the network configuration 1146 * to the supplicant 1147 * @return {@code true} if the operation succeeded 1148 */ 1149 @Override 1150 public boolean disableNetwork(int netId) { 1151 enforceChangePermission(); 1152 // TODO b/33807876 Log netId 1153 mLog.trace("disableNetwork uid=%").c(Binder.getCallingUid()).flush(); 1154 1155 if (mWifiStateMachineChannel != null) { 1156 return mWifiStateMachine.syncDisableNetwork(mWifiStateMachineChannel, netId); 1157 } else { 1158 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1159 return false; 1160 } 1161 } 1162 1163 /** 1164 * See {@link android.net.wifi.WifiManager#getConnectionInfo()} 1165 * @return the Wi-Fi information, contained in {@link WifiInfo}. 1166 */ 1167 @Override 1168 public WifiInfo getConnectionInfo() { 1169 enforceAccessPermission(); 1170 mLog.trace("getConnectionInfo uid=%").c(Binder.getCallingUid()).flush(); 1171 /* 1172 * Make sure we have the latest information, by sending 1173 * a status request to the supplicant. 1174 */ 1175 return mWifiStateMachine.syncRequestConnectionInfo(); 1176 } 1177 1178 /** 1179 * Return the results of the most recent access point scan, in the form of 1180 * a list of {@link ScanResult} objects. 1181 * @return the list of results 1182 */ 1183 @Override 1184 public List<ScanResult> getScanResults(String callingPackage) { 1185 enforceAccessPermission(); 1186 int uid = Binder.getCallingUid(); 1187 long ident = Binder.clearCallingIdentity(); 1188 try { 1189 if (!mWifiPermissionsUtil.canAccessScanResults(callingPackage, 1190 uid, Build.VERSION_CODES.M)) { 1191 return new ArrayList<ScanResult>(); 1192 } 1193 if (mWifiScanner == null) { 1194 mWifiScanner = mWifiInjector.getWifiScanner(); 1195 } 1196 return mWifiScanner.getSingleScanResults(); 1197 } finally { 1198 Binder.restoreCallingIdentity(ident); 1199 } 1200 } 1201 1202 /** 1203 * Add or update a Passpoint configuration. 1204 * 1205 * @param config The Passpoint configuration to be added 1206 * @return true on success or false on failure 1207 */ 1208 @Override 1209 public boolean addOrUpdatePasspointConfiguration(PasspointConfiguration config) { 1210 enforceChangePermission(); 1211 mLog.trace("addorUpdatePasspointConfiguration uid=%").c(Binder.getCallingUid()).flush(); 1212 if (!mContext.getResources().getBoolean( 1213 com.android.internal.R.bool.config_wifi_hotspot2_enabled)) { 1214 throw new UnsupportedOperationException("Passpoint not enabled"); 1215 } 1216 return mWifiStateMachine.syncAddOrUpdatePasspointConfig(mWifiStateMachineChannel, config, 1217 Binder.getCallingUid()); 1218 } 1219 1220 /** 1221 * Remove the Passpoint configuration identified by its FQDN (Fully Qualified Domain Name). 1222 * 1223 * @param fqdn The FQDN of the Passpoint configuration to be removed 1224 * @return true on success or false on failure 1225 */ 1226 @Override 1227 public boolean removePasspointConfiguration(String fqdn) { 1228 enforceChangePermission(); 1229 mLog.trace("removePasspointConfiguration uid=%").c(Binder.getCallingUid()).flush(); 1230 if (!mContext.getResources().getBoolean( 1231 com.android.internal.R.bool.config_wifi_hotspot2_enabled)) { 1232 throw new UnsupportedOperationException("Passpoint not enabled"); 1233 } 1234 return mWifiStateMachine.syncRemovePasspointConfig(mWifiStateMachineChannel, fqdn); 1235 } 1236 1237 /** 1238 * Return the list of the installed Passpoint configurations. 1239 * 1240 * An empty list will be returned when no configuration is installed. 1241 * 1242 * @return A list of {@link PasspointConfiguration} 1243 */ 1244 @Override 1245 public List<PasspointConfiguration> getPasspointConfigurations() { 1246 enforceAccessPermission(); 1247 mLog.trace("getPasspointConfigurations uid=%").c(Binder.getCallingUid()).flush(); 1248 if (!mContext.getResources().getBoolean( 1249 com.android.internal.R.bool.config_wifi_hotspot2_enabled)) { 1250 throw new UnsupportedOperationException("Passpoint not enabled"); 1251 } 1252 return mWifiStateMachine.syncGetPasspointConfigs(mWifiStateMachineChannel); 1253 } 1254 1255 /** 1256 * Query for a Hotspot 2.0 release 2 OSU icon 1257 * @param bssid The BSSID of the AP 1258 * @param fileName Icon file name 1259 */ 1260 @Override 1261 public void queryPasspointIcon(long bssid, String fileName) { 1262 enforceAccessPermission(); 1263 mLog.trace("queryPasspointIcon uid=%").c(Binder.getCallingUid()).flush(); 1264 if (!mContext.getResources().getBoolean( 1265 com.android.internal.R.bool.config_wifi_hotspot2_enabled)) { 1266 throw new UnsupportedOperationException("Passpoint not enabled"); 1267 } 1268 mWifiStateMachine.syncQueryPasspointIcon(mWifiStateMachineChannel, bssid, fileName); 1269 } 1270 1271 /** 1272 * Match the currently associated network against the SP matching the given FQDN 1273 * @param fqdn FQDN of the SP 1274 * @return ordinal [HomeProvider, RoamingProvider, Incomplete, None, Declined] 1275 */ 1276 @Override 1277 public int matchProviderWithCurrentNetwork(String fqdn) { 1278 mLog.trace("matchProviderWithCurrentNetwork uid=%").c(Binder.getCallingUid()).flush(); 1279 return mWifiStateMachine.matchProviderWithCurrentNetwork(mWifiStateMachineChannel, fqdn); 1280 } 1281 1282 /** 1283 * Deauthenticate and set the re-authentication hold off time for the current network 1284 * @param holdoff hold off time in milliseconds 1285 * @param ess set if the hold off pertains to an ESS rather than a BSS 1286 */ 1287 @Override 1288 public void deauthenticateNetwork(long holdoff, boolean ess) { 1289 mLog.trace("deauthenticateNetwork uid=%").c(Binder.getCallingUid()).flush(); 1290 mWifiStateMachine.deauthenticateNetwork(mWifiStateMachineChannel, holdoff, ess); 1291 } 1292 1293 /** 1294 * Tell the supplicant to persist the current list of configured networks. 1295 * @return {@code true} if the operation succeeded 1296 * 1297 * TODO: deprecate this 1298 */ 1299 @Override 1300 public boolean saveConfiguration() { 1301 enforceChangePermission(); 1302 mLog.trace("saveConfiguration uid=%").c(Binder.getCallingUid()).flush(); 1303 if (mWifiStateMachineChannel != null) { 1304 return mWifiStateMachine.syncSaveConfig(mWifiStateMachineChannel); 1305 } else { 1306 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1307 return false; 1308 } 1309 } 1310 1311 /** 1312 * Set the country code 1313 * @param countryCode ISO 3166 country code. 1314 * @param persist {@code true} if the setting should be remembered. 1315 * 1316 * The persist behavior exists so that wifi can fall back to the last 1317 * persisted country code on a restart, when the locale information is 1318 * not available from telephony. 1319 */ 1320 @Override 1321 public void setCountryCode(String countryCode, boolean persist) { 1322 Slog.i(TAG, "WifiService trying to set country code to " + countryCode + 1323 " with persist set to " + persist); 1324 enforceConnectivityInternalPermission(); 1325 mLog.trace("setCountryCode uid=%").c(Binder.getCallingUid()).flush(); 1326 final long token = Binder.clearCallingIdentity(); 1327 mCountryCode.setCountryCode(countryCode); 1328 Binder.restoreCallingIdentity(token); 1329 } 1330 1331 /** 1332 * Get the country code 1333 * @return Get the best choice country code for wifi, regardless of if it was set or 1334 * not. 1335 * Returns null when there is no country code available. 1336 */ 1337 @Override 1338 public String getCountryCode() { 1339 enforceConnectivityInternalPermission(); 1340 mLog.trace("getCountryCode uid=%").c(Binder.getCallingUid()).flush(); 1341 String country = mCountryCode.getCountryCode(); 1342 return country; 1343 } 1344 1345 @Override 1346 public boolean isDualBandSupported() { 1347 //TODO: Should move towards adding a driver API that checks at runtime 1348 mLog.trace("isDualBandSupported uid=%").c(Binder.getCallingUid()).flush(); 1349 return mContext.getResources().getBoolean( 1350 com.android.internal.R.bool.config_wifi_dual_band_support); 1351 } 1352 1353 /** 1354 * Return the DHCP-assigned addresses from the last successful DHCP request, 1355 * if any. 1356 * @return the DHCP information 1357 * @deprecated 1358 */ 1359 @Override 1360 @Deprecated 1361 public DhcpInfo getDhcpInfo() { 1362 enforceAccessPermission(); 1363 mLog.trace("getDhcpInfo uid=%").c(Binder.getCallingUid()).flush(); 1364 DhcpResults dhcpResults = mWifiStateMachine.syncGetDhcpResults(); 1365 1366 DhcpInfo info = new DhcpInfo(); 1367 1368 if (dhcpResults.ipAddress != null && 1369 dhcpResults.ipAddress.getAddress() instanceof Inet4Address) { 1370 info.ipAddress = NetworkUtils.inetAddressToInt((Inet4Address) dhcpResults.ipAddress.getAddress()); 1371 } 1372 1373 if (dhcpResults.gateway != null) { 1374 info.gateway = NetworkUtils.inetAddressToInt((Inet4Address) dhcpResults.gateway); 1375 } 1376 1377 int dnsFound = 0; 1378 for (InetAddress dns : dhcpResults.dnsServers) { 1379 if (dns instanceof Inet4Address) { 1380 if (dnsFound == 0) { 1381 info.dns1 = NetworkUtils.inetAddressToInt((Inet4Address)dns); 1382 } else { 1383 info.dns2 = NetworkUtils.inetAddressToInt((Inet4Address)dns); 1384 } 1385 if (++dnsFound > 1) break; 1386 } 1387 } 1388 Inet4Address serverAddress = dhcpResults.serverAddress; 1389 if (serverAddress != null) { 1390 info.serverAddress = NetworkUtils.inetAddressToInt(serverAddress); 1391 } 1392 info.leaseDuration = dhcpResults.leaseDuration; 1393 1394 return info; 1395 } 1396 1397 /** 1398 * enable TDLS for the local NIC to remote NIC 1399 * The APPs don't know the remote MAC address to identify NIC though, 1400 * so we need to do additional work to find it from remote IP address 1401 */ 1402 1403 class TdlsTaskParams { 1404 public String remoteIpAddress; 1405 public boolean enable; 1406 } 1407 1408 class TdlsTask extends AsyncTask<TdlsTaskParams, Integer, Integer> { 1409 @Override 1410 protected Integer doInBackground(TdlsTaskParams... params) { 1411 1412 // Retrieve parameters for the call 1413 TdlsTaskParams param = params[0]; 1414 String remoteIpAddress = param.remoteIpAddress.trim(); 1415 boolean enable = param.enable; 1416 1417 // Get MAC address of Remote IP 1418 String macAddress = null; 1419 1420 BufferedReader reader = null; 1421 1422 try { 1423 reader = new BufferedReader(new FileReader("/proc/net/arp")); 1424 1425 // Skip over the line bearing colum titles 1426 String line = reader.readLine(); 1427 1428 while ((line = reader.readLine()) != null) { 1429 String[] tokens = line.split("[ ]+"); 1430 if (tokens.length < 6) { 1431 continue; 1432 } 1433 1434 // ARP column format is 1435 // Address HWType HWAddress Flags Mask IFace 1436 String ip = tokens[0]; 1437 String mac = tokens[3]; 1438 1439 if (remoteIpAddress.equals(ip)) { 1440 macAddress = mac; 1441 break; 1442 } 1443 } 1444 1445 if (macAddress == null) { 1446 Slog.w(TAG, "Did not find remoteAddress {" + remoteIpAddress + "} in " + 1447 "/proc/net/arp"); 1448 } else { 1449 enableTdlsWithMacAddress(macAddress, enable); 1450 } 1451 1452 } catch (FileNotFoundException e) { 1453 Slog.e(TAG, "Could not open /proc/net/arp to lookup mac address"); 1454 } catch (IOException e) { 1455 Slog.e(TAG, "Could not read /proc/net/arp to lookup mac address"); 1456 } finally { 1457 try { 1458 if (reader != null) { 1459 reader.close(); 1460 } 1461 } 1462 catch (IOException e) { 1463 // Do nothing 1464 } 1465 } 1466 1467 return 0; 1468 } 1469 } 1470 1471 @Override 1472 public void enableTdls(String remoteAddress, boolean enable) { 1473 if (remoteAddress == null) { 1474 throw new IllegalArgumentException("remoteAddress cannot be null"); 1475 } 1476 mLog.trace("enableTdls uid=% enable=%").c(Binder.getCallingUid()).c(enable).flush(); 1477 TdlsTaskParams params = new TdlsTaskParams(); 1478 params.remoteIpAddress = remoteAddress; 1479 params.enable = enable; 1480 new TdlsTask().execute(params); 1481 } 1482 1483 1484 @Override 1485 public void enableTdlsWithMacAddress(String remoteMacAddress, boolean enable) { 1486 mLog.trace("enableTdlsWithMacAddress uid=% enable=%") 1487 .c(Binder.getCallingUid()) 1488 .c(enable) 1489 .flush(); 1490 if (remoteMacAddress == null) { 1491 throw new IllegalArgumentException("remoteMacAddress cannot be null"); 1492 } 1493 1494 mWifiStateMachine.enableTdls(remoteMacAddress, enable); 1495 } 1496 1497 /** 1498 * Get a reference to handler. This is used by a client to establish 1499 * an AsyncChannel communication with WifiService 1500 */ 1501 @Override 1502 public Messenger getWifiServiceMessenger() { 1503 enforceAccessPermission(); 1504 enforceChangePermission(); 1505 mLog.trace("getWifiServiceMessenger uid=%").c(Binder.getCallingUid()).flush(); 1506 return new Messenger(mClientHandler); 1507 } 1508 1509 /** 1510 * Disable an ephemeral network, i.e. network that is created thru a WiFi Scorer 1511 */ 1512 @Override 1513 public void disableEphemeralNetwork(String SSID) { 1514 enforceAccessPermission(); 1515 enforceChangePermission(); 1516 mLog.trace("disableEphemeralNetwork uid=%").c(Binder.getCallingUid()).flush(); 1517 mWifiStateMachine.disableEphemeralNetwork(SSID); 1518 } 1519 1520 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 1521 @Override 1522 public void onReceive(Context context, Intent intent) { 1523 String action = intent.getAction(); 1524 if (action.equals(Intent.ACTION_SCREEN_ON)) { 1525 mWifiController.sendMessage(CMD_SCREEN_ON); 1526 } else if (action.equals(Intent.ACTION_USER_PRESENT)) { 1527 mWifiController.sendMessage(CMD_USER_PRESENT); 1528 } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { 1529 mWifiController.sendMessage(CMD_SCREEN_OFF); 1530 } else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { 1531 int pluggedType = intent.getIntExtra("plugged", 0); 1532 mWifiController.sendMessage(CMD_BATTERY_CHANGED, pluggedType, 0, null); 1533 } else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) { 1534 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, 1535 BluetoothAdapter.STATE_DISCONNECTED); 1536 mWifiStateMachine.sendBluetoothAdapterStateChange(state); 1537 } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) { 1538 boolean emergencyMode = intent.getBooleanExtra("phoneinECMState", false); 1539 mWifiController.sendMessage(CMD_EMERGENCY_MODE_CHANGED, emergencyMode ? 1 : 0, 0); 1540 } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED)) { 1541 boolean inCall = intent.getBooleanExtra(PhoneConstants.PHONE_IN_EMERGENCY_CALL, false); 1542 mWifiController.sendMessage(CMD_EMERGENCY_CALL_STATE_CHANGED, inCall ? 1 : 0, 0); 1543 } else if (action.equals(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED)) { 1544 handleIdleModeChanged(); 1545 } 1546 } 1547 }; 1548 1549 private boolean startConsentUi(String packageName, 1550 int callingUid, String intentAction) throws RemoteException { 1551 if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) { 1552 return false; 1553 } 1554 try { 1555 // Validate the package only if we are going to use it 1556 ApplicationInfo applicationInfo = mContext.getPackageManager() 1557 .getApplicationInfoAsUser(packageName, 1558 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, 1559 UserHandle.getUserId(callingUid)); 1560 if (applicationInfo.uid != callingUid) { 1561 throw new SecurityException("Package " + callingUid 1562 + " not in uid " + callingUid); 1563 } 1564 1565 // Permission review mode, trigger a user prompt 1566 Intent intent = new Intent(intentAction); 1567 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK 1568 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 1569 intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName); 1570 mContext.startActivity(intent); 1571 return true; 1572 } catch (PackageManager.NameNotFoundException e) { 1573 throw new RemoteException(e.getMessage()); 1574 } 1575 } 1576 1577 /** 1578 * Observes settings changes to scan always mode. 1579 */ 1580 private void registerForScanModeChange() { 1581 ContentObserver contentObserver = new ContentObserver(null) { 1582 @Override 1583 public void onChange(boolean selfChange) { 1584 mSettingsStore.handleWifiScanAlwaysAvailableToggled(); 1585 mWifiController.sendMessage(CMD_SCAN_ALWAYS_MODE_CHANGED); 1586 } 1587 }; 1588 mFrameworkFacade.registerContentObserver(mContext, 1589 Settings.Global.getUriFor(Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE), 1590 false, contentObserver); 1591 } 1592 1593 private void registerForBroadcasts() { 1594 IntentFilter intentFilter = new IntentFilter(); 1595 intentFilter.addAction(Intent.ACTION_SCREEN_ON); 1596 intentFilter.addAction(Intent.ACTION_USER_PRESENT); 1597 intentFilter.addAction(Intent.ACTION_SCREEN_OFF); 1598 intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); 1599 intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); 1600 intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); 1601 intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED); 1602 intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); 1603 1604 boolean trackEmergencyCallState = mContext.getResources().getBoolean( 1605 com.android.internal.R.bool.config_wifi_turn_off_during_emergency_call); 1606 if (trackEmergencyCallState) { 1607 intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED); 1608 } 1609 1610 mContext.registerReceiver(mReceiver, intentFilter); 1611 } 1612 1613 private void registerForPackageOrUserRemoval() { 1614 IntentFilter intentFilter = new IntentFilter(); 1615 intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 1616 intentFilter.addAction(Intent.ACTION_USER_REMOVED); 1617 mContext.registerReceiverAsUser(new BroadcastReceiver() { 1618 @Override 1619 public void onReceive(Context context, Intent intent) { 1620 switch (intent.getAction()) { 1621 case Intent.ACTION_PACKAGE_REMOVED: { 1622 if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { 1623 return; 1624 } 1625 int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); 1626 Uri uri = intent.getData(); 1627 if (uid == -1 || uri == null) { 1628 return; 1629 } 1630 String pkgName = uri.getSchemeSpecificPart(); 1631 mWifiStateMachine.removeAppConfigs(pkgName, uid); 1632 break; 1633 } 1634 case Intent.ACTION_USER_REMOVED: { 1635 int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); 1636 mWifiStateMachine.removeUserConfigs(userHandle); 1637 break; 1638 } 1639 } 1640 } 1641 }, UserHandle.ALL, intentFilter, null, null); 1642 } 1643 1644 @Override 1645 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1646 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1647 != PackageManager.PERMISSION_GRANTED) { 1648 pw.println("Permission Denial: can't dump WifiService from from pid=" 1649 + Binder.getCallingPid() 1650 + ", uid=" + Binder.getCallingUid()); 1651 return; 1652 } 1653 if (args.length > 0 && WifiMetrics.PROTO_DUMP_ARG.equals(args[0])) { 1654 // WifiMetrics proto bytes were requested. Dump only these. 1655 mWifiStateMachine.updateWifiMetrics(); 1656 mWifiMetrics.dump(fd, pw, args); 1657 } else if (args.length > 0 && IpManager.DUMP_ARG.equals(args[0])) { 1658 // IpManager dump was requested. Pass it along and take no further action. 1659 String[] ipManagerArgs = new String[args.length - 1]; 1660 System.arraycopy(args, 1, ipManagerArgs, 0, ipManagerArgs.length); 1661 mWifiStateMachine.dumpIpManager(fd, pw, ipManagerArgs); 1662 } else if (args.length > 0 && DUMP_ARG_SET_IPREACH_DISCONNECT.equals(args[0])) { 1663 if (args.length > 1) { 1664 if (DUMP_ARG_SET_IPREACH_DISCONNECT_ENABLED.equals(args[1])) { 1665 mWifiStateMachine.setIpReachabilityDisconnectEnabled(true); 1666 } else if (DUMP_ARG_SET_IPREACH_DISCONNECT_DISABLED.equals(args[1])) { 1667 mWifiStateMachine.setIpReachabilityDisconnectEnabled(false); 1668 } 1669 } 1670 pw.println("IPREACH_DISCONNECT state is " 1671 + mWifiStateMachine.getIpReachabilityDisconnectEnabled()); 1672 return; 1673 } else { 1674 pw.println("Wi-Fi is " + mWifiStateMachine.syncGetWifiStateByName()); 1675 pw.println("Stay-awake conditions: " + 1676 Settings.Global.getInt(mContext.getContentResolver(), 1677 Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0)); 1678 pw.println("mInIdleMode " + mInIdleMode); 1679 pw.println("mScanPending " + mScanPending); 1680 mWifiController.dump(fd, pw, args); 1681 mSettingsStore.dump(fd, pw, args); 1682 mTrafficPoller.dump(fd, pw, args); 1683 pw.println(); 1684 pw.println("Locks held:"); 1685 mWifiLockManager.dump(pw); 1686 pw.println(); 1687 mWifiMulticastLockManager.dump(pw); 1688 pw.println(); 1689 mWifiStateMachine.dump(fd, pw, args); 1690 pw.println(); 1691 mWifiStateMachine.updateWifiMetrics(); 1692 mWifiMetrics.dump(fd, pw, args); 1693 pw.println(); 1694 mWifiBackupRestore.dump(fd, pw, args); 1695 pw.println(); 1696 } 1697 } 1698 1699 @Override 1700 public boolean acquireWifiLock(IBinder binder, int lockMode, String tag, WorkSource ws) { 1701 mLog.trace("acquireWifiLock uid=% lockMode=%") 1702 .c(Binder.getCallingUid()) 1703 .c(lockMode).flush(); 1704 if (mWifiLockManager.acquireWifiLock(lockMode, tag, binder, ws)) { 1705 mWifiController.sendMessage(CMD_LOCKS_CHANGED); 1706 return true; 1707 } 1708 return false; 1709 } 1710 1711 @Override 1712 public void updateWifiLockWorkSource(IBinder binder, WorkSource ws) { 1713 mLog.trace("updateWifiLockWorkSource uid=%").c(Binder.getCallingUid()).flush(); 1714 mWifiLockManager.updateWifiLockWorkSource(binder, ws); 1715 } 1716 1717 @Override 1718 public boolean releaseWifiLock(IBinder binder) { 1719 mLog.trace("releaseWifiLock uid=%").c(Binder.getCallingUid()).flush(); 1720 if (mWifiLockManager.releaseWifiLock(binder)) { 1721 mWifiController.sendMessage(CMD_LOCKS_CHANGED); 1722 return true; 1723 } 1724 return false; 1725 } 1726 1727 @Override 1728 public void initializeMulticastFiltering() { 1729 enforceMulticastChangePermission(); 1730 mLog.trace("initializeMulticastFiltering uid=%").c(Binder.getCallingUid()).flush(); 1731 mWifiMulticastLockManager.initializeFiltering(); 1732 } 1733 1734 @Override 1735 public void acquireMulticastLock(IBinder binder, String tag) { 1736 enforceMulticastChangePermission(); 1737 mLog.trace("acquireMulticastLock uid=%").c(Binder.getCallingUid()).flush(); 1738 mWifiMulticastLockManager.acquireLock(binder, tag); 1739 } 1740 1741 @Override 1742 public void releaseMulticastLock() { 1743 enforceMulticastChangePermission(); 1744 mLog.trace("releaseMulticastLock uid=%").c(Binder.getCallingUid()).flush(); 1745 mWifiMulticastLockManager.releaseLock(); 1746 } 1747 1748 @Override 1749 public boolean isMulticastEnabled() { 1750 enforceAccessPermission(); 1751 mLog.trace("isMulticastEnabled uid=%").c(Binder.getCallingUid()).flush(); 1752 return mWifiMulticastLockManager.isMulticastEnabled(); 1753 } 1754 1755 @Override 1756 public void enableVerboseLogging(int verbose) { 1757 enforceAccessPermission(); 1758 mLog.trace("enableVerboseLogging uid=% verbose=%") 1759 .c(Binder.getCallingUid()) 1760 .c(verbose).flush(); 1761 mFacade.setIntegerSetting( 1762 mContext, Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED, verbose); 1763 enableVerboseLoggingInternal(verbose); 1764 } 1765 1766 void enableVerboseLoggingInternal(int verbose) { 1767 mWifiStateMachine.enableVerboseLogging(verbose); 1768 mWifiLockManager.enableVerboseLogging(verbose); 1769 mWifiMulticastLockManager.enableVerboseLogging(verbose); 1770 mWifiInjector.getWifiLastResortWatchdog().enableVerboseLogging(verbose); 1771 mWifiInjector.getWifiBackupRestore().enableVerboseLogging(verbose); 1772 LogcatLog.enableVerboseLogging(verbose); 1773 } 1774 1775 @Override 1776 public int getVerboseLoggingLevel() { 1777 enforceAccessPermission(); 1778 mLog.trace("getVerboseLoggingLevel uid=%").c(Binder.getCallingUid()).flush(); 1779 return mFacade.getIntegerSetting( 1780 mContext, Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED, 0); 1781 } 1782 1783 @Override 1784 public void enableAggressiveHandover(int enabled) { 1785 enforceAccessPermission(); 1786 mLog.trace("enableAggressiveHandover uid=% enabled=%") 1787 .c(Binder.getCallingUid()) 1788 .c(enabled) 1789 .flush(); 1790 mWifiStateMachine.enableAggressiveHandover(enabled); 1791 } 1792 1793 @Override 1794 public int getAggressiveHandover() { 1795 enforceAccessPermission(); 1796 mLog.trace("getAggressiveHandover uid=%").c(Binder.getCallingUid()).flush(); 1797 return mWifiStateMachine.getAggressiveHandover(); 1798 } 1799 1800 @Override 1801 public void setAllowScansWithTraffic(int enabled) { 1802 enforceAccessPermission(); 1803 mLog.trace("setAllowScansWithTraffic uid=% enabled=%") 1804 .c(Binder.getCallingUid()) 1805 .c(enabled).flush(); 1806 mWifiStateMachine.setAllowScansWithTraffic(enabled); 1807 } 1808 1809 @Override 1810 public int getAllowScansWithTraffic() { 1811 enforceAccessPermission(); 1812 mLog.trace("getAllowScansWithTraffic uid=%").c(Binder.getCallingUid()).flush(); 1813 return mWifiStateMachine.getAllowScansWithTraffic(); 1814 } 1815 1816 @Override 1817 public boolean setEnableAutoJoinWhenAssociated(boolean enabled) { 1818 enforceChangePermission(); 1819 mLog.trace("setEnableAutoJoinWhenAssociated uid=% enabled=%") 1820 .c(Binder.getCallingUid()) 1821 .c(enabled).flush(); 1822 return mWifiStateMachine.setEnableAutoJoinWhenAssociated(enabled); 1823 } 1824 1825 @Override 1826 public boolean getEnableAutoJoinWhenAssociated() { 1827 enforceAccessPermission(); 1828 mLog.trace("getEnableAutoJoinWhenAssociated uid=%").c(Binder.getCallingUid()).flush(); 1829 return mWifiStateMachine.getEnableAutoJoinWhenAssociated(); 1830 } 1831 1832 /* Return the Wifi Connection statistics object */ 1833 @Override 1834 public WifiConnectionStatistics getConnectionStatistics() { 1835 enforceAccessPermission(); 1836 enforceReadCredentialPermission(); 1837 mLog.trace("getConnectionStatistics uid=%").c(Binder.getCallingUid()).flush(); 1838 if (mWifiStateMachineChannel != null) { 1839 return mWifiStateMachine.syncGetConnectionStatistics(mWifiStateMachineChannel); 1840 } else { 1841 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 1842 return null; 1843 } 1844 } 1845 1846 @Override 1847 public void factoryReset() { 1848 enforceConnectivityInternalPermission(); 1849 mLog.trace("factoryReset uid=%").c(Binder.getCallingUid()).flush(); 1850 if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) { 1851 return; 1852 } 1853 1854 if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING)) { 1855 // Turn mobile hotspot off 1856 setWifiApEnabled(null, false); 1857 } 1858 1859 if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_WIFI)) { 1860 // Enable wifi 1861 try { 1862 setWifiEnabled(mContext.getOpPackageName(), true); 1863 } catch (RemoteException e) { 1864 /* ignore - local call */ 1865 } 1866 // Delete all Wifi SSIDs 1867 if (mWifiStateMachineChannel != null) { 1868 List<WifiConfiguration> networks = mWifiStateMachine.syncGetConfiguredNetworks( 1869 Binder.getCallingUid(), mWifiStateMachineChannel); 1870 if (networks != null) { 1871 for (WifiConfiguration config : networks) { 1872 removeNetwork(config.networkId); 1873 } 1874 saveConfiguration(); 1875 } 1876 } 1877 } 1878 } 1879 1880 /* private methods */ 1881 static boolean logAndReturnFalse(String s) { 1882 Log.d(TAG, s); 1883 return false; 1884 } 1885 1886 public static boolean isValid(WifiConfiguration config) { 1887 String validity = checkValidity(config); 1888 return validity == null || logAndReturnFalse(validity); 1889 } 1890 1891 public static boolean isValidPasspoint(WifiConfiguration config) { 1892 String validity = checkPasspointValidity(config); 1893 return validity == null || logAndReturnFalse(validity); 1894 } 1895 1896 public static String checkValidity(WifiConfiguration config) { 1897 if (config.allowedKeyManagement == null) 1898 return "allowed kmgmt"; 1899 1900 if (config.allowedKeyManagement.cardinality() > 1) { 1901 if (config.allowedKeyManagement.cardinality() != 2) { 1902 return "cardinality != 2"; 1903 } 1904 if (!config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP)) { 1905 return "not WPA_EAP"; 1906 } 1907 if ((!config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X)) 1908 && (!config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK))) { 1909 return "not PSK or 8021X"; 1910 } 1911 } 1912 if (config.getIpAssignment() == IpConfiguration.IpAssignment.STATIC) { 1913 StaticIpConfiguration staticIpConf = config.getStaticIpConfiguration(); 1914 if (staticIpConf == null) { 1915 return "null StaticIpConfiguration"; 1916 } 1917 if (staticIpConf.ipAddress == null) { 1918 return "null static ip Address"; 1919 } 1920 } 1921 return null; 1922 } 1923 1924 public static String checkPasspointValidity(WifiConfiguration config) { 1925 if (!TextUtils.isEmpty(config.FQDN)) { 1926 /* this is passpoint configuration; it must not have an SSID */ 1927 if (!TextUtils.isEmpty(config.SSID)) { 1928 return "SSID not expected for Passpoint: '" + config.SSID + 1929 "' FQDN " + toHexString(config.FQDN); 1930 } 1931 /* this is passpoint configuration; it must have a providerFriendlyName */ 1932 if (TextUtils.isEmpty(config.providerFriendlyName)) { 1933 return "no provider friendly name"; 1934 } 1935 WifiEnterpriseConfig enterpriseConfig = config.enterpriseConfig; 1936 /* this is passpoint configuration; it must have enterprise config */ 1937 if (enterpriseConfig == null 1938 || enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.NONE ) { 1939 return "no enterprise config"; 1940 } 1941 if ((enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TLS || 1942 enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TTLS || 1943 enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.PEAP) && 1944 enterpriseConfig.getCaCertificate() == null) { 1945 return "no CA certificate"; 1946 } 1947 } 1948 return null; 1949 } 1950 1951 @Override 1952 public Network getCurrentNetwork() { 1953 enforceAccessPermission(); 1954 mLog.trace("getCurrentNetwork uid=%").c(Binder.getCallingUid()).flush(); 1955 return mWifiStateMachine.getCurrentNetwork(); 1956 } 1957 1958 public static String toHexString(String s) { 1959 if (s == null) { 1960 return "null"; 1961 } 1962 StringBuilder sb = new StringBuilder(); 1963 sb.append('\'').append(s).append('\''); 1964 for (int n = 0; n < s.length(); n++) { 1965 sb.append(String.format(" %02x", s.charAt(n) & 0xffff)); 1966 } 1967 return sb.toString(); 1968 } 1969 1970 public void hideCertFromUnaffiliatedUsers(String alias) { 1971 mCertManager.hideCertFromUnaffiliatedUsers(alias); 1972 } 1973 1974 public String[] listClientCertsForCurrentUser() { 1975 return mCertManager.listClientCertsForCurrentUser(); 1976 } 1977 1978 /** 1979 * Enable/disable WifiConnectivityManager at runtime 1980 * 1981 * @param enabled true-enable; false-disable 1982 */ 1983 @Override 1984 public void enableWifiConnectivityManager(boolean enabled) { 1985 enforceConnectivityInternalPermission(); 1986 mLog.trace("enableWifiConnectivityManager uid=% enabled=%") 1987 .c(Binder.getCallingUid()) 1988 .c(enabled).flush(); 1989 mWifiStateMachine.enableWifiConnectivityManager(enabled); 1990 } 1991 1992 /** 1993 * Retrieve the data to be backed to save the current state. 1994 * 1995 * @return Raw byte stream of the data to be backed up. 1996 */ 1997 @Override 1998 public byte[] retrieveBackupData() { 1999 enforceReadCredentialPermission(); 2000 enforceAccessPermission(); 2001 mLog.trace("retrieveBackupData uid=%").c(Binder.getCallingUid()).flush(); 2002 if (mWifiStateMachineChannel == null) { 2003 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 2004 return null; 2005 } 2006 2007 Slog.d(TAG, "Retrieving backup data"); 2008 List<WifiConfiguration> wifiConfigurations = 2009 mWifiStateMachine.syncGetPrivilegedConfiguredNetwork(mWifiStateMachineChannel); 2010 byte[] backupData = 2011 mWifiBackupRestore.retrieveBackupDataFromConfigurations(wifiConfigurations); 2012 Slog.d(TAG, "Retrieved backup data"); 2013 return backupData; 2014 } 2015 2016 /** 2017 * Helper method to restore networks retrieved from backup data. 2018 * 2019 * @param configurations list of WifiConfiguration objects parsed from the backup data. 2020 */ 2021 private void restoreNetworks(List<WifiConfiguration> configurations) { 2022 if (configurations == null) { 2023 Slog.e(TAG, "Backup data parse failed"); 2024 return; 2025 } 2026 for (WifiConfiguration configuration : configurations) { 2027 int networkId = mWifiStateMachine.syncAddOrUpdateNetwork( 2028 mWifiStateMachineChannel, configuration); 2029 if (networkId == WifiConfiguration.INVALID_NETWORK_ID) { 2030 Slog.e(TAG, "Restore network failed: " + configuration.configKey()); 2031 continue; 2032 } 2033 // Enable all networks restored. 2034 mWifiStateMachine.syncEnableNetwork(mWifiStateMachineChannel, networkId, false); 2035 } 2036 } 2037 2038 /** 2039 * Restore state from the backed up data. 2040 * 2041 * @param data Raw byte stream of the backed up data. 2042 */ 2043 @Override 2044 public void restoreBackupData(byte[] data) { 2045 enforceChangePermission(); 2046 mLog.trace("restoreBackupData uid=%").c(Binder.getCallingUid()).flush(); 2047 if (mWifiStateMachineChannel == null) { 2048 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 2049 return; 2050 } 2051 2052 Slog.d(TAG, "Restoring backup data"); 2053 List<WifiConfiguration> wifiConfigurations = 2054 mWifiBackupRestore.retrieveConfigurationsFromBackupData(data); 2055 restoreNetworks(wifiConfigurations); 2056 Slog.d(TAG, "Restored backup data"); 2057 } 2058 2059 /** 2060 * Restore state from the older supplicant back up data. 2061 * The old backup data was essentially a backup of wpa_supplicant.conf & ipconfig.txt file. 2062 * 2063 * @param supplicantData Raw byte stream of wpa_supplicant.conf 2064 * @param ipConfigData Raw byte stream of ipconfig.txt 2065 */ 2066 public void restoreSupplicantBackupData(byte[] supplicantData, byte[] ipConfigData) { 2067 enforceChangePermission(); 2068 mLog.trace("restoreSupplicantBackupData uid=%").c(Binder.getCallingUid()).flush(); 2069 if (mWifiStateMachineChannel == null) { 2070 Slog.e(TAG, "mWifiStateMachineChannel is not initialized"); 2071 return; 2072 } 2073 2074 Slog.d(TAG, "Restoring supplicant backup data"); 2075 List<WifiConfiguration> wifiConfigurations = 2076 mWifiBackupRestore.retrieveConfigurationsFromSupplicantBackupData( 2077 supplicantData, ipConfigData); 2078 restoreNetworks(wifiConfigurations); 2079 Slog.d(TAG, "Restored supplicant backup data"); 2080 } 2081} 2082