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