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