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