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