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