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