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