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