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