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