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