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