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