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