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