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