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