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