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