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