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