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