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