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