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 17 package com.android.server.wifi; 18 19 import static android.app.AppOpsManager.MODE_ALLOWED; 20 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 21 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_GENERIC; 22 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_NO_CHANNEL; 23 import static android.net.wifi.WifiManager.SAP_START_FAILURE_NO_CHANNEL; 24 import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED; 25 import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING; 26 import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED; 27 import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING; 28 import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED; 29 30 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_LOCAL_ONLY; 31 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_LONG_LIVED; 32 import static com.android.server.wifi.ClientModeImpl.RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED; 33 import static com.android.server.wifi.ClientModeImpl.RESET_SIM_REASON_SIM_INSERTED; 34 import static com.android.server.wifi.ClientModeImpl.RESET_SIM_REASON_SIM_REMOVED; 35 import static com.android.server.wifi.SelfRecovery.REASON_API_CALL; 36 import static com.android.server.wifi.WifiConfigurationUtil.addSecurityTypeToNetworkId; 37 import static com.android.server.wifi.WifiConfigurationUtil.convertWifiInfoSecurityTypeToWifiConfiguration; 38 import static com.android.server.wifi.WifiConfigurationUtil.removeSecurityTypeFromNetworkId; 39 import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_VERBOSE_LOGGING_ENABLED; 40 41 import android.Manifest; 42 import android.annotation.CheckResult; 43 import android.annotation.NonNull; 44 import android.annotation.Nullable; 45 import android.app.AppOpsManager; 46 import android.bluetooth.BluetoothAdapter; 47 import android.content.BroadcastReceiver; 48 import android.content.ComponentName; 49 import android.content.Context; 50 import android.content.Intent; 51 import android.content.IntentFilter; 52 import android.content.pm.ApplicationInfo; 53 import android.content.pm.PackageInfo; 54 import android.content.pm.PackageManager; 55 import android.content.pm.ResolveInfo; 56 import android.net.DhcpInfo; 57 import android.net.DhcpResultsParcelable; 58 import android.net.InetAddresses; 59 import android.net.Network; 60 import android.net.NetworkCapabilities; 61 import android.net.NetworkStack; 62 import android.net.Uri; 63 import android.net.ip.IpClientUtil; 64 import android.net.wifi.CoexUnsafeChannel; 65 import android.net.wifi.IActionListener; 66 import android.net.wifi.ICoexCallback; 67 import android.net.wifi.IDppCallback; 68 import android.net.wifi.ILocalOnlyHotspotCallback; 69 import android.net.wifi.INetworkRequestMatchCallback; 70 import android.net.wifi.IOnWifiActivityEnergyInfoListener; 71 import android.net.wifi.IOnWifiUsabilityStatsListener; 72 import android.net.wifi.IScanResultsCallback; 73 import android.net.wifi.ISoftApCallback; 74 import android.net.wifi.ISubsystemRestartCallback; 75 import android.net.wifi.ISuggestionConnectionStatusListener; 76 import android.net.wifi.ISuggestionUserApprovalStatusListener; 77 import android.net.wifi.ITrafficStateCallback; 78 import android.net.wifi.IWifiConnectedNetworkScorer; 79 import android.net.wifi.IWifiVerboseLoggingStatusChangedListener; 80 import android.net.wifi.ScanResult; 81 import android.net.wifi.SoftApCapability; 82 import android.net.wifi.SoftApConfiguration; 83 import android.net.wifi.SoftApInfo; 84 import android.net.wifi.WifiAnnotations.WifiStandard; 85 import android.net.wifi.WifiAvailableChannel; 86 import android.net.wifi.WifiClient; 87 import android.net.wifi.WifiConfiguration; 88 import android.net.wifi.WifiInfo; 89 import android.net.wifi.WifiManager; 90 import android.net.wifi.WifiManager.AddNetworkResult; 91 import android.net.wifi.WifiManager.CoexRestriction; 92 import android.net.wifi.WifiManager.DeviceMobilityState; 93 import android.net.wifi.WifiManager.LocalOnlyHotspotCallback; 94 import android.net.wifi.WifiManager.SapClientBlockedReason; 95 import android.net.wifi.WifiManager.SapStartFailure; 96 import android.net.wifi.WifiManager.SuggestionConnectionStatusListener; 97 import android.net.wifi.WifiManager.WifiApState; 98 import android.net.wifi.WifiNetworkSuggestion; 99 import android.net.wifi.WifiScanner; 100 import android.net.wifi.hotspot2.IProvisioningCallback; 101 import android.net.wifi.hotspot2.OsuProvider; 102 import android.net.wifi.hotspot2.PasspointConfiguration; 103 import android.os.AsyncTask; 104 import android.os.Binder; 105 import android.os.Build; 106 import android.os.Handler; 107 import android.os.HandlerExecutor; 108 import android.os.IBinder; 109 import android.os.Looper; 110 import android.os.ParcelFileDescriptor; 111 import android.os.PersistableBundle; 112 import android.os.PowerManager; 113 import android.os.Process; 114 import android.os.RemoteCallbackList; 115 import android.os.RemoteException; 116 import android.os.UserHandle; 117 import android.os.UserManager; 118 import android.os.WorkSource; 119 import android.os.connectivity.WifiActivityEnergyInfo; 120 import android.provider.Settings; 121 import android.telephony.CarrierConfigManager; 122 import android.telephony.PhoneStateListener; 123 import android.telephony.SubscriptionManager; 124 import android.telephony.TelephonyManager; 125 import android.text.TextUtils; 126 import android.util.Log; 127 128 import androidx.annotation.RequiresApi; 129 130 import com.android.internal.annotations.GuardedBy; 131 import com.android.internal.annotations.VisibleForTesting; 132 import com.android.modules.utils.ParceledListSlice; 133 import com.android.modules.utils.build.SdkLevel; 134 import com.android.net.module.util.Inet4AddressUtils; 135 import com.android.server.wifi.coex.CoexManager; 136 import com.android.server.wifi.hotspot2.PasspointManager; 137 import com.android.server.wifi.hotspot2.PasspointProvider; 138 import com.android.server.wifi.proto.nano.WifiMetricsProto.UserActionEvent; 139 import com.android.server.wifi.util.ActionListenerWrapper; 140 import com.android.server.wifi.util.ApConfigUtil; 141 import com.android.server.wifi.util.GeneralUtil.Mutable; 142 import com.android.server.wifi.util.LastCallerInfoManager; 143 import com.android.server.wifi.util.RssiUtil; 144 import com.android.server.wifi.util.ScanResultUtil; 145 import com.android.server.wifi.util.WifiPermissionsUtil; 146 import com.android.wifi.resources.R; 147 148 import java.io.BufferedReader; 149 import java.io.FileDescriptor; 150 import java.io.FileNotFoundException; 151 import java.io.FileReader; 152 import java.io.IOException; 153 import java.io.PrintWriter; 154 import java.net.Inet4Address; 155 import java.net.InetAddress; 156 import java.security.GeneralSecurityException; 157 import java.security.KeyStore; 158 import java.security.cert.CertPath; 159 import java.security.cert.CertPathValidator; 160 import java.security.cert.CertificateFactory; 161 import java.security.cert.PKIXParameters; 162 import java.security.cert.X509Certificate; 163 import java.util.ArrayList; 164 import java.util.Arrays; 165 import java.util.Collections; 166 import java.util.HashMap; 167 import java.util.List; 168 import java.util.Map; 169 import java.util.Objects; 170 import java.util.concurrent.CountDownLatch; 171 import java.util.concurrent.Executor; 172 import java.util.concurrent.TimeUnit; 173 174 /** 175 * WifiService handles remote WiFi operation requests by implementing 176 * the IWifiManager interface. 177 */ 178 public class WifiServiceImpl extends BaseWifiService { 179 private static final String TAG = "WifiService"; 180 private static final boolean VDBG = false; 181 182 /** Max wait time for posting blocking runnables */ 183 private static final int RUN_WITH_SCISSORS_TIMEOUT_MILLIS = 4000; 184 @VisibleForTesting 185 static final int AUTO_DISABLE_SHOW_KEY_COUNTDOWN_MILLIS = 24 * 60 * 60 * 1000; 186 187 private final ActiveModeWarden mActiveModeWarden; 188 private final ScanRequestProxy mScanRequestProxy; 189 190 private final Context mContext; 191 private final FrameworkFacade mFacade; 192 private final Clock mClock; 193 194 private final PowerManager mPowerManager; 195 private final AppOpsManager mAppOps; 196 private final UserManager mUserManager; 197 private final WifiCountryCode mCountryCode; 198 199 /** Polls traffic stats and notifies clients */ 200 private final WifiTrafficPoller mWifiTrafficPoller; 201 /** Tracks the persisted states for wi-fi & airplane mode */ 202 private final WifiSettingsStore mSettingsStore; 203 /** Logs connection events and some general router and scan stats */ 204 private final WifiMetrics mWifiMetrics; 205 206 private final WifiInjector mWifiInjector; 207 /** Backup/Restore Module */ 208 private final WifiBackupRestore mWifiBackupRestore; 209 private final SoftApBackupRestore mSoftApBackupRestore; 210 private final CoexManager mCoexManager; 211 private final WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager; 212 private final WifiConfigManager mWifiConfigManager; 213 private final PasspointManager mPasspointManager; 214 private final WifiLog mLog; 215 private final WifiConnectivityManager mWifiConnectivityManager; 216 private final ConnectHelper mConnectHelper; 217 private final WifiGlobals mWifiGlobals; 218 private final WifiCarrierInfoManager mWifiCarrierInfoManager; 219 private @WifiManager.VerboseLoggingLevel int mVerboseLoggingLevel = 220 WifiManager.VERBOSE_LOGGING_LEVEL_DISABLED; 221 private final RemoteCallbackList<IWifiVerboseLoggingStatusChangedListener> 222 mRegisteredWifiLoggingStatusListeners = new RemoteCallbackList<>(); 223 224 private final FrameworkFacade mFrameworkFacade; 225 226 private final WifiPermissionsUtil mWifiPermissionsUtil; 227 228 private final TetheredSoftApTracker mTetheredSoftApTracker; 229 230 private final LohsSoftApTracker mLohsSoftApTracker; 231 232 private final BuildProperties mBuildProperties; 233 234 private final DefaultClientModeManager mDefaultClientModeManager; 235 236 /** 237 * Callback for use with LocalOnlyHotspot to unregister requesting applications upon death. 238 */ 239 public final class LocalOnlyRequestorCallback 240 implements LocalOnlyHotspotRequestInfo.RequestingApplicationDeathCallback { 241 /** 242 * Called with requesting app has died. 243 */ 244 @Override onLocalOnlyHotspotRequestorDeath(LocalOnlyHotspotRequestInfo requestor)245 public void onLocalOnlyHotspotRequestorDeath(LocalOnlyHotspotRequestInfo requestor) { 246 mLog.trace("onLocalOnlyHotspotRequestorDeath pid=%") 247 .c(requestor.getPid()).flush(); 248 mLohsSoftApTracker.stopByRequest(requestor); 249 } 250 } 251 252 /** 253 * Listen for phone call state events to get active data subcription id. 254 */ 255 private class WifiPhoneStateListener extends PhoneStateListener { WifiPhoneStateListener(Looper looper)256 WifiPhoneStateListener(Looper looper) { 257 super(new HandlerExecutor(new Handler(looper))); 258 } 259 260 @Override onActiveDataSubscriptionIdChanged(int subId)261 public void onActiveDataSubscriptionIdChanged(int subId) { 262 // post operation to handler thread 263 mWifiThreadRunner.post(() -> { 264 Log.d(TAG, "OBSERVED active data subscription change, subId: " + subId); 265 mTetheredSoftApTracker.updateSoftApCapabilityWhenCarrierConfigChanged(subId); 266 mActiveModeWarden.updateSoftApCapability( 267 mTetheredSoftApTracker.getSoftApCapability()); 268 }); 269 } 270 } 271 272 private final WifiLockManager mWifiLockManager; 273 private final WifiMulticastLockManager mWifiMulticastLockManager; 274 private final DppManager mDppManager; 275 private final WifiApConfigStore mWifiApConfigStore; 276 private final WifiThreadRunner mWifiThreadRunner; 277 private final MemoryStoreImpl mMemoryStoreImpl; 278 private final WifiScoreCard mWifiScoreCard; 279 private final WifiHealthMonitor mWifiHealthMonitor; 280 private final WifiDataStall mWifiDataStall; 281 private final WifiNative mWifiNative; 282 private final SimRequiredNotifier mSimRequiredNotifier; 283 private final MakeBeforeBreakManager mMakeBeforeBreakManager; 284 private final LastCallerInfoManager mLastCallerInfoManager; 285 286 /** 287 * The wrapper of SoftApCallback is used in WifiService internally. 288 * see: {@code WifiManager.SoftApCallback} 289 */ 290 public interface SoftApCallbackInternal { 291 /** 292 * see: {@code WifiManager.SoftApCallback#onStateChanged(int, int)} 293 */ onStateChanged(@ifiApState int state, @SapStartFailure int failureReason)294 default void onStateChanged(@WifiApState int state, @SapStartFailure int failureReason) {} 295 296 /** 297 * The callback which only is used in service internally and pass to WifiManager. 298 * It will base on the change to send corresponding callback as below: 299 * 1. onInfoChanged(SoftApInfo) 300 * 2. onInfoChanged(List<SoftApInfo>) 301 * 3. onConnectedClientsChanged(SoftApInfo, List<WifiClient>) 302 * 4. onConnectedClientsChanged(List<WifiClient>) 303 */ onConnectedClientsOrInfoChanged(Map<String, SoftApInfo> infos, Map<String, List<WifiClient>> clients, boolean isBridged)304 default void onConnectedClientsOrInfoChanged(Map<String, SoftApInfo> infos, 305 Map<String, List<WifiClient>> clients, boolean isBridged) {} 306 307 /** 308 * see: {@code WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)} 309 */ onCapabilityChanged(@onNull SoftApCapability softApCapability)310 default void onCapabilityChanged(@NonNull SoftApCapability softApCapability) {} 311 312 /** 313 * see: {@code WifiManager.SoftApCallback#onBlockedClientConnecting(WifiClient, int)} 314 */ onBlockedClientConnecting(@onNull WifiClient client, @SapClientBlockedReason int blockedReason)315 default void onBlockedClientConnecting(@NonNull WifiClient client, 316 @SapClientBlockedReason int blockedReason) {} 317 } 318 319 WifiServiceImpl(Context context, WifiInjector wifiInjector)320 public WifiServiceImpl(Context context, WifiInjector wifiInjector) { 321 mContext = context; 322 mWifiInjector = wifiInjector; 323 mClock = wifiInjector.getClock(); 324 325 mFacade = mWifiInjector.getFrameworkFacade(); 326 mWifiMetrics = mWifiInjector.getWifiMetrics(); 327 mWifiTrafficPoller = mWifiInjector.getWifiTrafficPoller(); 328 mUserManager = mWifiInjector.getUserManager(); 329 mCountryCode = mWifiInjector.getWifiCountryCode(); 330 mActiveModeWarden = mWifiInjector.getActiveModeWarden(); 331 mScanRequestProxy = mWifiInjector.getScanRequestProxy(); 332 mSettingsStore = mWifiInjector.getWifiSettingsStore(); 333 mPowerManager = mContext.getSystemService(PowerManager.class); 334 mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 335 mWifiLockManager = mWifiInjector.getWifiLockManager(); 336 mWifiMulticastLockManager = mWifiInjector.getWifiMulticastLockManager(); 337 mWifiBackupRestore = mWifiInjector.getWifiBackupRestore(); 338 mSoftApBackupRestore = mWifiInjector.getSoftApBackupRestore(); 339 mWifiApConfigStore = mWifiInjector.getWifiApConfigStore(); 340 mWifiPermissionsUtil = mWifiInjector.getWifiPermissionsUtil(); 341 mLog = mWifiInjector.makeLog(TAG); 342 mFrameworkFacade = wifiInjector.getFrameworkFacade(); 343 mTetheredSoftApTracker = new TetheredSoftApTracker(); 344 mActiveModeWarden.registerSoftApCallback(mTetheredSoftApTracker); 345 mLohsSoftApTracker = new LohsSoftApTracker(); 346 mActiveModeWarden.registerLohsCallback(mLohsSoftApTracker); 347 mWifiNetworkSuggestionsManager = mWifiInjector.getWifiNetworkSuggestionsManager(); 348 mDppManager = mWifiInjector.getDppManager(); 349 mWifiThreadRunner = mWifiInjector.getWifiThreadRunner(); 350 mWifiConfigManager = mWifiInjector.getWifiConfigManager(); 351 mPasspointManager = mWifiInjector.getPasspointManager(); 352 mWifiScoreCard = mWifiInjector.getWifiScoreCard(); 353 mWifiHealthMonitor = wifiInjector.getWifiHealthMonitor(); 354 mMemoryStoreImpl = new MemoryStoreImpl(mContext, mWifiInjector, 355 mWifiScoreCard, mWifiHealthMonitor); 356 mWifiConnectivityManager = wifiInjector.getWifiConnectivityManager(); 357 mWifiDataStall = wifiInjector.getWifiDataStall(); 358 mWifiNative = wifiInjector.getWifiNative(); 359 mCoexManager = wifiInjector.getCoexManager(); 360 mConnectHelper = wifiInjector.getConnectHelper(); 361 mWifiGlobals = wifiInjector.getWifiGlobals(); 362 mSimRequiredNotifier = wifiInjector.getSimRequiredNotifier(); 363 mWifiCarrierInfoManager = wifiInjector.getWifiCarrierInfoManager(); 364 mMakeBeforeBreakManager = mWifiInjector.getMakeBeforeBreakManager(); 365 mLastCallerInfoManager = mWifiInjector.getLastCallerInfoManager(); 366 mBuildProperties = mWifiInjector.getBuildProperties(); 367 mDefaultClientModeManager = mWifiInjector.getDefaultClientModeManager(); 368 } 369 370 /** 371 * Check if we are ready to start wifi. 372 * 373 * First check if we will be restarting system services to decrypt the device. If the device is 374 * not encrypted, check if Wi-Fi needs to be enabled and start if needed 375 * 376 * This function is used only at boot time. 377 */ checkAndStartWifi()378 public void checkAndStartWifi() { 379 mWifiThreadRunner.post(() -> { 380 if (!mWifiConfigManager.loadFromStore()) { 381 Log.e(TAG, "Failed to load from config store"); 382 } 383 mWifiConfigManager.incrementNumRebootsSinceLastUse(); 384 // config store is read, check if verbose logging is enabled. 385 enableVerboseLoggingInternal( 386 mWifiInjector.getSettingsConfigStore().get(WIFI_VERBOSE_LOGGING_ENABLED) 387 ? 1 : 0); 388 // Check if wi-fi needs to be enabled 389 boolean wifiEnabled = mSettingsStore.isWifiToggleEnabled(); 390 Log.i(TAG, 391 "WifiService starting up with Wi-Fi " + (wifiEnabled ? "enabled" : "disabled")); 392 393 mWifiInjector.getWifiScanAlwaysAvailableSettingsCompatibility().initialize(); 394 mWifiInjector.getWifiNotificationManager().createNotificationChannels(); 395 mContext.registerReceiver( 396 new BroadcastReceiver() { 397 @Override 398 public void onReceive(Context context, Intent intent) { 399 int state = intent.getIntExtra(TelephonyManager.EXTRA_SIM_STATE, 400 TelephonyManager.SIM_STATE_UNKNOWN); 401 if (TelephonyManager.SIM_STATE_ABSENT == state) { 402 Log.d(TAG, "resetting networks because SIM was removed"); 403 resetCarrierNetworks(RESET_SIM_REASON_SIM_REMOVED); 404 } 405 } 406 }, 407 new IntentFilter(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED)); 408 409 mContext.registerReceiver( 410 new BroadcastReceiver() { 411 @Override 412 public void onReceive(Context context, Intent intent) { 413 int state = intent.getIntExtra(TelephonyManager.EXTRA_SIM_STATE, 414 TelephonyManager.SIM_STATE_UNKNOWN); 415 if (TelephonyManager.SIM_STATE_LOADED == state) { 416 Log.d(TAG, "resetting networks because SIM was loaded"); 417 resetCarrierNetworks(RESET_SIM_REASON_SIM_INSERTED); 418 } 419 } 420 }, 421 new IntentFilter(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED)); 422 423 mContext.registerReceiver( 424 new BroadcastReceiver() { 425 private int mLastSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 426 @Override 427 public void onReceive(Context context, Intent intent) { 428 final int subId = intent.getIntExtra("subscription", 429 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 430 if (subId != mLastSubId) { 431 Log.d(TAG, "resetting networks as default data SIM is changed"); 432 resetCarrierNetworks(RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED); 433 mLastSubId = subId; 434 mWifiThreadRunner.post(() -> { 435 mWifiDataStall.resetPhoneStateListener(); 436 }); 437 } 438 } 439 }, 440 new IntentFilter(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)); 441 442 mContext.registerReceiver( 443 new BroadcastReceiver() { 444 @Override 445 public void onReceive(Context context, Intent intent) { 446 String countryCode = intent.getStringExtra( 447 TelephonyManager.EXTRA_NETWORK_COUNTRY); 448 Log.d(TAG, "Country code changed to :" + countryCode); 449 mCountryCode.setTelephonyCountryCodeAndUpdate(countryCode); 450 }}, new IntentFilter(TelephonyManager.ACTION_NETWORK_COUNTRY_CHANGED)); 451 mContext.registerReceiver( 452 new BroadcastReceiver() { 453 @Override 454 public void onReceive(Context context, Intent intent) { 455 Log.d(TAG, "locale changed"); 456 resetNotificationManager(); 457 }}, new IntentFilter(Intent.ACTION_LOCALE_CHANGED)); 458 459 // Adding optimizations of only receiving broadcasts when wifi is enabled 460 // can result in race conditions when apps toggle wifi in the background 461 // without active user involvement. Always receive broadcasts. 462 registerForBroadcasts(); 463 mInIdleMode = mPowerManager.isDeviceIdleMode(); 464 465 mActiveModeWarden.start(); 466 registerForCarrierConfigChange(); 467 mWifiInjector.getAdaptiveConnectivityEnabledSettingObserver().initialize(); 468 }); 469 } 470 resetCarrierNetworks(@lientModeImpl.ResetSimReason int resetReason)471 private void resetCarrierNetworks(@ClientModeImpl.ResetSimReason int resetReason) { 472 mWifiThreadRunner.post(() -> { 473 Log.d(TAG, "resetting carrier networks since SIM was changed"); 474 if (resetReason == RESET_SIM_REASON_SIM_INSERTED 475 || resetReason == RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED) { 476 // clear all SIM related notifications since some action was taken to address 477 // "missing" SIM issue 478 mSimRequiredNotifier.dismissSimRequiredNotification(); 479 } 480 if (resetReason != RESET_SIM_REASON_SIM_INSERTED) { 481 mWifiConfigManager.resetSimNetworks(); 482 mWifiNetworkSuggestionsManager.resetSimNetworkSuggestions(); 483 mPasspointManager.resetSimPasspointNetwork(); 484 mWifiConfigManager.stopRestrictingAutoJoinToSubscriptionId(); 485 } 486 487 // do additional handling if we are current connected to a sim auth network 488 for (ClientModeManager cmm : mActiveModeWarden.getClientModeManagers()) { 489 cmm.resetSimAuthNetworks(resetReason); 490 } 491 mWifiNetworkSuggestionsManager.resetCarrierPrivilegedApps(); 492 if (resetReason == RESET_SIM_REASON_SIM_INSERTED) { 493 // clear the blocklists in case any SIM based network were disabled due to the SIM 494 // not being available. 495 mWifiConfigManager.enableTemporaryDisabledNetworks(); 496 mWifiConnectivityManager.forceConnectivityScan(ClientModeImpl.WIFI_WORK_SOURCE); 497 } else { 498 // Remove all ephemeral carrier networks keep subscriptionId update with SIM changes 499 mWifiConfigManager.removeEphemeralCarrierNetworks(); 500 } 501 }); 502 } 503 handleBootCompleted()504 public void handleBootCompleted() { 505 mWifiThreadRunner.post(() -> { 506 Log.d(TAG, "Handle boot completed"); 507 508 // Register for system broadcasts. 509 IntentFilter intentFilter = new IntentFilter(); 510 intentFilter.addAction(Intent.ACTION_USER_REMOVED); 511 intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); 512 intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); 513 intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); 514 intentFilter.addAction(Intent.ACTION_SHUTDOWN); 515 mContext.registerReceiver(new BroadcastReceiver() { 516 @Override 517 public void onReceive(Context context, Intent intent) { 518 String action = intent.getAction(); 519 if (action.equals(Intent.ACTION_USER_REMOVED)) { 520 UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER); 521 if (userHandle == null) { 522 Log.e(TAG, "User removed broadcast received with no user handle"); 523 return; 524 } 525 mWifiThreadRunner.post(() -> mWifiConfigManager 526 .removeNetworksForUser(userHandle.getIdentifier())); 527 } else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) { 528 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, 529 BluetoothAdapter.STATE_DISCONNECTED); 530 boolean isConnected = state != BluetoothAdapter.STATE_DISCONNECTED; 531 mWifiGlobals.setBluetoothConnected(isConnected); 532 for (ClientModeManager cmm : mActiveModeWarden.getClientModeManagers()) { 533 cmm.onBluetoothConnectionStateChanged(); 534 } 535 } else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { 536 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 537 BluetoothAdapter.STATE_OFF); 538 boolean isEnabled = state != BluetoothAdapter.STATE_OFF; 539 mWifiGlobals.setBluetoothEnabled(isEnabled); 540 for (ClientModeManager cmm : mActiveModeWarden.getClientModeManagers()) { 541 cmm.onBluetoothConnectionStateChanged(); 542 } 543 } else if (action.equals(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED)) { 544 handleIdleModeChanged(); 545 } else if (action.equals(Intent.ACTION_SHUTDOWN)) { 546 handleShutDown(); 547 } 548 } 549 }, intentFilter); 550 mMemoryStoreImpl.start(); 551 mPasspointManager.initializeProvisioner( 552 mWifiInjector.getPasspointProvisionerHandlerThread().getLooper()); 553 mWifiInjector.getWifiNetworkFactory().register(); 554 mWifiInjector.getUntrustedWifiNetworkFactory().register(); 555 mWifiInjector.getOemWifiNetworkFactory().register(); 556 mWifiInjector.getWifiP2pConnection().handleBootCompleted(); 557 // Start to listen country code change. 558 mCountryCode.registerListener(new CountryCodeListenerProxy()); 559 mTetheredSoftApTracker.handleBootCompleted(); 560 mWifiInjector.getSarManager().handleBootCompleted(); 561 }); 562 } 563 handleUserSwitch(int userId)564 public void handleUserSwitch(int userId) { 565 Log.d(TAG, "Handle user switch " + userId); 566 567 mWifiThreadRunner.post(() -> { 568 mWifiConfigManager.handleUserSwitch(userId); 569 resetNotificationManager(); 570 }); 571 } 572 handleUserUnlock(int userId)573 public void handleUserUnlock(int userId) { 574 Log.d(TAG, "Handle user unlock " + userId); 575 mWifiThreadRunner.post(() -> mWifiConfigManager.handleUserUnlock(userId)); 576 } 577 handleUserStop(int userId)578 public void handleUserStop(int userId) { 579 Log.d(TAG, "Handle user stop " + userId); 580 mWifiThreadRunner.post(() -> mWifiConfigManager.handleUserStop(userId)); 581 } 582 583 /** 584 * See {@link android.net.wifi.WifiManager#startScan} 585 * 586 * @param packageName Package name of the app that requests wifi scan. 587 * @param featureId The feature in the package 588 */ 589 @Override startScan(String packageName, String featureId)590 public boolean startScan(String packageName, String featureId) { 591 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 592 return false; 593 } 594 595 int callingUid = Binder.getCallingUid(); 596 long ident = Binder.clearCallingIdentity(); 597 mLog.info("startScan uid=%").c(callingUid).flush(); 598 synchronized (this) { 599 if (mInIdleMode) { 600 // Need to send an immediate scan result broadcast in case the 601 // caller is waiting for a result .. 602 603 // TODO: investigate if the logic to cancel scans when idle can move to 604 // WifiScanningServiceImpl. This will 1 - clean up WifiServiceImpl and 2 - 605 // avoid plumbing an awkward path to report a cancelled/failed scan. This will 606 // be sent directly until b/31398592 is fixed. 607 sendFailedScanBroadcast(); 608 mScanPending = true; 609 return false; 610 } 611 } 612 try { 613 mWifiPermissionsUtil.enforceCanAccessScanResults(packageName, featureId, callingUid, 614 null); 615 Boolean scanSuccess = mWifiThreadRunner.call(() -> 616 mScanRequestProxy.startScan(callingUid, packageName), null); 617 if (scanSuccess == null) { 618 sendFailedScanBroadcast(); 619 return false; 620 } 621 if (!scanSuccess) { 622 Log.e(TAG, "Failed to start scan"); 623 return false; 624 } 625 } catch (SecurityException e) { 626 Log.w(TAG, "Permission violation - startScan not allowed for" 627 + " uid=" + callingUid + ", packageName=" + packageName + ", reason=" + e); 628 return false; 629 } finally { 630 Binder.restoreCallingIdentity(ident); 631 } 632 return true; 633 } 634 635 // Send a failed scan broadcast to indicate the current scan request failed. sendFailedScanBroadcast()636 private void sendFailedScanBroadcast() { 637 // clear calling identity to send broadcast 638 long callingIdentity = Binder.clearCallingIdentity(); 639 try { 640 Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); 641 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 642 intent.putExtra(WifiManager.EXTRA_RESULTS_UPDATED, false); 643 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 644 } finally { 645 // restore calling identity 646 Binder.restoreCallingIdentity(callingIdentity); 647 } 648 649 } 650 651 /** 652 * WPS support in Client mode is deprecated. Return null. 653 */ 654 @Override getCurrentNetworkWpsNfcConfigurationToken()655 public String getCurrentNetworkWpsNfcConfigurationToken() { 656 // while CLs are in flight, return null here, will be removed (b/72423090) 657 enforceNetworkStackPermission(); 658 if (isVerboseLoggingEnabled()) { 659 mLog.info("getCurrentNetworkWpsNfcConfigurationToken uid=%") 660 .c(Binder.getCallingUid()).flush(); 661 } 662 return null; 663 } 664 665 private boolean mInIdleMode; 666 private boolean mScanPending; 667 handleIdleModeChanged()668 private void handleIdleModeChanged() { 669 boolean doScan = false; 670 synchronized (this) { 671 boolean idle = mPowerManager.isDeviceIdleMode(); 672 if (mInIdleMode != idle) { 673 mInIdleMode = idle; 674 if (!idle) { 675 if (mScanPending) { 676 mScanPending = false; 677 doScan = true; 678 } 679 } 680 } 681 } 682 if (doScan) { 683 // Someone requested a scan while we were idle; do a full scan now. 684 // A security check of the caller's identity was made when the request arrived via 685 // Binder. Now we'll pass the current process's identity to startScan(). 686 startScan(mContext.getOpPackageName(), mContext.getAttributionTag()); 687 } 688 } 689 handleShutDown()690 private void handleShutDown() { 691 // Direct call to notify ActiveModeWarden as soon as possible with the assumption that 692 // notifyShuttingDown() doesn't have codes that may cause concurrentModificationException, 693 // e.g., access to a collection. 694 mActiveModeWarden.notifyShuttingDown(); 695 mWifiThreadRunner.post(()-> { 696 // There is no explicit disconnection event in clientModeImpl during shutdown. 697 // Call resetConnectionState() so that connection duration is calculated 698 // before memory store write triggered by mMemoryStoreImpl.stop(). 699 mWifiScoreCard.resetAllConnectionStates(); 700 mMemoryStoreImpl.stop(); 701 }); 702 } 703 checkNetworkSettingsPermission(int pid, int uid)704 private boolean checkNetworkSettingsPermission(int pid, int uid) { 705 return mContext.checkPermission(android.Manifest.permission.NETWORK_SETTINGS, pid, uid) 706 == PERMISSION_GRANTED; 707 } 708 checkNetworkSetupWizardPermission(int pid, int uid)709 private boolean checkNetworkSetupWizardPermission(int pid, int uid) { 710 return mContext.checkPermission(android.Manifest.permission.NETWORK_SETUP_WIZARD, pid, uid) 711 == PackageManager.PERMISSION_GRANTED; 712 } 713 checkMainlineNetworkStackPermission(int pid, int uid)714 private boolean checkMainlineNetworkStackPermission(int pid, int uid) { 715 return mContext.checkPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, pid, uid) 716 == PackageManager.PERMISSION_GRANTED; 717 } 718 checkNetworkStackPermission(int pid, int uid)719 private boolean checkNetworkStackPermission(int pid, int uid) { 720 return mContext.checkPermission(android.Manifest.permission.NETWORK_STACK, pid, uid) 721 == PackageManager.PERMISSION_GRANTED; 722 } 723 checkNetworkManagedProvisioningPermission(int pid, int uid)724 private boolean checkNetworkManagedProvisioningPermission(int pid, int uid) { 725 return mContext.checkPermission(android.Manifest.permission.NETWORK_MANAGED_PROVISIONING, 726 pid, uid) == PackageManager.PERMISSION_GRANTED; 727 } 728 729 /** 730 * Helper method to check if the entity initiating the binder call has any of the signature only 731 * permissions. 732 */ isPrivileged(int pid, int uid)733 private boolean isPrivileged(int pid, int uid) { 734 return checkNetworkSettingsPermission(pid, uid) 735 || checkNetworkSetupWizardPermission(pid, uid) 736 || checkNetworkStackPermission(pid, uid) 737 || checkNetworkManagedProvisioningPermission(pid, uid) 738 || isSignedWithPlatformKey(uid); 739 } 740 741 /** Whether the uid is signed with the same key as the platform. */ isSignedWithPlatformKey(int uid)742 private boolean isSignedWithPlatformKey(int uid) { 743 return mContext.getPackageManager().checkSignatures(uid, Process.SYSTEM_UID) 744 == PackageManager.SIGNATURE_MATCH; 745 } 746 747 /** 748 * Helper method to check if the entity initiating the binder call has setup wizard or settings 749 * permissions. 750 */ isSettingsOrSuw(int pid, int uid)751 private boolean isSettingsOrSuw(int pid, int uid) { 752 return checkNetworkSettingsPermission(pid, uid) 753 || checkNetworkSetupWizardPermission(pid, uid); 754 } 755 756 /** Helper method to check if the entity initiating the binder call is a DO/PO app. */ isDeviceOrProfileOwner(int uid, String packageName)757 private boolean isDeviceOrProfileOwner(int uid, String packageName) { 758 return mWifiPermissionsUtil.isDeviceOwner(uid, packageName) 759 || mWifiPermissionsUtil.isProfileOwner(uid, packageName); 760 } 761 enforceNetworkSettingsPermission()762 private void enforceNetworkSettingsPermission() { 763 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.NETWORK_SETTINGS, 764 "WifiService"); 765 } 766 checkAnyPermissionOf(String... permissions)767 private boolean checkAnyPermissionOf(String... permissions) { 768 for (String permission : permissions) { 769 if (mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED) { 770 return true; 771 } 772 } 773 return false; 774 } 775 enforceAnyPermissionOf(String... permissions)776 private void enforceAnyPermissionOf(String... permissions) { 777 if (!checkAnyPermissionOf(permissions)) { 778 throw new SecurityException("Requires one of the following permissions: " 779 + String.join(", ", permissions) + "."); 780 } 781 } 782 enforceNetworkStackPermission()783 private void enforceNetworkStackPermission() { 784 // TODO(b/142554155): Only check for MAINLINE_NETWORK_STACK permission 785 boolean granted = mContext.checkCallingOrSelfPermission( 786 android.Manifest.permission.NETWORK_STACK) 787 == PackageManager.PERMISSION_GRANTED; 788 if (granted) { 789 return; 790 } 791 mContext.enforceCallingOrSelfPermission( 792 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, "WifiService"); 793 } 794 enforceAccessPermission()795 private void enforceAccessPermission() { 796 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE, 797 "WifiService"); 798 } 799 enforceRestartWifiSubsystemPermission()800 private void enforceRestartWifiSubsystemPermission() { 801 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RESTART_WIFI_SUBSYSTEM, 802 "WifiService"); 803 } 804 805 /** 806 * Checks whether the caller can change the wifi state. 807 * Possible results: 808 * 1. Operation is allowed. No exception thrown, and AppOpsManager.MODE_ALLOWED returned. 809 * 2. Operation is not allowed, and caller must be told about this. SecurityException is thrown. 810 * 3. Operation is not allowed, and caller must not be told about this (i.e. must silently 811 * ignore the operation). No exception is thrown, and AppOpsManager.MODE_IGNORED returned. 812 */ 813 @CheckResult enforceChangePermission(String callingPackage)814 private int enforceChangePermission(String callingPackage) { 815 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); 816 if (checkNetworkSettingsPermission(Binder.getCallingPid(), Binder.getCallingUid())) { 817 return MODE_ALLOWED; 818 } 819 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE, 820 "WifiService"); 821 822 return mAppOps.noteOp( 823 AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Binder.getCallingUid(), callingPackage); 824 } 825 enforceReadCredentialPermission()826 private void enforceReadCredentialPermission() { 827 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.READ_WIFI_CREDENTIAL, 828 "WifiService"); 829 } 830 enforceMulticastChangePermission()831 private void enforceMulticastChangePermission() { 832 mContext.enforceCallingOrSelfPermission( 833 android.Manifest.permission.CHANGE_WIFI_MULTICAST_STATE, 834 "WifiService"); 835 } 836 enforceConnectivityInternalPermission()837 private void enforceConnectivityInternalPermission() { 838 mContext.enforceCallingOrSelfPermission( 839 android.Manifest.permission.CONNECTIVITY_INTERNAL, 840 "ConnectivityService"); 841 } 842 enforceLocationPermission(String pkgName, @Nullable String featureId, int uid)843 private void enforceLocationPermission(String pkgName, @Nullable String featureId, int uid) { 844 mWifiPermissionsUtil.enforceLocationPermission(pkgName, featureId, uid); 845 } 846 847 /** 848 * Helper method to check if the app is allowed to access public API's deprecated in 849 * {@link Build.VERSION_CODES#Q}. 850 * Note: Invoke mAppOps.checkPackage(uid, packageName) before to ensure correct package name. 851 */ isTargetSdkLessThanQOrPrivileged(String packageName, int pid, int uid)852 private boolean isTargetSdkLessThanQOrPrivileged(String packageName, int pid, int uid) { 853 return mWifiPermissionsUtil.isTargetSdkLessThan(packageName, Build.VERSION_CODES.Q, uid) 854 || isPrivileged(pid, uid) 855 || isDeviceOrProfileOwner(uid, packageName) 856 || mWifiPermissionsUtil.isSystem(packageName, uid) 857 // TODO(b/140540984): Remove this bypass. 858 || mWifiPermissionsUtil.checkSystemAlertWindowPermission(uid, packageName); 859 } 860 861 /** 862 * Helper method to check if the app is allowed to access public API's deprecated in 863 * {@link Build.VERSION_CODES#R}. 864 * Note: Invoke mAppOps.checkPackage(uid, packageName) before to ensure correct package name. 865 */ isTargetSdkLessThanROrPrivileged(String packageName, int pid, int uid)866 private boolean isTargetSdkLessThanROrPrivileged(String packageName, int pid, int uid) { 867 return mWifiPermissionsUtil.isTargetSdkLessThan(packageName, Build.VERSION_CODES.R, uid) 868 || isPrivileged(pid, uid) 869 || isDeviceOrProfileOwner(uid, packageName) 870 || mWifiPermissionsUtil.isSystem(packageName, uid); 871 } 872 873 /** 874 * Get the current primary ClientModeManager in a thread safe manner, but blocks on the main 875 * Wifi thread. 876 */ getPrimaryClientModeManagerBlockingThreadSafe()877 private ClientModeManager getPrimaryClientModeManagerBlockingThreadSafe() { 878 return mWifiThreadRunner.call( 879 () -> mActiveModeWarden.getPrimaryClientModeManager(), 880 mDefaultClientModeManager); 881 } 882 883 /** 884 * see {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)} 885 * @param enable {@code true} to enable, {@code false} to disable. 886 * @return {@code true} if the enable/disable operation was 887 * started or is already in the queue. 888 */ 889 @Override setWifiEnabled(String packageName, boolean enable)890 public synchronized boolean setWifiEnabled(String packageName, boolean enable) { 891 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 892 return false; 893 } 894 boolean isPrivileged = isPrivileged(Binder.getCallingPid(), Binder.getCallingUid()); 895 if (!isPrivileged && !isDeviceOrProfileOwner(Binder.getCallingUid(), packageName) 896 && !mWifiPermissionsUtil.isTargetSdkLessThan(packageName, Build.VERSION_CODES.Q, 897 Binder.getCallingUid()) 898 && !mWifiPermissionsUtil.isSystem(packageName, Binder.getCallingUid())) { 899 mLog.info("setWifiEnabled not allowed for uid=%") 900 .c(Binder.getCallingUid()).flush(); 901 return false; 902 } 903 // If Airplane mode is enabled, only privileged apps are allowed to toggle Wifi 904 if (mSettingsStore.isAirplaneModeOn() && !isPrivileged) { 905 mLog.err("setWifiEnabled in Airplane mode: only Settings can toggle wifi").flush(); 906 return false; 907 } 908 909 // If SoftAp is enabled, only privileged apps are allowed to toggle wifi 910 if (!isPrivileged && mTetheredSoftApTracker.getState() == WIFI_AP_STATE_ENABLED) { 911 mLog.err("setWifiEnabled with SoftAp enabled: only Settings can toggle wifi").flush(); 912 return false; 913 } 914 915 mLog.info("setWifiEnabled package=% uid=% enable=%").c(packageName) 916 .c(Binder.getCallingUid()).c(enable).flush(); 917 long ident = Binder.clearCallingIdentity(); 918 try { 919 if (!mSettingsStore.handleWifiToggled(enable)) { 920 // Nothing to do if wifi cannot be toggled 921 return true; 922 } 923 } finally { 924 Binder.restoreCallingIdentity(ident); 925 } 926 if (mWifiPermissionsUtil.checkNetworkSettingsPermission(Binder.getCallingUid())) { 927 if (enable) { 928 mWifiMetrics.logUserActionEvent(UserActionEvent.EVENT_TOGGLE_WIFI_ON); 929 } else { 930 WifiInfo wifiInfo = 931 getPrimaryClientModeManagerBlockingThreadSafe().syncRequestConnectionInfo(); 932 mWifiMetrics.logUserActionEvent(UserActionEvent.EVENT_TOGGLE_WIFI_OFF, 933 wifiInfo == null ? -1 : wifiInfo.getNetworkId()); 934 } 935 } 936 mWifiMetrics.incrementNumWifiToggles(isPrivileged, enable); 937 mActiveModeWarden.wifiToggled(new WorkSource(Binder.getCallingUid(), packageName)); 938 mLastCallerInfoManager.put(LastCallerInfoManager.WIFI_ENABLED, Process.myTid(), 939 Binder.getCallingUid(), Binder.getCallingPid(), packageName, enable); 940 return true; 941 } 942 943 @RequiresApi(Build.VERSION_CODES.S) 944 @Override registerSubsystemRestartCallback(ISubsystemRestartCallback callback)945 public void registerSubsystemRestartCallback(ISubsystemRestartCallback callback) { 946 if (!SdkLevel.isAtLeastS()) { 947 throw new UnsupportedOperationException(); 948 } 949 enforceAccessPermission(); 950 if (isVerboseLoggingEnabled()) { 951 mLog.info("registerSubsystemRestartCallback uid=%").c(Binder.getCallingUid()).flush(); 952 } 953 954 mWifiThreadRunner.post(() -> { 955 if (!mActiveModeWarden.registerSubsystemRestartCallback(callback)) { 956 Log.e(TAG, "registerSubsystemRestartCallback: Failed to register callback"); 957 } 958 }); 959 } 960 961 @RequiresApi(Build.VERSION_CODES.S) 962 @Override unregisterSubsystemRestartCallback(ISubsystemRestartCallback callback)963 public void unregisterSubsystemRestartCallback(ISubsystemRestartCallback callback) { 964 if (!SdkLevel.isAtLeastS()) { 965 throw new UnsupportedOperationException(); 966 } 967 enforceAccessPermission(); 968 if (isVerboseLoggingEnabled()) { 969 mLog.info("registerSubsystemRestartCallback uid=%").c(Binder.getCallingUid()).flush(); 970 } 971 mWifiThreadRunner.post(() -> { 972 if (!mActiveModeWarden.unregisterSubsystemRestartCallback(callback)) { 973 Log.e(TAG, "unregisterSubsystemRestartCallback: Failed to register callback"); 974 } 975 }); 976 } 977 978 @RequiresApi(Build.VERSION_CODES.S) 979 @Override restartWifiSubsystem()980 public void restartWifiSubsystem() { 981 if (!SdkLevel.isAtLeastS()) { 982 throw new UnsupportedOperationException(); 983 } 984 enforceRestartWifiSubsystemPermission(); 985 if (isVerboseLoggingEnabled()) { 986 mLog.info("restartWifiSubsystem uid=%").c(Binder.getCallingUid()).flush(); 987 } 988 mWifiThreadRunner.post(() -> { 989 WifiInfo wifiInfo = 990 mActiveModeWarden.getPrimaryClientModeManager().syncRequestConnectionInfo(); 991 mWifiMetrics.logUserActionEvent(UserActionEvent.EVENT_RESTART_WIFI_SUB_SYSTEM, 992 wifiInfo == null ? -1 : wifiInfo.getNetworkId()); 993 mWifiInjector.getSelfRecovery().trigger(REASON_API_CALL); 994 }); 995 } 996 997 /** 998 * see {@link WifiManager#getWifiState()} 999 * @return One of {@link WifiManager#WIFI_STATE_DISABLED}, 1000 * {@link WifiManager#WIFI_STATE_DISABLING}, 1001 * {@link WifiManager#WIFI_STATE_ENABLED}, 1002 * {@link WifiManager#WIFI_STATE_ENABLING}, 1003 * {@link WifiManager#WIFI_STATE_UNKNOWN} 1004 */ 1005 @Override getWifiEnabledState()1006 public int getWifiEnabledState() { 1007 enforceAccessPermission(); 1008 if (isVerboseLoggingEnabled()) { 1009 mLog.info("getWifiEnabledState uid=%").c(Binder.getCallingUid()).flush(); 1010 } 1011 return getPrimaryClientModeManagerBlockingThreadSafe().syncGetWifiState(); 1012 } 1013 1014 /** 1015 * see {@link WifiManager#getWifiApState()} 1016 * @return One of {@link WifiManager#WIFI_AP_STATE_DISABLED}, 1017 * {@link WifiManager#WIFI_AP_STATE_DISABLING}, 1018 * {@link WifiManager#WIFI_AP_STATE_ENABLED}, 1019 * {@link WifiManager#WIFI_AP_STATE_ENABLING}, 1020 * {@link WifiManager#WIFI_AP_STATE_FAILED} 1021 */ 1022 @Override getWifiApEnabledState()1023 public int getWifiApEnabledState() { 1024 enforceAccessPermission(); 1025 if (isVerboseLoggingEnabled()) { 1026 mLog.info("getWifiApEnabledState uid=%").c(Binder.getCallingUid()).flush(); 1027 } 1028 return mTetheredSoftApTracker.getState(); 1029 } 1030 1031 /** 1032 * see {@link android.net.wifi.WifiManager#updateInterfaceIpState(String, int)} 1033 * 1034 * The possible modes include: {@link WifiManager#IFACE_IP_MODE_TETHERED}, 1035 * {@link WifiManager#IFACE_IP_MODE_LOCAL_ONLY}, 1036 * {@link WifiManager#IFACE_IP_MODE_CONFIGURATION_ERROR} 1037 * 1038 * @param ifaceName String name of the updated interface 1039 * @param mode new operating mode of the interface 1040 * 1041 * @throws SecurityException if the caller does not have permission to call update 1042 */ 1043 @Override updateInterfaceIpState(String ifaceName, int mode)1044 public void updateInterfaceIpState(String ifaceName, int mode) { 1045 // NETWORK_STACK is a signature only permission. 1046 enforceNetworkStackPermission(); 1047 mLog.info("updateInterfaceIpState uid=%").c(Binder.getCallingUid()).flush(); 1048 // hand off the work to our handler thread 1049 mWifiThreadRunner.post(() -> mLohsSoftApTracker.updateInterfaceIpState(ifaceName, mode)); 1050 } 1051 1052 /** 1053 * see {@link WifiManager#isDefaultCoexAlgorithmEnabled()} 1054 * @return {@code true} if the default coex algorithm is enabled. {@code false} otherwise. 1055 */ 1056 @Override isDefaultCoexAlgorithmEnabled()1057 public boolean isDefaultCoexAlgorithmEnabled() { 1058 return mContext.getResources().getBoolean(R.bool.config_wifiDefaultCoexAlgorithmEnabled); 1059 } 1060 1061 /** 1062 * see {@link android.net.wifi.WifiManager#setCoexUnsafeChannels(List, int)} 1063 * @param unsafeChannels List of {@link CoexUnsafeChannel} to avoid. 1064 * @param restrictions Bitmap of {@link CoexRestriction} specifying the mandatory 1065 * uses of the specified channels. 1066 */ 1067 @Override 1068 @RequiresApi(Build.VERSION_CODES.S) setCoexUnsafeChannels( @onNull List<CoexUnsafeChannel> unsafeChannels, int restrictions)1069 public void setCoexUnsafeChannels( 1070 @NonNull List<CoexUnsafeChannel> unsafeChannels, int restrictions) { 1071 if (!SdkLevel.isAtLeastS()) { 1072 throw new UnsupportedOperationException(); 1073 } 1074 mContext.enforceCallingOrSelfPermission( 1075 Manifest.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS, "WifiService"); 1076 if (unsafeChannels == null) { 1077 throw new IllegalArgumentException("unsafeChannels cannot be null"); 1078 } 1079 if (mContext.getResources().getBoolean(R.bool.config_wifiDefaultCoexAlgorithmEnabled)) { 1080 Log.e(TAG, "setCoexUnsafeChannels called but default coex algorithm is enabled"); 1081 return; 1082 } 1083 mWifiThreadRunner.post(() -> 1084 mCoexManager.setCoexUnsafeChannels(unsafeChannels, restrictions)); 1085 } 1086 1087 /** 1088 * See {@link WifiManager#registerCoexCallback(WifiManager.CoexCallback)} 1089 */ 1090 @RequiresApi(Build.VERSION_CODES.S) registerCoexCallback(@onNull ICoexCallback callback)1091 public void registerCoexCallback(@NonNull ICoexCallback callback) { 1092 if (!SdkLevel.isAtLeastS()) { 1093 throw new UnsupportedOperationException(); 1094 } 1095 mContext.enforceCallingOrSelfPermission( 1096 Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS, "WifiService"); 1097 if (callback == null) { 1098 throw new IllegalArgumentException("callback must not be null"); 1099 } 1100 if (isVerboseLoggingEnabled()) { 1101 mLog.info("registerCoexCallback uid=%").c(Binder.getCallingUid()).flush(); 1102 } 1103 mWifiThreadRunner.post(() -> mCoexManager.registerRemoteCoexCallback(callback)); 1104 } 1105 1106 /** 1107 * See {@link WifiManager#unregisterCoexCallback(WifiManager.CoexCallback)} 1108 */ 1109 @RequiresApi(Build.VERSION_CODES.S) unregisterCoexCallback(@onNull ICoexCallback callback)1110 public void unregisterCoexCallback(@NonNull ICoexCallback callback) { 1111 if (!SdkLevel.isAtLeastS()) { 1112 throw new UnsupportedOperationException(); 1113 } 1114 mContext.enforceCallingOrSelfPermission( 1115 Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS, "WifiService"); 1116 if (callback == null) { 1117 throw new IllegalArgumentException("callback must not be null"); 1118 } 1119 if (isVerboseLoggingEnabled()) { 1120 mLog.info("unregisterCoexCallback uid=%").c(Binder.getCallingUid()).flush(); 1121 } 1122 mWifiThreadRunner.post(() -> mCoexManager.unregisterRemoteCoexCallback(callback)); 1123 } 1124 1125 /** 1126 * see {@link android.net.wifi.WifiManager#startSoftAp(WifiConfiguration)} 1127 * @param wifiConfig SSID, security and channel details as part of WifiConfiguration 1128 * @return {@code true} if softap start was triggered 1129 * @throws SecurityException if the caller does not have permission to start softap 1130 */ 1131 @Override startSoftAp(WifiConfiguration wifiConfig, String packageName)1132 public boolean startSoftAp(WifiConfiguration wifiConfig, String packageName) { 1133 // NETWORK_STACK is a signature only permission. 1134 enforceNetworkStackPermission(); 1135 1136 mLog.info("startSoftAp uid=%").c(Binder.getCallingUid()).flush(); 1137 1138 SoftApConfiguration softApConfig = null; 1139 if (wifiConfig != null) { 1140 softApConfig = ApConfigUtil.fromWifiConfiguration(wifiConfig); 1141 if (softApConfig == null) { 1142 return false; 1143 } 1144 } 1145 1146 if (!mTetheredSoftApTracker.setEnablingIfAllowed()) { 1147 mLog.err("Tethering is already active.").flush(); 1148 return false; 1149 } 1150 1151 WorkSource requestorWs = new WorkSource(Binder.getCallingUid(), packageName); 1152 if (!mWifiThreadRunner.call( 1153 () -> mActiveModeWarden.canRequestMoreSoftApManagers(requestorWs), false)) { 1154 // Take down LOHS if it is up. 1155 mLohsSoftApTracker.stopAll(); 1156 } 1157 1158 if (!startSoftApInternal(new SoftApModeConfiguration( 1159 WifiManager.IFACE_IP_MODE_TETHERED, softApConfig, 1160 mTetheredSoftApTracker.getSoftApCapability()), requestorWs)) { 1161 mTetheredSoftApTracker.setFailedWhileEnabling(); 1162 return false; 1163 } 1164 mLastCallerInfoManager.put(LastCallerInfoManager.SOFT_AP, Process.myTid(), 1165 Binder.getCallingUid(), Binder.getCallingPid(), packageName, true); 1166 return true; 1167 } 1168 1169 /** 1170 * see {@link android.net.wifi.WifiManager#startTetheredHotspot(SoftApConfiguration)} 1171 * @param softApConfig SSID, security and channel details as part of SoftApConfiguration 1172 * @return {@code true} if softap start was triggered 1173 * @throws SecurityException if the caller does not have permission to start softap 1174 */ 1175 @Override startTetheredHotspot(@ullable SoftApConfiguration softApConfig, @NonNull String packageName)1176 public boolean startTetheredHotspot(@Nullable SoftApConfiguration softApConfig, 1177 @NonNull String packageName) { 1178 // NETWORK_STACK is a signature only permission. 1179 enforceNetworkStackPermission(); 1180 1181 mLog.info("startTetheredHotspot uid=%").c(Binder.getCallingUid()).flush(); 1182 1183 if (!mTetheredSoftApTracker.setEnablingIfAllowed()) { 1184 mLog.err("Tethering is already active.").flush(); 1185 return false; 1186 } 1187 1188 WorkSource requestorWs = new WorkSource(Binder.getCallingUid(), packageName); 1189 if (!mWifiThreadRunner.call( 1190 () -> mActiveModeWarden.canRequestMoreSoftApManagers(requestorWs), false)) { 1191 // Take down LOHS if it is up. 1192 mLohsSoftApTracker.stopAll(); 1193 } 1194 1195 if (!startSoftApInternal(new SoftApModeConfiguration( 1196 WifiManager.IFACE_IP_MODE_TETHERED, softApConfig, 1197 mTetheredSoftApTracker.getSoftApCapability()), requestorWs)) { 1198 mTetheredSoftApTracker.setFailedWhileEnabling(); 1199 return false; 1200 } 1201 mLastCallerInfoManager.put(LastCallerInfoManager.TETHERED_HOTSPOT, Process.myTid(), 1202 Binder.getCallingUid(), Binder.getCallingPid(), packageName, true); 1203 return true; 1204 } 1205 1206 /** 1207 * Internal method to start softap mode. Callers of this method should have already checked 1208 * proper permissions beyond the NetworkStack permission. 1209 */ startSoftApInternal(SoftApModeConfiguration apConfig, WorkSource requestorWs)1210 private boolean startSoftApInternal(SoftApModeConfiguration apConfig, WorkSource requestorWs) { 1211 int uid = Binder.getCallingUid(); 1212 boolean privileged = isSettingsOrSuw(Binder.getCallingPid(), uid); 1213 mLog.trace("startSoftApInternal uid=% mode=%") 1214 .c(uid).c(apConfig.getTargetMode()).flush(); 1215 1216 // null wifiConfig is a meaningful input for CMD_SET_AP; it means to use the persistent 1217 // AP config. 1218 SoftApConfiguration softApConfig = apConfig.getSoftApConfiguration(); 1219 if (softApConfig != null 1220 && (!WifiApConfigStore.validateApWifiConfiguration( 1221 softApConfig, privileged, mContext))) { 1222 Log.e(TAG, "Invalid SoftApConfiguration"); 1223 return false; 1224 } 1225 1226 mActiveModeWarden.startSoftAp(apConfig, requestorWs); 1227 return true; 1228 } 1229 1230 /** 1231 * see {@link android.net.wifi.WifiManager#stopSoftAp()} 1232 * @return {@code true} if softap stop was triggered 1233 * @throws SecurityException if the caller does not have permission to stop softap 1234 */ 1235 @Override stopSoftAp()1236 public boolean stopSoftAp() { 1237 // NETWORK_STACK is a signature only permission. 1238 enforceNetworkStackPermission(); 1239 1240 // only permitted callers are allowed to this point - they must have gone through 1241 // connectivity service since this method is protected with the NETWORK_STACK PERMISSION 1242 1243 mLog.info("stopSoftAp uid=%").c(Binder.getCallingUid()).flush(); 1244 1245 stopSoftApInternal(WifiManager.IFACE_IP_MODE_TETHERED); 1246 mLastCallerInfoManager.put(LastCallerInfoManager.SOFT_AP, Process.myTid(), 1247 Binder.getCallingUid(), Binder.getCallingPid(), "<unknown>", false); 1248 return true; 1249 } 1250 1251 /** 1252 * Internal method to stop softap mode. 1253 * 1254 * Callers of this method should have already checked 1255 * proper permissions beyond the NetworkStack permission. 1256 * 1257 * @param mode the operating mode of APs to bring down (ex, 1258 * {@link WifiManager.IFACE_IP_MODE_TETHERED} or 1259 * {@link WifiManager.IFACE_IP_MODE_LOCAL_ONLY}). 1260 * Use {@link WifiManager.IFACE_IP_MODE_UNSPECIFIED} to stop all APs. 1261 */ stopSoftApInternal(int mode)1262 private void stopSoftApInternal(int mode) { 1263 mLog.trace("stopSoftApInternal uid=% mode=%").c(Binder.getCallingUid()).c(mode).flush(); 1264 1265 mActiveModeWarden.stopSoftAp(mode); 1266 } 1267 1268 private final class CountryCodeListenerProxy implements WifiCountryCode.ChangeListener { 1269 @Override onDriverCountryCodeChanged(String countryCode)1270 public void onDriverCountryCodeChanged(String countryCode) { 1271 // post operation to handler thread 1272 mWifiThreadRunner.post(() -> { 1273 Log.i(TAG, "onDriverCountryCodeChanged " + countryCode); 1274 mTetheredSoftApTracker.updateAvailChannelListInSoftApCapability(); 1275 mActiveModeWarden.updateSoftApCapability( 1276 mTetheredSoftApTracker.getSoftApCapability()); 1277 }); 1278 } 1279 } 1280 1281 /** 1282 * SoftAp callback 1283 */ 1284 private final class TetheredSoftApTracker implements SoftApCallbackInternal { 1285 /** 1286 * State of tethered SoftAP 1287 * One of: {@link WifiManager#WIFI_AP_STATE_DISABLED}, 1288 * {@link WifiManager#WIFI_AP_STATE_DISABLING}, 1289 * {@link WifiManager#WIFI_AP_STATE_ENABLED}, 1290 * {@link WifiManager#WIFI_AP_STATE_ENABLING}, 1291 * {@link WifiManager#WIFI_AP_STATE_FAILED} 1292 */ 1293 private final Object mLock = new Object(); 1294 private int mTetheredSoftApState = WIFI_AP_STATE_DISABLED; 1295 private Map<String, List<WifiClient>> mTetheredSoftApConnectedClientsMap = new HashMap(); 1296 private Map<String, SoftApInfo> mTetheredSoftApInfoMap = new HashMap(); 1297 private boolean mIsBridgedMode = false; 1298 // TODO: We need to maintain two capability. One for LTE + SAP and one for WIFI + SAP 1299 private SoftApCapability mTetheredSoftApCapability = null; 1300 private boolean mIsBootComplete = false; 1301 handleBootCompleted()1302 public void handleBootCompleted() { 1303 mIsBootComplete = true; 1304 updateAvailChannelListInSoftApCapability(); 1305 } 1306 getState()1307 public int getState() { 1308 synchronized (mLock) { 1309 return mTetheredSoftApState; 1310 } 1311 } 1312 setEnablingIfAllowed()1313 public boolean setEnablingIfAllowed() { 1314 synchronized (mLock) { 1315 if (mTetheredSoftApState != WIFI_AP_STATE_DISABLED 1316 && mTetheredSoftApState != WIFI_AP_STATE_FAILED) { 1317 return false; 1318 } 1319 mTetheredSoftApState = WIFI_AP_STATE_ENABLING; 1320 return true; 1321 } 1322 } 1323 setFailedWhileEnabling()1324 public void setFailedWhileEnabling() { 1325 synchronized (mLock) { 1326 if (mTetheredSoftApState == WIFI_AP_STATE_ENABLING) { 1327 mTetheredSoftApState = WIFI_AP_STATE_FAILED; 1328 } 1329 } 1330 } 1331 getConnectedClients()1332 public Map<String, List<WifiClient>> getConnectedClients() { 1333 synchronized (mLock) { 1334 return mTetheredSoftApConnectedClientsMap; 1335 } 1336 } 1337 getSoftApInfos()1338 public Map<String, SoftApInfo> getSoftApInfos() { 1339 synchronized (mLock) { 1340 return mTetheredSoftApInfoMap; 1341 } 1342 } 1343 getIsBridgedMode()1344 public boolean getIsBridgedMode() { 1345 synchronized (mLock) { 1346 return mIsBridgedMode; 1347 } 1348 } 1349 getSoftApCapability()1350 public SoftApCapability getSoftApCapability() { 1351 synchronized (mLock) { 1352 if (mTetheredSoftApCapability == null) { 1353 mTetheredSoftApCapability = ApConfigUtil.updateCapabilityFromResource(mContext); 1354 // Default country code 1355 mTetheredSoftApCapability = updateSoftApCapabilityWithAvailableChannelList( 1356 mTetheredSoftApCapability); 1357 } 1358 return mTetheredSoftApCapability; 1359 } 1360 } 1361 updateSoftApCapabilityWithAvailableChannelList( @onNull SoftApCapability softApCapability)1362 private SoftApCapability updateSoftApCapabilityWithAvailableChannelList( 1363 @NonNull SoftApCapability softApCapability) { 1364 SoftApCapability newSoftApCapability = new SoftApCapability(softApCapability); 1365 if (!mIsBootComplete) { 1366 // The available channel list is from wificond. 1367 // It might be a failure or stuck during wificond init. 1368 return newSoftApCapability; 1369 } 1370 List<Integer> supportedChannelList = null; 1371 if (ApConfigUtil.isSoftAp24GhzSupported(mContext)) { 1372 supportedChannelList = ApConfigUtil.getAvailableChannelFreqsForBand( 1373 SoftApConfiguration.BAND_2GHZ, mWifiNative, mContext.getResources(), false); 1374 if (supportedChannelList != null) { 1375 newSoftApCapability.setSupportedChannelList( 1376 SoftApConfiguration.BAND_2GHZ, 1377 supportedChannelList.stream().mapToInt(Integer::intValue).toArray()); 1378 } 1379 } 1380 if (ApConfigUtil.isSoftAp5GhzSupported(mContext)) { 1381 supportedChannelList = ApConfigUtil.getAvailableChannelFreqsForBand( 1382 SoftApConfiguration.BAND_5GHZ, mWifiNative, mContext.getResources(), false); 1383 if (supportedChannelList != null) { 1384 newSoftApCapability.setSupportedChannelList( 1385 SoftApConfiguration.BAND_5GHZ, 1386 supportedChannelList.stream().mapToInt(Integer::intValue).toArray()); 1387 } 1388 } 1389 if (ApConfigUtil.isSoftAp6GhzSupported(mContext)) { 1390 supportedChannelList = ApConfigUtil.getAvailableChannelFreqsForBand( 1391 SoftApConfiguration.BAND_6GHZ, mWifiNative, mContext.getResources(), false); 1392 if (supportedChannelList != null) { 1393 newSoftApCapability.setSupportedChannelList( 1394 SoftApConfiguration.BAND_6GHZ, 1395 supportedChannelList.stream().mapToInt(Integer::intValue).toArray()); 1396 } 1397 } 1398 if (ApConfigUtil.isSoftAp60GhzSupported(mContext)) { 1399 supportedChannelList = ApConfigUtil.getAvailableChannelFreqsForBand( 1400 SoftApConfiguration.BAND_60GHZ, mWifiNative, mContext.getResources(), 1401 false); 1402 if (supportedChannelList != null) { 1403 newSoftApCapability.setSupportedChannelList( 1404 SoftApConfiguration.BAND_60GHZ, 1405 supportedChannelList.stream().mapToInt(Integer::intValue).toArray()); 1406 } 1407 } 1408 return newSoftApCapability; 1409 } 1410 updateAvailChannelListInSoftApCapability()1411 public void updateAvailChannelListInSoftApCapability() { 1412 onCapabilityChanged(updateSoftApCapabilityWithAvailableChannelList( 1413 getSoftApCapability())); 1414 } 1415 updateSoftApCapabilityWhenCarrierConfigChanged(int subId)1416 public void updateSoftApCapabilityWhenCarrierConfigChanged(int subId) { 1417 CarrierConfigManager carrierConfigManager = 1418 mContext.getSystemService(CarrierConfigManager.class); 1419 if (carrierConfigManager == null) return; 1420 PersistableBundle carrierConfig = carrierConfigManager.getConfigForSubId(subId); 1421 if (carrierConfig == null) return; 1422 int carrierMaxClient = carrierConfig.getInt( 1423 CarrierConfigManager.Wifi.KEY_HOTSPOT_MAX_CLIENT_COUNT); 1424 int finalSupportedClientNumber = mContext.getResources().getInteger( 1425 R.integer.config_wifiHardwareSoftapMaxClientCount); 1426 if (carrierMaxClient > 0) { 1427 finalSupportedClientNumber = Math.min(finalSupportedClientNumber, 1428 carrierMaxClient); 1429 } 1430 if (finalSupportedClientNumber == getSoftApCapability().getMaxSupportedClients()) { 1431 return; 1432 } 1433 SoftApCapability newSoftApCapability = new SoftApCapability(mTetheredSoftApCapability); 1434 newSoftApCapability.setMaxSupportedClients( 1435 finalSupportedClientNumber); 1436 onCapabilityChanged(newSoftApCapability); 1437 } 1438 1439 private final RemoteCallbackList<ISoftApCallback> mRegisteredSoftApCallbacks = 1440 new RemoteCallbackList<>(); 1441 registerSoftApCallback(ISoftApCallback callback)1442 public boolean registerSoftApCallback(ISoftApCallback callback) { 1443 return mRegisteredSoftApCallbacks.register(callback); 1444 } 1445 unregisterSoftApCallback(ISoftApCallback callback)1446 public void unregisterSoftApCallback(ISoftApCallback callback) { 1447 mRegisteredSoftApCallbacks.unregister(callback); 1448 } 1449 1450 /** 1451 * Called when soft AP state changes. 1452 * 1453 * @param state new new AP state. One of {@link #WIFI_AP_STATE_DISABLED}, 1454 * {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED}, 1455 * {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED} 1456 * @param failureReason reason when in failed state. One of 1457 * {@link #SAP_START_FAILURE_GENERAL}, {@link #SAP_START_FAILURE_NO_CHANNEL} 1458 */ 1459 @Override onStateChanged(int state, int failureReason)1460 public void onStateChanged(int state, int failureReason) { 1461 synchronized (mLock) { 1462 mTetheredSoftApState = state; 1463 } 1464 1465 int itemCount = mRegisteredSoftApCallbacks.beginBroadcast(); 1466 for (int i = 0; i < itemCount; i++) { 1467 try { 1468 mRegisteredSoftApCallbacks.getBroadcastItem(i).onStateChanged(state, 1469 failureReason); 1470 } catch (RemoteException e) { 1471 Log.e(TAG, "onStateChanged: remote exception -- " + e); 1472 } 1473 } 1474 mRegisteredSoftApCallbacks.finishBroadcast(); 1475 } 1476 1477 /** 1478 * Called when the connected clients to soft AP changes. 1479 * 1480 * @param clients connected clients to soft AP 1481 */ 1482 @Override onConnectedClientsOrInfoChanged(Map<String, SoftApInfo> infos, Map<String, List<WifiClient>> clients, boolean isBridged)1483 public void onConnectedClientsOrInfoChanged(Map<String, SoftApInfo> infos, 1484 Map<String, List<WifiClient>> clients, boolean isBridged) { 1485 synchronized (mLock) { 1486 mIsBridgedMode = isBridged; 1487 if (infos.size() == 0 && isBridged) { 1488 Log.d(TAG, "ShutDown bridged mode, clear isBridged cache in Service"); 1489 mIsBridgedMode = false; 1490 } 1491 mTetheredSoftApConnectedClientsMap = 1492 ApConfigUtil.deepCopyForWifiClientListMap(clients); 1493 mTetheredSoftApInfoMap = ApConfigUtil.deepCopyForSoftApInfoMap(infos); 1494 } 1495 int itemCount = mRegisteredSoftApCallbacks.beginBroadcast(); 1496 for (int i = 0; i < itemCount; i++) { 1497 try { 1498 mRegisteredSoftApCallbacks.getBroadcastItem(i).onConnectedClientsOrInfoChanged( 1499 ApConfigUtil.deepCopyForSoftApInfoMap(mTetheredSoftApInfoMap), 1500 ApConfigUtil.deepCopyForWifiClientListMap( 1501 mTetheredSoftApConnectedClientsMap), isBridged, false); 1502 } catch (RemoteException e) { 1503 Log.e(TAG, "onConnectedClientsOrInfoChanged: remote exception -- " + e); 1504 } 1505 } 1506 mRegisteredSoftApCallbacks.finishBroadcast(); 1507 } 1508 1509 /** 1510 * Called when capability of softap changes. 1511 * 1512 * @param capability is the softap capability. {@link SoftApCapability} 1513 */ 1514 @Override onCapabilityChanged(SoftApCapability capability)1515 public void onCapabilityChanged(SoftApCapability capability) { 1516 synchronized (mLock) { 1517 if (Objects.equals(capability, mTetheredSoftApCapability)) { 1518 return; 1519 } 1520 mTetheredSoftApCapability = new SoftApCapability(capability); 1521 } 1522 int itemCount = mRegisteredSoftApCallbacks.beginBroadcast(); 1523 for (int i = 0; i < itemCount; i++) { 1524 try { 1525 mRegisteredSoftApCallbacks.getBroadcastItem(i).onCapabilityChanged( 1526 mTetheredSoftApCapability); 1527 } catch (RemoteException e) { 1528 Log.e(TAG, "onCapabiliyChanged: remote exception -- " + e); 1529 } 1530 } 1531 mRegisteredSoftApCallbacks.finishBroadcast(); 1532 } 1533 1534 /** 1535 * Called when client trying to connect but device blocked the client with specific reason. 1536 * 1537 * @param client the currently blocked client. 1538 * @param blockedReason one of blocked reason from 1539 * {@link WifiManager.SapClientBlockedReason} 1540 */ 1541 @Override onBlockedClientConnecting(WifiClient client, int blockedReason)1542 public void onBlockedClientConnecting(WifiClient client, int blockedReason) { 1543 int itemCount = mRegisteredSoftApCallbacks.beginBroadcast(); 1544 for (int i = 0; i < itemCount; i++) { 1545 try { 1546 mRegisteredSoftApCallbacks.getBroadcastItem(i).onBlockedClientConnecting(client, 1547 blockedReason); 1548 } catch (RemoteException e) { 1549 Log.e(TAG, "onBlockedClientConnecting: remote exception -- " + e); 1550 } 1551 } 1552 mRegisteredSoftApCallbacks.finishBroadcast(); 1553 } 1554 } 1555 1556 /** 1557 * Implements LOHS behavior on top of the existing SoftAp API. 1558 */ 1559 private final class LohsSoftApTracker implements SoftApCallbackInternal { 1560 @GuardedBy("mLocalOnlyHotspotRequests") 1561 private final HashMap<Integer, LocalOnlyHotspotRequestInfo> 1562 mLocalOnlyHotspotRequests = new HashMap<>(); 1563 1564 /** Currently-active config, to be sent to shared clients registering later. */ 1565 @GuardedBy("mLocalOnlyHotspotRequests") 1566 private SoftApModeConfiguration mActiveConfig = null; 1567 1568 /** 1569 * Whether we are currently operating in exclusive mode (i.e. whether a custom config is 1570 * active). 1571 */ 1572 @GuardedBy("mLocalOnlyHotspotRequests") 1573 private boolean mIsExclusive = false; 1574 1575 @GuardedBy("mLocalOnlyHotspotRequests") 1576 private String mLohsInterfaceName; 1577 1578 /** 1579 * State of local-only hotspot 1580 * One of: {@link WifiManager#WIFI_AP_STATE_DISABLED}, 1581 * {@link WifiManager#WIFI_AP_STATE_DISABLING}, 1582 * {@link WifiManager#WIFI_AP_STATE_ENABLED}, 1583 * {@link WifiManager#WIFI_AP_STATE_ENABLING}, 1584 * {@link WifiManager#WIFI_AP_STATE_FAILED} 1585 */ 1586 @GuardedBy("mLocalOnlyHotspotRequests") 1587 private int mLohsState = WIFI_AP_STATE_DISABLED; 1588 1589 @GuardedBy("mLocalOnlyHotspotRequests") 1590 private int mLohsInterfaceMode = WifiManager.IFACE_IP_MODE_UNSPECIFIED; 1591 1592 private SoftApCapability mLohsSoftApCapability = null; 1593 getSoftApCapability()1594 public SoftApCapability getSoftApCapability() { 1595 if (mLohsSoftApCapability == null) { 1596 mLohsSoftApCapability = ApConfigUtil.updateCapabilityFromResource(mContext); 1597 } 1598 return mLohsSoftApCapability; 1599 } 1600 updateInterfaceIpState(String ifaceName, int mode)1601 public void updateInterfaceIpState(String ifaceName, int mode) { 1602 // update interface IP state related to local-only hotspot 1603 synchronized (mLocalOnlyHotspotRequests) { 1604 Log.d(TAG, "updateInterfaceIpState: ifaceName=" + ifaceName + " mode=" + mode 1605 + " previous LOHS mode= " + mLohsInterfaceMode); 1606 1607 switch (mode) { 1608 case WifiManager.IFACE_IP_MODE_LOCAL_ONLY: 1609 // first make sure we have registered requests. 1610 if (mLocalOnlyHotspotRequests.isEmpty()) { 1611 // we don't have requests... stop the hotspot 1612 Log.wtf(TAG, "Starting LOHS without any requests?"); 1613 stopSoftApInternal(WifiManager.IFACE_IP_MODE_LOCAL_ONLY); 1614 return; 1615 } 1616 // LOHS is ready to go! Call our registered requestors! 1617 mLohsInterfaceName = ifaceName; 1618 mLohsInterfaceMode = mode; 1619 sendHotspotStartedMessageToAllLOHSRequestInfoEntriesLocked(); 1620 break; 1621 case WifiManager.IFACE_IP_MODE_TETHERED: 1622 if (mLohsInterfaceName != null 1623 && mLohsInterfaceName.equals(ifaceName)) { 1624 /* This shouldn't happen except in a race, but if it does, tear down 1625 * the LOHS and let tethering win. 1626 * 1627 * If concurrent SAPs are allowed, the interface names will differ, 1628 * so we don't have to check the config here. 1629 */ 1630 Log.e(TAG, "Unexpected IP mode change on " + ifaceName); 1631 mLohsInterfaceName = null; 1632 mLohsInterfaceMode = WifiManager.IFACE_IP_MODE_UNSPECIFIED; 1633 sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked( 1634 LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE); 1635 } 1636 break; 1637 case WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR: 1638 if (ifaceName == null) { 1639 // All softAps 1640 mLohsInterfaceName = null; 1641 mLohsInterfaceMode = mode; 1642 sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked( 1643 LocalOnlyHotspotCallback.ERROR_GENERIC); 1644 stopSoftApInternal(WifiManager.IFACE_IP_MODE_UNSPECIFIED); 1645 } else if (ifaceName.equals(mLohsInterfaceName)) { 1646 mLohsInterfaceName = null; 1647 mLohsInterfaceMode = mode; 1648 sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked( 1649 LocalOnlyHotspotCallback.ERROR_GENERIC); 1650 stopSoftApInternal(WifiManager.IFACE_IP_MODE_LOCAL_ONLY); 1651 } else { 1652 // Not for LOHS. This is the wrong place to do this, but... 1653 stopSoftApInternal(WifiManager.IFACE_IP_MODE_TETHERED); 1654 } 1655 break; 1656 case WifiManager.IFACE_IP_MODE_UNSPECIFIED: 1657 if (ifaceName == null || ifaceName.equals(mLohsInterfaceName)) { 1658 mLohsInterfaceName = null; 1659 mLohsInterfaceMode = mode; 1660 } 1661 break; 1662 default: 1663 mLog.warn("updateInterfaceIpState: unknown mode %").c(mode).flush(); 1664 } 1665 } 1666 } 1667 1668 /** 1669 * Helper method to send a HOTSPOT_FAILED message to all registered LocalOnlyHotspotRequest 1670 * callers and clear the registrations. 1671 * 1672 * Callers should already hold the mLocalOnlyHotspotRequests lock. 1673 */ 1674 @GuardedBy("mLocalOnlyHotspotRequests") sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked(int reason)1675 private void sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked(int reason) { 1676 for (LocalOnlyHotspotRequestInfo requestor : mLocalOnlyHotspotRequests.values()) { 1677 try { 1678 requestor.sendHotspotFailedMessage(reason); 1679 requestor.unlinkDeathRecipient(); 1680 } catch (RemoteException e) { 1681 // This will be cleaned up by binder death handling 1682 } 1683 } 1684 1685 // Since all callers were notified, now clear the registrations. 1686 mLocalOnlyHotspotRequests.clear(); 1687 } 1688 1689 /** 1690 * Helper method to send a HOTSPOT_STOPPED message to all registered LocalOnlyHotspotRequest 1691 * callers and clear the registrations. 1692 * 1693 * Callers should already hold the mLocalOnlyHotspotRequests lock. 1694 */ 1695 @GuardedBy("mLocalOnlyHotspotRequests") sendHotspotStoppedMessageToAllLOHSRequestInfoEntriesLocked()1696 private void sendHotspotStoppedMessageToAllLOHSRequestInfoEntriesLocked() { 1697 for (LocalOnlyHotspotRequestInfo requestor : mLocalOnlyHotspotRequests.values()) { 1698 try { 1699 requestor.sendHotspotStoppedMessage(); 1700 requestor.unlinkDeathRecipient(); 1701 } catch (RemoteException e) { 1702 // This will be cleaned up by binder death handling 1703 } 1704 } 1705 1706 // Since all callers were notified, now clear the registrations. 1707 mLocalOnlyHotspotRequests.clear(); 1708 } 1709 1710 /** 1711 * Add a new LOHS client 1712 */ start(int pid, LocalOnlyHotspotRequestInfo request)1713 private int start(int pid, LocalOnlyHotspotRequestInfo request) { 1714 synchronized (mLocalOnlyHotspotRequests) { 1715 // does this caller already have a request? 1716 if (mLocalOnlyHotspotRequests.get(pid) != null) { 1717 mLog.trace("caller already has an active request").flush(); 1718 throw new IllegalStateException( 1719 "Caller already has an active LocalOnlyHotspot request"); 1720 } 1721 1722 // Never accept exclusive requests (with custom configuration) at the same time as 1723 // shared requests. 1724 if (!mLocalOnlyHotspotRequests.isEmpty()) { 1725 boolean requestIsExclusive = request.getCustomConfig() != null; 1726 if (mIsExclusive || requestIsExclusive) { 1727 mLog.trace("Cannot share with existing LOHS request due to custom config") 1728 .flush(); 1729 return LocalOnlyHotspotCallback.ERROR_GENERIC; 1730 } 1731 } 1732 1733 // At this point, the request is accepted. 1734 if (mLocalOnlyHotspotRequests.isEmpty()) { 1735 mWifiThreadRunner.post(() -> { 1736 startForFirstRequestLocked(request); 1737 }); 1738 1739 } else if (mLohsInterfaceMode == WifiManager.IFACE_IP_MODE_LOCAL_ONLY) { 1740 // LOHS has already started up for an earlier request, so we can send the 1741 // current config to the incoming request right away. 1742 try { 1743 mLog.trace("LOHS already up, trigger onStarted callback").flush(); 1744 request.sendHotspotStartedMessage(mActiveConfig.getSoftApConfiguration()); 1745 } catch (RemoteException e) { 1746 return LocalOnlyHotspotCallback.ERROR_GENERIC; 1747 } 1748 } 1749 1750 mLocalOnlyHotspotRequests.put(pid, request); 1751 return LocalOnlyHotspotCallback.REQUEST_REGISTERED; 1752 } 1753 } 1754 1755 @GuardedBy("mLocalOnlyHotspotRequests") startForFirstRequestLocked(LocalOnlyHotspotRequestInfo request)1756 private void startForFirstRequestLocked(LocalOnlyHotspotRequestInfo request) { 1757 int band = WifiApConfigStore.generateDefaultBand(mContext); 1758 1759 // For auto only 1760 if (hasAutomotiveFeature(mContext)) { 1761 if (mContext.getResources().getBoolean(R.bool.config_wifiLocalOnlyHotspot6ghz) 1762 && ApConfigUtil.isBandSupported(SoftApConfiguration.BAND_6GHZ, mContext)) { 1763 band = SoftApConfiguration.BAND_6GHZ; 1764 } else if (mContext.getResources().getBoolean( 1765 R.bool.config_wifi_local_only_hotspot_5ghz) 1766 && ApConfigUtil.isBandSupported(SoftApConfiguration.BAND_5GHZ, mContext)) { 1767 band = SoftApConfiguration.BAND_5GHZ; 1768 } 1769 } 1770 SoftApConfiguration softApConfig = mWifiApConfigStore.generateLocalOnlyHotspotConfig( 1771 mContext, band, request.getCustomConfig()); 1772 1773 mActiveConfig = new SoftApModeConfiguration( 1774 WifiManager.IFACE_IP_MODE_LOCAL_ONLY, 1775 softApConfig, mLohsSoftApTracker.getSoftApCapability()); 1776 mIsExclusive = (request.getCustomConfig() != null); 1777 1778 startSoftApInternal(mActiveConfig, request.getWorkSource()); 1779 } 1780 1781 /** 1782 * Requests that any local-only hotspot be stopped. 1783 */ stopAll()1784 public void stopAll() { 1785 synchronized (mLocalOnlyHotspotRequests) { 1786 if (!mLocalOnlyHotspotRequests.isEmpty()) { 1787 // This is used to take down LOHS when tethering starts, and in that 1788 // case we send failed instead of stopped. 1789 // TODO check if that is right. Calling onFailed instead of onStopped when the 1790 // hotspot is already started does not seem to match the documentation 1791 sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked( 1792 LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE); 1793 stopIfEmptyLocked(); 1794 } 1795 } 1796 } 1797 1798 /** 1799 * Unregisters the LOHS request from the given process and stops LOHS if no other clients. 1800 */ stopByPid(int pid)1801 public void stopByPid(int pid) { 1802 synchronized (mLocalOnlyHotspotRequests) { 1803 LocalOnlyHotspotRequestInfo requestInfo = mLocalOnlyHotspotRequests.remove(pid); 1804 if (requestInfo == null) return; 1805 requestInfo.unlinkDeathRecipient(); 1806 stopIfEmptyLocked(); 1807 } 1808 } 1809 1810 /** 1811 * Unregisters LocalOnlyHotspot request and stops the hotspot if needed. 1812 */ stopByRequest(LocalOnlyHotspotRequestInfo request)1813 public void stopByRequest(LocalOnlyHotspotRequestInfo request) { 1814 synchronized (mLocalOnlyHotspotRequests) { 1815 if (mLocalOnlyHotspotRequests.remove(request.getPid()) == null) { 1816 mLog.trace("LocalOnlyHotspotRequestInfo not found to remove").flush(); 1817 return; 1818 } 1819 stopIfEmptyLocked(); 1820 } 1821 } 1822 1823 @GuardedBy("mLocalOnlyHotspotRequests") stopIfEmptyLocked()1824 private void stopIfEmptyLocked() { 1825 if (mLocalOnlyHotspotRequests.isEmpty()) { 1826 mActiveConfig = null; 1827 mIsExclusive = false; 1828 mLohsInterfaceName = null; 1829 mLohsInterfaceMode = WifiManager.IFACE_IP_MODE_UNSPECIFIED; 1830 stopSoftApInternal(WifiManager.IFACE_IP_MODE_LOCAL_ONLY); 1831 } 1832 } 1833 1834 /** 1835 * Helper method to send a HOTSPOT_STARTED message to all registered LocalOnlyHotspotRequest 1836 * callers. 1837 * 1838 * Callers should already hold the mLocalOnlyHotspotRequests lock. 1839 */ 1840 @GuardedBy("mLocalOnlyHotspotRequests") sendHotspotStartedMessageToAllLOHSRequestInfoEntriesLocked()1841 private void sendHotspotStartedMessageToAllLOHSRequestInfoEntriesLocked() { 1842 for (LocalOnlyHotspotRequestInfo requestor : mLocalOnlyHotspotRequests.values()) { 1843 try { 1844 requestor.sendHotspotStartedMessage(mActiveConfig.getSoftApConfiguration()); 1845 } catch (RemoteException e) { 1846 // This will be cleaned up by binder death handling 1847 } 1848 } 1849 } 1850 1851 @Override onStateChanged(int state, int failureReason)1852 public void onStateChanged(int state, int failureReason) { 1853 // The AP state update from ClientModeImpl for softap 1854 synchronized (mLocalOnlyHotspotRequests) { 1855 Log.d(TAG, "lohs.onStateChanged: currentState=" + state 1856 + " previousState=" + mLohsState + " errorCode= " + failureReason 1857 + " ifaceName=" + mLohsInterfaceName); 1858 1859 // check if we have a failure - since it is possible (worst case scenario where 1860 // WifiController and ClientModeImpl are out of sync wrt modes) to get two FAILED 1861 // notifications in a row, we need to handle this first. 1862 if (state == WIFI_AP_STATE_FAILED) { 1863 // update registered LOHS callbacks if we see a failure 1864 int errorToReport = ERROR_GENERIC; 1865 if (failureReason == SAP_START_FAILURE_NO_CHANNEL) { 1866 errorToReport = ERROR_NO_CHANNEL; 1867 } 1868 // holding the required lock: send message to requestors and clear the list 1869 sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked(errorToReport); 1870 // also need to clear interface ip state 1871 updateInterfaceIpState(mLohsInterfaceName, 1872 WifiManager.IFACE_IP_MODE_UNSPECIFIED); 1873 } else if (state == WIFI_AP_STATE_DISABLING || state == WIFI_AP_STATE_DISABLED) { 1874 // softap is shutting down or is down... let requestors know via the 1875 // onStopped call 1876 // if we are currently in hotspot mode, then trigger onStopped for registered 1877 // requestors, otherwise something odd happened and we should clear state 1878 if (mLohsInterfaceName != null 1879 && mLohsInterfaceMode == WifiManager.IFACE_IP_MODE_LOCAL_ONLY) { 1880 // holding the required lock: send message to requestors and clear the list 1881 sendHotspotStoppedMessageToAllLOHSRequestInfoEntriesLocked(); 1882 } else { 1883 // LOHS not active: report an error (still holding the required lock) 1884 sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked(ERROR_GENERIC); 1885 } 1886 // also clear interface ip state 1887 updateInterfaceIpState(mLohsInterfaceName, 1888 WifiManager.IFACE_IP_MODE_UNSPECIFIED); 1889 } 1890 // For enabling and enabled, just record the new state 1891 mLohsState = state; 1892 } 1893 } 1894 } 1895 1896 /** 1897 * see {@link android.net.wifi.WifiManager#registerSoftApCallback(Executor, 1898 * WifiManager.SoftApCallback)} 1899 * 1900 * @param callback Soft AP callback to register 1901 * 1902 * @throws SecurityException if the caller does not have permission to register a callback 1903 * @throws RemoteException if remote exception happens 1904 * @throws IllegalArgumentException if the arguments are null or invalid 1905 */ 1906 @Override registerSoftApCallback(ISoftApCallback callback)1907 public void registerSoftApCallback(ISoftApCallback callback) { 1908 // verify arguments 1909 if (callback == null) { 1910 throw new IllegalArgumentException("Callback must not be null"); 1911 } 1912 1913 int uid = Binder.getCallingUid(); 1914 int pid = Binder.getCallingPid(); 1915 if (!mWifiPermissionsUtil.checkConfigOverridePermission(uid) 1916 && !checkNetworkSettingsPermission(pid, uid) 1917 && !checkMainlineNetworkStackPermission(pid, uid)) { 1918 // random apps should not be allowed to read the user specified config 1919 throw new SecurityException("App not allowed to read WiFi Ap information " 1920 + "(uid/pid = " + uid + "/" + pid + ")"); 1921 } 1922 1923 if (isVerboseLoggingEnabled()) { 1924 mLog.info("registerSoftApCallback uid=%").c(Binder.getCallingUid()).flush(); 1925 } 1926 1927 // post operation to handler thread 1928 mWifiThreadRunner.post(() -> { 1929 if (!mTetheredSoftApTracker.registerSoftApCallback(callback)) { 1930 Log.e(TAG, "registerSoftApCallback: Failed to add callback"); 1931 return; 1932 } 1933 // Update the client about the current state immediately after registering the callback 1934 try { 1935 callback.onStateChanged(mTetheredSoftApTracker.getState(), 0); 1936 callback.onConnectedClientsOrInfoChanged(mTetheredSoftApTracker.getSoftApInfos(), 1937 mTetheredSoftApTracker.getConnectedClients(), 1938 mTetheredSoftApTracker.getIsBridgedMode(), true); 1939 callback.onCapabilityChanged(mTetheredSoftApTracker.getSoftApCapability()); 1940 } catch (RemoteException e) { 1941 Log.e(TAG, "registerSoftApCallback: remote exception -- " + e); 1942 } 1943 }); 1944 } 1945 1946 /** 1947 * see {@link android.net.wifi.WifiManager#unregisterSoftApCallback(WifiManager.SoftApCallback)} 1948 * 1949 * @param callback Soft AP callback to unregister 1950 * 1951 * @throws SecurityException if the caller does not have permission to register a callback 1952 */ 1953 @Override unregisterSoftApCallback(ISoftApCallback callback)1954 public void unregisterSoftApCallback(ISoftApCallback callback) { 1955 int uid = Binder.getCallingUid(); 1956 int pid = Binder.getCallingPid(); 1957 if (!mWifiPermissionsUtil.checkConfigOverridePermission(uid) 1958 && !checkNetworkSettingsPermission(pid, uid) 1959 && !checkMainlineNetworkStackPermission(pid, uid)) { 1960 // random apps should not be allowed to read the user specified config 1961 throw new SecurityException("App not allowed to read WiFi Ap information " 1962 + "(uid/pid = " + uid + "/" + pid + ")"); 1963 } 1964 1965 if (isVerboseLoggingEnabled()) { 1966 mLog.info("unregisterSoftApCallback uid=%").c(Binder.getCallingUid()).flush(); 1967 } 1968 1969 // post operation to handler thread 1970 mWifiThreadRunner.post(() -> 1971 mTetheredSoftApTracker.unregisterSoftApCallback(callback)); 1972 } 1973 1974 /** 1975 * Temporary method used for testing while start is not fully implemented. This 1976 * method allows unit tests to register callbacks directly for testing mechanisms triggered by 1977 * softap mode changes. 1978 */ 1979 @VisibleForTesting registerLOHSForTest(int pid, LocalOnlyHotspotRequestInfo request)1980 void registerLOHSForTest(int pid, LocalOnlyHotspotRequestInfo request) { 1981 mLohsSoftApTracker.start(pid, request); 1982 } 1983 1984 /** 1985 * Method to start LocalOnlyHotspot. In this method, permissions, settings and modes are 1986 * checked to verify that we can enter softapmode. This method returns 1987 * {@link LocalOnlyHotspotCallback#REQUEST_REGISTERED} if we will attempt to start, otherwise, 1988 * possible startup erros may include tethering being disallowed failure reason {@link 1989 * LocalOnlyHotspotCallback#ERROR_TETHERING_DISALLOWED} or an incompatible mode failure reason 1990 * {@link LocalOnlyHotspotCallback#ERROR_INCOMPATIBLE_MODE}. 1991 * 1992 * see {@link WifiManager#startLocalOnlyHotspot(LocalOnlyHotspotCallback)} 1993 * 1994 * @param callback Callback to communicate with WifiManager and allow cleanup if the app dies. 1995 * @param packageName String name of the calling package. 1996 * @param featureId The feature in the package 1997 * @param customConfig Custom configuration to be applied to the hotspot, or null for a shared 1998 * hotspot with framework-generated config. 1999 * 2000 * @return int return code for attempt to start LocalOnlyHotspot. 2001 * 2002 * @throws SecurityException if the caller does not have permission to start a Local Only 2003 * Hotspot. 2004 * @throws IllegalStateException if the caller attempts to start the LocalOnlyHotspot while they 2005 * have an outstanding request. 2006 */ 2007 @Override startLocalOnlyHotspot(ILocalOnlyHotspotCallback callback, String packageName, String featureId, SoftApConfiguration customConfig)2008 public int startLocalOnlyHotspot(ILocalOnlyHotspotCallback callback, String packageName, 2009 String featureId, SoftApConfiguration customConfig) { 2010 // first check if the caller has permission to start a local only hotspot 2011 // need to check for WIFI_STATE_CHANGE and location permission 2012 final int uid = Binder.getCallingUid(); 2013 final int pid = Binder.getCallingPid(); 2014 2015 mLog.info("start uid=% pid=%").c(uid).c(pid).flush(); 2016 2017 final WorkSource requestorWs; 2018 // Permission requirements are different with/without custom config. 2019 if (customConfig == null) { 2020 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 2021 return LocalOnlyHotspotCallback.ERROR_GENERIC; 2022 } 2023 enforceLocationPermission(packageName, featureId, uid); 2024 long ident = Binder.clearCallingIdentity(); 2025 try { 2026 // also need to verify that Locations services are enabled. 2027 if (!mWifiPermissionsUtil.isLocationModeEnabled()) { 2028 throw new SecurityException("Location mode is not enabled."); 2029 } 2030 // TODO(b/162344695): Exception added for LOHS. This exception is need to avoid 2031 // breaking existing LOHS behavior: LOHS AP iface is allowed to delete STA iface 2032 // (even if LOHS app has lower priority than user toggled on STA iface). This does 2033 // not fit in with the new context based concurrency priority in HalDeviceManager, 2034 // but we cannot break existing API's. So, we artificially boost the priority of 2035 // the request by "faking" the requestor context as settings app. 2036 // We probably need some UI dialog to allow the user to grant the app's LOHS 2037 // request. Once that UI dialog is added, we can get rid of this hack and use the UI 2038 // to elevate the priority of LOHS request only if user approves the request to 2039 // toggle wifi off for LOHS. 2040 requestorWs = mFrameworkFacade.getSettingsWorkSource(mContext); 2041 } finally { 2042 Binder.restoreCallingIdentity(ident); 2043 } 2044 } else { 2045 if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { 2046 throw new SecurityException(TAG + ": Permission denied"); 2047 } 2048 // Already privileged, no need to fake. 2049 requestorWs = new WorkSource(uid, packageName); 2050 } 2051 2052 // verify that tethering is not disabled 2053 if (mUserManager.hasUserRestrictionForUser( 2054 UserManager.DISALLOW_CONFIG_TETHERING, UserHandle.getUserHandleForUid(uid))) { 2055 return LocalOnlyHotspotCallback.ERROR_TETHERING_DISALLOWED; 2056 } 2057 2058 // the app should be in the foreground 2059 long ident = Binder.clearCallingIdentity(); 2060 try { 2061 // also need to verify that Locations services are enabled. 2062 if (!mFrameworkFacade.isAppForeground(mContext, uid)) { 2063 return LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE; 2064 } 2065 } finally { 2066 Binder.restoreCallingIdentity(ident); 2067 } 2068 2069 // check if we are currently tethering 2070 if (!mActiveModeWarden.canRequestMoreSoftApManagers(requestorWs) 2071 && mTetheredSoftApTracker.getState() == WIFI_AP_STATE_ENABLED) { 2072 // Tethering is enabled, cannot start LocalOnlyHotspot 2073 mLog.info("Cannot start localOnlyHotspot when WiFi Tethering is active.") 2074 .flush(); 2075 return LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE; 2076 } 2077 2078 // now create the new LOHS request info object 2079 LocalOnlyHotspotRequestInfo request = new LocalOnlyHotspotRequestInfo( 2080 requestorWs, callback, new LocalOnlyRequestorCallback(), customConfig); 2081 2082 return mLohsSoftApTracker.start(pid, request); 2083 } 2084 2085 /** 2086 * see {@link WifiManager#stopLocalOnlyHotspot()} 2087 * 2088 * @throws SecurityException if the caller does not have permission to stop a Local Only 2089 * Hotspot. 2090 */ 2091 @Override stopLocalOnlyHotspot()2092 public void stopLocalOnlyHotspot() { 2093 // don't do a permission check here. if the app's permission to change the wifi state is 2094 // revoked, we still want them to be able to stop a previously created hotspot (otherwise 2095 // it could cost the user money). When the app created the hotspot, its permission was 2096 // checked. 2097 final int uid = Binder.getCallingUid(); 2098 final int pid = Binder.getCallingPid(); 2099 2100 mLog.info("stopLocalOnlyHotspot uid=% pid=%").c(uid).c(pid).flush(); 2101 2102 mLohsSoftApTracker.stopByPid(pid); 2103 } 2104 2105 /** 2106 * see {@link WifiManager#watchLocalOnlyHotspot(LocalOnlyHotspotObserver)} 2107 * 2108 * This call requires the android.permission.NETWORK_SETTINGS permission. 2109 * 2110 * @param callback Callback to communicate with WifiManager and allow cleanup if the app dies. 2111 * 2112 * @throws SecurityException if the caller does not have permission to watch Local Only Hotspot 2113 * status updates. 2114 * @throws IllegalStateException if the caller attempts to watch LocalOnlyHotspot updates with 2115 * an existing subscription. 2116 */ 2117 @Override startWatchLocalOnlyHotspot(ILocalOnlyHotspotCallback callback)2118 public void startWatchLocalOnlyHotspot(ILocalOnlyHotspotCallback callback) { 2119 // NETWORK_SETTINGS is a signature only permission. 2120 enforceNetworkSettingsPermission(); 2121 2122 throw new UnsupportedOperationException("LocalOnlyHotspot is still in development"); 2123 } 2124 2125 /** 2126 * see {@link WifiManager#unregisterLocalOnlyHotspotObserver()} 2127 */ 2128 @Override stopWatchLocalOnlyHotspot()2129 public void stopWatchLocalOnlyHotspot() { 2130 // NETWORK_STACK is a signature only permission. 2131 enforceNetworkSettingsPermission(); 2132 throw new UnsupportedOperationException("LocalOnlyHotspot is still in development"); 2133 } 2134 2135 /** 2136 * see {@link WifiManager#getWifiApConfiguration()} 2137 * @return soft access point configuration 2138 * @throws SecurityException if the caller does not have permission to retrieve the softap 2139 * config 2140 */ 2141 @Nullable 2142 @Override getWifiApConfiguration()2143 public WifiConfiguration getWifiApConfiguration() { 2144 enforceAccessPermission(); 2145 int uid = Binder.getCallingUid(); 2146 // only allow Settings UI to get the saved SoftApConfig 2147 if (!mWifiPermissionsUtil.checkConfigOverridePermission(uid)) { 2148 // random apps should not be allowed to read the user specified config 2149 throw new SecurityException("App not allowed to read or update stored WiFi Ap config " 2150 + "(uid = " + uid + ")"); 2151 } 2152 2153 if (isVerboseLoggingEnabled()) { 2154 mLog.info("getWifiApConfiguration uid=%").c(uid).flush(); 2155 } 2156 2157 // hand off work to the ClientModeImpl handler thread to sync work between calls 2158 // and SoftApManager starting up softap 2159 return (mWifiThreadRunner.call(mWifiApConfigStore::getApConfiguration, 2160 new SoftApConfiguration.Builder().build())).toWifiConfiguration(); 2161 } 2162 2163 /** 2164 * see {@link WifiManager#getSoftApConfiguration()} 2165 * @return soft access point configuration {@link SoftApConfiguration} 2166 * @throws SecurityException if the caller does not have permission to retrieve the softap 2167 * config 2168 */ 2169 @NonNull 2170 @Override getSoftApConfiguration()2171 public SoftApConfiguration getSoftApConfiguration() { 2172 int uid = Binder.getCallingUid(); 2173 if (!mWifiPermissionsUtil.checkConfigOverridePermission(uid) 2174 && !mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { 2175 // random apps should not be allowed to read the user specified config 2176 throw new SecurityException("App not allowed to read or update stored WiFi Ap config " 2177 + "(uid = " + uid + ")"); 2178 } 2179 if (isVerboseLoggingEnabled()) { 2180 mLog.info("getSoftApConfiguration uid=%").c(uid).flush(); 2181 } 2182 2183 // hand off work to the ClientModeImpl handler thread to sync work between calls 2184 // and SoftApManager starting up softap 2185 return mWifiThreadRunner.call(mWifiApConfigStore::getApConfiguration, 2186 new SoftApConfiguration.Builder().build()); 2187 } 2188 2189 /** 2190 * see {@link WifiManager#setWifiApConfiguration(WifiConfiguration)} 2191 * @param wifiConfig WifiConfiguration details for soft access point 2192 * @return boolean indicating success or failure of the operation 2193 * @throws SecurityException if the caller does not have permission to write the softap config 2194 */ 2195 @Override setWifiApConfiguration(WifiConfiguration wifiConfig, String packageName)2196 public boolean setWifiApConfiguration(WifiConfiguration wifiConfig, String packageName) { 2197 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 2198 return false; 2199 } 2200 int uid = Binder.getCallingUid(); 2201 // only allow Settings UI to write the stored SoftApConfig 2202 if (!mWifiPermissionsUtil.checkConfigOverridePermission(uid)) { 2203 // random apps should not be allowed to read the user specified config 2204 throw new SecurityException("App not allowed to read or update stored WiFi AP config " 2205 + "(uid = " + uid + ")"); 2206 } 2207 mLog.info("setWifiApConfiguration uid=%").c(uid).flush(); 2208 if (wifiConfig == null) 2209 return false; 2210 SoftApConfiguration softApConfig = ApConfigUtil.fromWifiConfiguration(wifiConfig); 2211 if (softApConfig == null) return false; 2212 if (WifiApConfigStore.validateApWifiConfiguration( 2213 softApConfig, false, mContext)) { 2214 mWifiThreadRunner.post(() -> mWifiApConfigStore.setApConfiguration(softApConfig)); 2215 return true; 2216 } else { 2217 Log.e(TAG, "Invalid WifiConfiguration"); 2218 return false; 2219 } 2220 } 2221 2222 /** 2223 * see {@link WifiManager#setSoftApConfiguration(SoftApConfiguration)} 2224 * @param softApConfig {@link SoftApConfiguration} details for soft access point 2225 * @return boolean indicating success or failure of the operation 2226 * @throws SecurityException if the caller does not have permission to write the softap config 2227 */ 2228 @Override setSoftApConfiguration( @onNull SoftApConfiguration softApConfig, @NonNull String packageName)2229 public boolean setSoftApConfiguration( 2230 @NonNull SoftApConfiguration softApConfig, @NonNull String packageName) { 2231 int uid = Binder.getCallingUid(); 2232 boolean privileged = mWifiPermissionsUtil.checkNetworkSettingsPermission(uid); 2233 if (!mWifiPermissionsUtil.checkConfigOverridePermission(uid) 2234 && !privileged) { 2235 // random apps should not be allowed to read the user specified config 2236 throw new SecurityException("App not allowed to read or update stored WiFi Ap config " 2237 + "(uid = " + uid + ")"); 2238 } 2239 mLog.info("setSoftApConfiguration uid=%").c(uid).flush(); 2240 if (softApConfig == null) return false; 2241 if (WifiApConfigStore.validateApWifiConfiguration(softApConfig, privileged, mContext)) { 2242 mActiveModeWarden.updateSoftApConfiguration(softApConfig); 2243 mWifiThreadRunner.post(() -> mWifiApConfigStore.setApConfiguration(softApConfig)); 2244 return true; 2245 } else { 2246 Log.e(TAG, "Invalid SoftAp Configuration"); 2247 return false; 2248 } 2249 } 2250 2251 /** 2252 * see {@link android.net.wifi.WifiManager#setScanAlwaysAvailable(boolean)} 2253 */ 2254 @Override setScanAlwaysAvailable(boolean isAvailable, String packageName)2255 public void setScanAlwaysAvailable(boolean isAvailable, String packageName) { 2256 enforceNetworkSettingsPermission(); 2257 mLog.info("setScanAlwaysAvailable uid=% package=% isAvailable=%") 2258 .c(Binder.getCallingUid()) 2259 .c(packageName) 2260 .c(isAvailable) 2261 .flush(); 2262 mSettingsStore.handleWifiScanAlwaysAvailableToggled(isAvailable); 2263 long ident = Binder.clearCallingIdentity(); 2264 try { 2265 mWifiInjector.getWifiScanAlwaysAvailableSettingsCompatibility() 2266 .handleWifiScanAlwaysAvailableToggled(isAvailable); 2267 } finally { 2268 Binder.restoreCallingIdentity(ident); 2269 } 2270 mActiveModeWarden.scanAlwaysModeChanged(); 2271 } 2272 2273 /** 2274 * see {@link android.net.wifi.WifiManager#isScanAlwaysAvailable()} 2275 */ 2276 @Override isScanAlwaysAvailable()2277 public boolean isScanAlwaysAvailable() { 2278 enforceAccessPermission(); 2279 if (isVerboseLoggingEnabled()) { 2280 mLog.info("isScanAlwaysAvailable uid=%").c(Binder.getCallingUid()).flush(); 2281 } 2282 return mSettingsStore.isScanAlwaysAvailableToggleEnabled(); 2283 } 2284 2285 /** 2286 * see {@link android.net.wifi.WifiManager#disconnect()} 2287 */ 2288 @Override disconnect(String packageName)2289 public boolean disconnect(String packageName) { 2290 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 2291 return false; 2292 } 2293 if (!isTargetSdkLessThanQOrPrivileged( 2294 packageName, Binder.getCallingPid(), Binder.getCallingUid())) { 2295 mLog.info("disconnect not allowed for uid=%") 2296 .c(Binder.getCallingUid()).flush(); 2297 return false; 2298 } 2299 mLog.info("disconnect uid=%").c(Binder.getCallingUid()).flush(); 2300 mWifiThreadRunner.post(() -> mActiveModeWarden.getPrimaryClientModeManager().disconnect()); 2301 return true; 2302 } 2303 2304 /** 2305 * see {@link android.net.wifi.WifiManager#reconnect()} 2306 */ 2307 @Override reconnect(String packageName)2308 public boolean reconnect(String packageName) { 2309 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 2310 return false; 2311 } 2312 int callingUid = Binder.getCallingUid(); 2313 if (!isTargetSdkLessThanQOrPrivileged(packageName, Binder.getCallingPid(), callingUid)) { 2314 mLog.info("reconnect not allowed for uid=%").c(callingUid).flush(); 2315 return false; 2316 } 2317 mLog.info("reconnect uid=%").c(callingUid).flush(); 2318 2319 mWifiThreadRunner.post(() -> { 2320 mActiveModeWarden.getPrimaryClientModeManager().reconnect(new WorkSource(callingUid)); 2321 }); 2322 return true; 2323 } 2324 2325 /** 2326 * see {@link android.net.wifi.WifiManager#reassociate()} 2327 */ 2328 @Override reassociate(String packageName)2329 public boolean reassociate(String packageName) { 2330 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 2331 return false; 2332 } 2333 if (!isTargetSdkLessThanQOrPrivileged( 2334 packageName, Binder.getCallingPid(), Binder.getCallingUid())) { 2335 mLog.info("reassociate not allowed for uid=%") 2336 .c(Binder.getCallingUid()).flush(); 2337 return false; 2338 } 2339 mLog.info("reassociate uid=%").c(Binder.getCallingUid()).flush(); 2340 mWifiThreadRunner.post(() -> mActiveModeWarden.getPrimaryClientModeManager().reassociate()); 2341 return true; 2342 } 2343 2344 /** 2345 * Returns true if we should log the call to getSupportedFeatures. 2346 * 2347 * Because of the way getSupportedFeatures is used in WifiManager, there are 2348 * often clusters of several back-to-back calls; avoid repeated logging if 2349 * the feature set has not changed and the time interval is short. 2350 */ needToLogSupportedFeatures(long features)2351 private boolean needToLogSupportedFeatures(long features) { 2352 if (isVerboseLoggingEnabled()) { 2353 long now = mClock.getElapsedSinceBootMillis(); 2354 synchronized (this) { 2355 if (now > mLastLoggedSupportedFeaturesTimestamp + A_FEW_MILLISECONDS 2356 || features != mLastLoggedSupportedFeatures) { 2357 mLastLoggedSupportedFeaturesTimestamp = now; 2358 mLastLoggedSupportedFeatures = features; 2359 return true; 2360 } 2361 } 2362 } 2363 return false; 2364 } 2365 private static final int A_FEW_MILLISECONDS = 250; 2366 private long mLastLoggedSupportedFeatures = -1; 2367 private long mLastLoggedSupportedFeaturesTimestamp = 0; 2368 2369 /** 2370 * see {@link android.net.wifi.WifiManager#getSupportedFeatures} 2371 */ 2372 @Override getSupportedFeatures()2373 public long getSupportedFeatures() { 2374 enforceAccessPermission(); 2375 long features = getSupportedFeaturesInternal(); 2376 if (needToLogSupportedFeatures(features)) { 2377 mLog.info("getSupportedFeatures uid=% returns %") 2378 .c(Binder.getCallingUid()) 2379 .c(Long.toHexString(features)) 2380 .flush(); 2381 } 2382 return features; 2383 } 2384 2385 @Override getWifiActivityEnergyInfoAsync(IOnWifiActivityEnergyInfoListener listener)2386 public void getWifiActivityEnergyInfoAsync(IOnWifiActivityEnergyInfoListener listener) { 2387 if (isVerboseLoggingEnabled()) { 2388 mLog.info("getWifiActivityEnergyInfoAsync uid=%") 2389 .c(Binder.getCallingUid()) 2390 .flush(); 2391 } 2392 // getWifiActivityEnergyInfo() performs permission checking 2393 WifiActivityEnergyInfo info = getWifiActivityEnergyInfo(); 2394 try { 2395 listener.onWifiActivityEnergyInfo(info); 2396 } catch (RemoteException e) { 2397 Log.e(TAG, "onWifiActivityEnergyInfo: RemoteException -- ", e); 2398 } 2399 } 2400 getWifiActivityEnergyInfo()2401 private WifiActivityEnergyInfo getWifiActivityEnergyInfo() { 2402 enforceAccessPermission(); 2403 if (isVerboseLoggingEnabled()) { 2404 mLog.info("getWifiActivityEnergyInfo uid=%").c(Binder.getCallingUid()).flush(); 2405 } 2406 if ((getSupportedFeatures() & WifiManager.WIFI_FEATURE_LINK_LAYER_STATS) == 0) { 2407 return null; 2408 } 2409 WifiLinkLayerStats stats = mWifiThreadRunner.call( 2410 () -> mActiveModeWarden.getPrimaryClientModeManager().getWifiLinkLayerStats(), 2411 null); 2412 if (stats == null) { 2413 return null; 2414 } 2415 2416 final long rxIdleTimeMillis = stats.on_time - stats.tx_time - stats.rx_time; 2417 if (VDBG || rxIdleTimeMillis < 0 || stats.on_time < 0 || stats.tx_time < 0 2418 || stats.rx_time < 0 || stats.on_time_scan < 0) { 2419 Log.d(TAG, " getWifiActivityEnergyInfo: " 2420 + " on_time_millis=" + stats.on_time 2421 + " tx_time_millis=" + stats.tx_time 2422 + " rx_time_millis=" + stats.rx_time 2423 + " rxIdleTimeMillis=" + rxIdleTimeMillis 2424 + " scan_time_millis=" + stats.on_time_scan); 2425 } 2426 2427 // Convert the LinkLayerStats into WifiActivityEnergyInfo 2428 return new WifiActivityEnergyInfo( 2429 mClock.getElapsedSinceBootMillis(), 2430 WifiActivityEnergyInfo.STACK_STATE_STATE_IDLE, 2431 stats.tx_time, 2432 stats.rx_time, 2433 stats.on_time_scan, 2434 rxIdleTimeMillis); 2435 } 2436 2437 /** 2438 * see {@link android.net.wifi.WifiManager#getConfiguredNetworks()} 2439 * 2440 * @param packageName String name of the calling package 2441 * @param featureId The feature in the package 2442 * @param callerNetworksOnly Whether to only return networks created by the caller 2443 * @return the list of configured networks 2444 */ 2445 @Override getConfiguredNetworks(String packageName, String featureId, boolean callerNetworksOnly)2446 public ParceledListSlice<WifiConfiguration> getConfiguredNetworks(String packageName, 2447 String featureId, boolean callerNetworksOnly) { 2448 enforceAccessPermission(); 2449 int callingUid = Binder.getCallingUid(); 2450 // bypass shell: can get various pkg name 2451 // also bypass if caller is only retrieving networks added by itself 2452 if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID) { 2453 mWifiPermissionsUtil.checkPackage(callingUid, packageName); 2454 if (!callerNetworksOnly) { 2455 long ident = Binder.clearCallingIdentity(); 2456 try { 2457 mWifiPermissionsUtil.enforceCanAccessScanResults(packageName, featureId, 2458 callingUid, null); 2459 } catch (SecurityException e) { 2460 Log.w(TAG, "Permission violation - getConfiguredNetworks not allowed for uid=" 2461 + callingUid + ", packageName=" + packageName + ", reason=" + e); 2462 return new ParceledListSlice<>(new ArrayList<>()); 2463 } finally { 2464 Binder.restoreCallingIdentity(ident); 2465 } 2466 } 2467 } 2468 boolean isDeviceOrProfileOwner = isDeviceOrProfileOwner(callingUid, packageName); 2469 boolean isCarrierApp = mWifiInjector.makeTelephonyManager() 2470 .checkCarrierPrivilegesForPackageAnyPhone(packageName) 2471 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; 2472 boolean isPrivileged = isPrivileged(getCallingPid(), callingUid); 2473 // Only DO, PO, carrier app or system app can use callerNetworksOnly argument 2474 if (callerNetworksOnly) { 2475 if (!isDeviceOrProfileOwner && !isCarrierApp && !isPrivileged) { 2476 throw new SecurityException( 2477 "Not a DO, PO, carrier or privileged app"); 2478 } 2479 } 2480 boolean isTargetSdkLessThanQOrPrivileged = isTargetSdkLessThanQOrPrivileged( 2481 packageName, Binder.getCallingPid(), callingUid); 2482 if (!isTargetSdkLessThanQOrPrivileged && !isCarrierApp) { 2483 mLog.info("getConfiguredNetworks not allowed for uid=%") 2484 .c(callingUid).flush(); 2485 return new ParceledListSlice<>(new ArrayList<>()); 2486 } 2487 if (isVerboseLoggingEnabled()) { 2488 mLog.info("getConfiguredNetworks uid=%").c(callingUid).flush(); 2489 } 2490 2491 int targetConfigUid = Process.INVALID_UID; // don't expose any MAC addresses 2492 if (isPrivileged || isDeviceOrProfileOwner) { 2493 targetConfigUid = Process.WIFI_UID; // expose all MAC addresses 2494 } else if (isCarrierApp) { 2495 targetConfigUid = callingUid; // expose only those configs created by the Carrier App 2496 } 2497 int finalTargetConfigUid = targetConfigUid; 2498 List<WifiConfiguration> configs = mWifiThreadRunner.call( 2499 () -> mWifiConfigManager.getSavedNetworks(finalTargetConfigUid), 2500 Collections.emptyList()); 2501 if (isTargetSdkLessThanQOrPrivileged && !callerNetworksOnly) { 2502 return new ParceledListSlice<>( 2503 WifiConfigurationUtil.convertMultiTypeConfigsToLegacyConfigs(configs)); 2504 } 2505 // Should only get its own configs 2506 List<WifiConfiguration> creatorConfigs = new ArrayList<>(); 2507 for (WifiConfiguration config : configs) { 2508 if (config.creatorUid == callingUid) { 2509 creatorConfigs.add(config); 2510 } 2511 } 2512 return new ParceledListSlice<>( 2513 WifiConfigurationUtil.convertMultiTypeConfigsToLegacyConfigs(creatorConfigs)); 2514 } 2515 2516 /** 2517 * see {@link android.net.wifi.WifiManager#getPrivilegedConfiguredNetworks()} 2518 * 2519 * @param packageName String name of the calling package 2520 * @param featureId The feature in the package 2521 * @return the list of configured networks with real preSharedKey 2522 */ 2523 @Override getPrivilegedConfiguredNetworks( String packageName, String featureId)2524 public ParceledListSlice<WifiConfiguration> getPrivilegedConfiguredNetworks( 2525 String packageName, String featureId) { 2526 enforceReadCredentialPermission(); 2527 enforceAccessPermission(); 2528 int callingUid = Binder.getCallingUid(); 2529 long ident = Binder.clearCallingIdentity(); 2530 try { 2531 mWifiPermissionsUtil.enforceCanAccessScanResults(packageName, featureId, callingUid, 2532 null); 2533 } catch (SecurityException e) { 2534 Log.w(TAG, "Permission violation - getPrivilegedConfiguredNetworks not allowed for" 2535 + " uid=" + callingUid + ", packageName=" + packageName + ", reason=" + e); 2536 return null; 2537 } finally { 2538 Binder.restoreCallingIdentity(ident); 2539 } 2540 if (isVerboseLoggingEnabled()) { 2541 mLog.info("getPrivilegedConfiguredNetworks uid=%").c(callingUid).flush(); 2542 } 2543 List<WifiConfiguration> configs = mWifiThreadRunner.call( 2544 () -> mWifiConfigManager.getConfiguredNetworksWithPasswords(), 2545 Collections.emptyList()); 2546 return new ParceledListSlice<>( 2547 WifiConfigurationUtil.convertMultiTypeConfigsToLegacyConfigs(configs)); 2548 } 2549 2550 /** 2551 * Return a map of all matching configurations keys with corresponding scanResults (or an empty 2552 * map if none). 2553 * 2554 * @param scanResults The list of scan results 2555 * @return Map that consists of FQDN (Fully Qualified Domain Name) and corresponding 2556 * scanResults per network type({@link WifiManager#PASSPOINT_HOME_NETWORK} and {@link 2557 * WifiManager#PASSPOINT_ROAMING_NETWORK}). 2558 */ 2559 @Override 2560 public Map<String, Map<Integer, List<ScanResult>>> getAllMatchingPasspointProfilesForScanResults(List<ScanResult> scanResults)2561 getAllMatchingPasspointProfilesForScanResults(List<ScanResult> scanResults) { 2562 if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { 2563 throw new SecurityException(TAG + ": Permission denied"); 2564 } 2565 if (isVerboseLoggingEnabled()) { 2566 mLog.info("getMatchingPasspointConfigurations uid=%").c(Binder.getCallingUid()).flush(); 2567 } 2568 if (!ScanResultUtil.validateScanResultList(scanResults)) { 2569 Log.e(TAG, "Attempt to retrieve passpoint with invalid scanResult List"); 2570 return Collections.emptyMap(); 2571 } 2572 return mWifiThreadRunner.call( 2573 () -> mPasspointManager.getAllMatchingPasspointProfilesForScanResults(scanResults), 2574 Collections.emptyMap()); 2575 } 2576 2577 /** 2578 * Returns list of OSU (Online Sign-Up) providers associated with the given list of ScanResult. 2579 * 2580 * @param scanResults a list of ScanResult that has Passpoint APs. 2581 * @return Map that consists of {@link OsuProvider} and a matching list of {@link ScanResult}. 2582 */ 2583 @Override getMatchingOsuProviders( List<ScanResult> scanResults)2584 public Map<OsuProvider, List<ScanResult>> getMatchingOsuProviders( 2585 List<ScanResult> scanResults) { 2586 if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { 2587 throw new SecurityException(TAG + ": Permission denied"); 2588 } 2589 if (isVerboseLoggingEnabled()) { 2590 mLog.info("getMatchingOsuProviders uid=%").c(Binder.getCallingUid()).flush(); 2591 } 2592 2593 if (!ScanResultUtil.validateScanResultList(scanResults)) { 2594 Log.w(TAG, "Attempt to retrieve OsuProviders with invalid scanResult List"); 2595 return Collections.emptyMap(); 2596 } 2597 return mWifiThreadRunner.call( 2598 () -> mPasspointManager.getMatchingOsuProviders(scanResults), Collections.emptyMap()); 2599 } 2600 2601 /** 2602 * Returns the matching Passpoint configurations for given OSU(Online Sign-Up) providers. 2603 * 2604 * @param osuProviders a list of {@link OsuProvider} 2605 * @return Map that consists of {@link OsuProvider} and matching {@link PasspointConfiguration}. 2606 */ 2607 @Override getMatchingPasspointConfigsForOsuProviders( List<OsuProvider> osuProviders)2608 public Map<OsuProvider, PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders( 2609 List<OsuProvider> osuProviders) { 2610 if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { 2611 throw new SecurityException(TAG + ": Permission denied"); 2612 } 2613 if (isVerboseLoggingEnabled()) { 2614 mLog.info("getMatchingPasspointConfigsForOsuProviders uid=%").c( 2615 Binder.getCallingUid()).flush(); 2616 } 2617 if (osuProviders == null) { 2618 Log.e(TAG, "Attempt to retrieve Passpoint configuration with null osuProviders"); 2619 return new HashMap<>(); 2620 } 2621 return mWifiThreadRunner.call( 2622 () -> mPasspointManager.getMatchingPasspointConfigsForOsuProviders(osuProviders), 2623 Collections.emptyMap()); 2624 } 2625 2626 /** 2627 * Returns the corresponding wifi configurations for given FQDN (Fully Qualified Domain Name) 2628 * list. 2629 * 2630 * An empty list will be returned when no match is found. 2631 * 2632 * @param fqdnList a list of FQDN 2633 * @return List of {@link WifiConfiguration} converted from {@link PasspointProvider} 2634 */ 2635 @Override getWifiConfigsForPasspointProfiles(List<String> fqdnList)2636 public List<WifiConfiguration> getWifiConfigsForPasspointProfiles(List<String> fqdnList) { 2637 if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { 2638 throw new SecurityException(TAG + ": Permission denied"); 2639 } 2640 if (isVerboseLoggingEnabled()) { 2641 mLog.info("getWifiConfigsForPasspointProfiles uid=%").c( 2642 Binder.getCallingUid()).flush(); 2643 } 2644 if (fqdnList == null) { 2645 Log.e(TAG, "Attempt to retrieve WifiConfiguration with null fqdn List"); 2646 return new ArrayList<>(); 2647 } 2648 return mWifiThreadRunner.call( 2649 () -> mPasspointManager.getWifiConfigsForPasspointProfiles(fqdnList), 2650 Collections.emptyList()); 2651 } 2652 2653 /** 2654 * Returns a list of Wifi configurations for matched available WifiNetworkSuggestion 2655 * corresponding to the given scan results. 2656 * 2657 * An empty list will be returned when no match is found or all matched suggestions is not 2658 * available(not allow user manually connect, user not approved or open network). 2659 * 2660 * @param scanResults a list of {@link ScanResult}. 2661 * @return a list of {@link WifiConfiguration} from matched {@link WifiNetworkSuggestion}. 2662 */ 2663 @Override getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( List<ScanResult> scanResults)2664 public List<WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( 2665 List<ScanResult> scanResults) { 2666 if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { 2667 throw new SecurityException(TAG + ": Permission denied"); 2668 } 2669 if (isVerboseLoggingEnabled()) { 2670 mLog.info("getWifiConfigsForMatchedNetworkSuggestions uid=%").c( 2671 Binder.getCallingUid()).flush(); 2672 } 2673 if (!ScanResultUtil.validateScanResultList(scanResults)) { 2674 Log.w(TAG, "Attempt to retrieve WifiConfiguration with invalid scanResult List"); 2675 return new ArrayList<>(); 2676 } 2677 return mWifiThreadRunner.call( 2678 () -> mWifiNetworkSuggestionsManager 2679 .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(scanResults), 2680 Collections.emptyList()); 2681 } 2682 2683 /** 2684 * see {@link WifiManager#addNetworkPrivileged(WifiConfiguration)} 2685 * @return WifiManager.AddNetworkResult Object. 2686 */ 2687 @Override addOrUpdateNetworkPrivileged( WifiConfiguration config, String packageName)2688 public @NonNull WifiManager.AddNetworkResult addOrUpdateNetworkPrivileged( 2689 WifiConfiguration config, String packageName) { 2690 int pid = Binder.getCallingPid(); 2691 int uid = Binder.getCallingUid(); 2692 mWifiPermissionsUtil.checkPackage(uid, packageName); 2693 boolean hasPermission = isPrivileged(pid, uid) 2694 || isDeviceOrProfileOwner(uid, packageName) 2695 || mWifiPermissionsUtil.isSystem(packageName, uid); 2696 if (!hasPermission) { 2697 throw new SecurityException("Caller is not a device owner, profile owner, system app," 2698 + " or privileged app"); 2699 } 2700 if (config != null) { 2701 config.networkId = removeSecurityTypeFromNetworkId(config.networkId); 2702 } 2703 return addOrUpdateNetworkInternal(config, packageName, uid); 2704 } 2705 2706 /** 2707 * see {@link android.net.wifi.WifiManager#addOrUpdateNetwork(WifiConfiguration)} 2708 * @return the supplicant-assigned identifier for the new or updated 2709 * network if the operation succeeds, or {@code -1} if it fails 2710 */ 2711 @Override addOrUpdateNetwork(WifiConfiguration config, String packageName)2712 public int addOrUpdateNetwork(WifiConfiguration config, String packageName) { 2713 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 2714 return -1; 2715 } 2716 int callingUid = Binder.getCallingUid(); 2717 if (!isTargetSdkLessThanQOrPrivileged( 2718 packageName, Binder.getCallingPid(), callingUid)) { 2719 mLog.info("addOrUpdateNetwork not allowed for uid=%") 2720 .c(Binder.getCallingUid()).flush(); 2721 return -1; 2722 } 2723 if (config != null) { 2724 config.networkId = removeSecurityTypeFromNetworkId(config.networkId); 2725 } 2726 mLog.info("addOrUpdateNetwork uid=%").c(Binder.getCallingUid()).flush(); 2727 return addOrUpdateNetworkInternal(config, packageName, callingUid).networkId; 2728 } 2729 addOrUpdateNetworkInternal(WifiConfiguration config, String packageName, int callingUid)2730 private @NonNull AddNetworkResult addOrUpdateNetworkInternal(WifiConfiguration config, 2731 String packageName, int callingUid) { 2732 if (config == null) { 2733 Log.e(TAG, "bad network configuration"); 2734 return new AddNetworkResult( 2735 AddNetworkResult.STATUS_INVALID_CONFIGURATION, -1); 2736 } 2737 mWifiMetrics.incrementNumAddOrUpdateNetworkCalls(); 2738 2739 // Previously, this API is overloaded for installing Passpoint profiles. Now 2740 // that we have a dedicated API for doing it, redirect the call to the dedicated API. 2741 if (config.isPasspoint()) { 2742 PasspointConfiguration passpointConfig = 2743 PasspointProvider.convertFromWifiConfig(config); 2744 if (passpointConfig == null || passpointConfig.getCredential() == null) { 2745 Log.e(TAG, "Missing credential for Passpoint profile"); 2746 return new AddNetworkResult( 2747 AddNetworkResult.STATUS_ADD_PASSPOINT_FAILURE, -1); 2748 } 2749 2750 // Copy over certificates and keys. 2751 X509Certificate[] x509Certificates = null; 2752 if (config.enterpriseConfig.getCaCertificate() != null) { 2753 x509Certificates = 2754 new X509Certificate[]{config.enterpriseConfig.getCaCertificate()}; 2755 } 2756 passpointConfig.getCredential().setCaCertificates(x509Certificates); 2757 passpointConfig.getCredential().setClientCertificateChain( 2758 config.enterpriseConfig.getClientCertificateChain()); 2759 passpointConfig.getCredential().setClientPrivateKey( 2760 config.enterpriseConfig.getClientPrivateKey()); 2761 if (!addOrUpdatePasspointConfiguration(passpointConfig, packageName)) { 2762 Log.e(TAG, "Failed to add Passpoint profile"); 2763 return new AddNetworkResult( 2764 AddNetworkResult.STATUS_ADD_PASSPOINT_FAILURE, -1); 2765 } 2766 // There is no network ID associated with a Passpoint profile. 2767 return new AddNetworkResult(AddNetworkResult.STATUS_SUCCESS, 0); 2768 } 2769 2770 if (config.isEnterprise() && config.enterpriseConfig.isEapMethodServerCertUsed() 2771 && !config.enterpriseConfig.isMandatoryParameterSetForServerCertValidation()) { 2772 if (!(mContext.getResources().getBoolean( 2773 R.bool.config_wifiAllowInsecureEnterpriseConfigurationsForSettingsAndSUW) 2774 && isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid()))) { 2775 Log.e(TAG, "Enterprise network configuration is missing either a Root CA " 2776 + "or a domain name"); 2777 return new AddNetworkResult( 2778 AddNetworkResult.STATUS_INVALID_CONFIGURATION_ENTERPRISE, -1); 2779 } 2780 Log.w(TAG, "Insecure Enterprise network " + config.SSID 2781 + " configured by Settings/SUW"); 2782 } 2783 2784 Log.i("addOrUpdateNetworkInternal", " uid = " + Binder.getCallingUid() 2785 + " SSID " + config.SSID 2786 + " nid=" + config.networkId); 2787 // TODO: b/171981339, add more detailed failure reason into 2788 // WifiConfigManager.NetworkUpdateResult, and plumb that reason up. 2789 int networkId = mWifiThreadRunner.call( 2790 () -> mWifiConfigManager.addOrUpdateNetwork(config, callingUid, packageName) 2791 .getNetworkId(), 2792 WifiConfiguration.INVALID_NETWORK_ID); 2793 if (networkId >= 0) { 2794 return new AddNetworkResult(AddNetworkResult.STATUS_SUCCESS, addSecurityTypeToNetworkId( 2795 networkId, config.getDefaultSecurityParams().getSecurityType())); 2796 } 2797 return new AddNetworkResult( 2798 AddNetworkResult.STATUS_ADD_WIFI_CONFIG_FAILURE, -1); 2799 } 2800 verifyCert(X509Certificate caCert)2801 public static void verifyCert(X509Certificate caCert) 2802 throws GeneralSecurityException, IOException { 2803 CertificateFactory factory = CertificateFactory.getInstance("X.509"); 2804 CertPathValidator validator = 2805 CertPathValidator.getInstance(CertPathValidator.getDefaultType()); 2806 CertPath path = factory.generateCertPath( 2807 Arrays.asList(caCert)); 2808 KeyStore ks = KeyStore.getInstance("AndroidCAStore"); 2809 ks.load(null, null); 2810 PKIXParameters params = new PKIXParameters(ks); 2811 params.setRevocationEnabled(false); 2812 validator.validate(path, params); 2813 } 2814 2815 /** 2816 * See {@link android.net.wifi.WifiManager#removeNetwork(int)} 2817 * @param netId the integer that identifies the network configuration 2818 * to the supplicant 2819 * @return {@code true} if the operation succeeded 2820 */ 2821 @Override removeNetwork(int netId, String packageName)2822 public boolean removeNetwork(int netId, String packageName) { 2823 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 2824 return false; 2825 } 2826 if (!isTargetSdkLessThanQOrPrivileged( 2827 packageName, Binder.getCallingPid(), Binder.getCallingUid())) { 2828 mLog.info("removeNetwork not allowed for uid=%") 2829 .c(Binder.getCallingUid()).flush(); 2830 return false; 2831 } 2832 final int internalNetId = removeSecurityTypeFromNetworkId(netId); 2833 int callingUid = Binder.getCallingUid(); 2834 mLog.info("removeNetwork uid=%").c(callingUid).flush(); 2835 return mWifiThreadRunner.call( 2836 () -> mWifiConfigManager.removeNetwork(internalNetId, callingUid, packageName), 2837 false); 2838 } 2839 2840 @Override removeNonCallerConfiguredNetworks(String packageName)2841 public boolean removeNonCallerConfiguredNetworks(String packageName) { 2842 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 2843 throw new SecurityException("Caller does not hold CHANGE_WIFI_STATE permission"); 2844 } 2845 final int callingUid = Binder.getCallingUid(); 2846 if (!mWifiPermissionsUtil.isDeviceOwner(callingUid, packageName)) { 2847 throw new SecurityException("Caller is not device owner"); 2848 } 2849 return mWifiThreadRunner.call( 2850 () -> mWifiConfigManager.removeNonCallerConfiguredNetwork(callingUid), false); 2851 } 2852 2853 /** 2854 * Trigger a connect request and wait for the callback to return status. 2855 * This preserves the legacy connect API behavior, i.e. {@link WifiManager#enableNetwork( 2856 * int, true)} 2857 * @return 2858 */ triggerConnectAndReturnStatus(int netId, int callingUid)2859 private boolean triggerConnectAndReturnStatus(int netId, int callingUid) { 2860 final CountDownLatch countDownLatch = new CountDownLatch(1); 2861 final Mutable<Boolean> success = new Mutable<>(false); 2862 IActionListener.Stub connectListener = new IActionListener.Stub() { 2863 @Override 2864 public void onSuccess() { 2865 success.value = true; 2866 countDownLatch.countDown(); 2867 } 2868 @Override 2869 public void onFailure(int reason) { 2870 success.value = false; 2871 countDownLatch.countDown(); 2872 } 2873 }; 2874 mWifiThreadRunner.post(() -> 2875 mMakeBeforeBreakManager.stopAllSecondaryTransientClientModeManagers(() -> 2876 mConnectHelper.connectToNetwork( 2877 new NetworkUpdateResult(netId), 2878 new ActionListenerWrapper(connectListener), 2879 callingUid) 2880 ) 2881 ); 2882 // now wait for response. 2883 try { 2884 countDownLatch.await(RUN_WITH_SCISSORS_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 2885 } catch (InterruptedException e) { 2886 Log.e(TAG, "Failed to retrieve connect status"); 2887 } 2888 return success.value; 2889 } 2890 2891 /** 2892 * See {@link android.net.wifi.WifiManager#enableNetwork(int, boolean)} 2893 * @param netId the integer that identifies the network configuration 2894 * to the supplicant 2895 * @param disableOthers if true, disable all other networks. 2896 * @return {@code true} if the operation succeeded 2897 */ 2898 @Override enableNetwork(int netId, boolean disableOthers, String packageName)2899 public boolean enableNetwork(int netId, boolean disableOthers, String packageName) { 2900 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 2901 return false; 2902 } 2903 if (!isTargetSdkLessThanQOrPrivileged( 2904 packageName, Binder.getCallingPid(), Binder.getCallingUid())) { 2905 mLog.info("enableNetwork not allowed for uid=%") 2906 .c(Binder.getCallingUid()).flush(); 2907 return false; 2908 } 2909 final int internalNetId = removeSecurityTypeFromNetworkId(netId); 2910 int callingUid = Binder.getCallingUid(); 2911 // TODO b/33807876 Log netId 2912 mLog.info("enableNetwork uid=% disableOthers=%") 2913 .c(callingUid) 2914 .c(disableOthers).flush(); 2915 2916 mWifiMetrics.incrementNumEnableNetworkCalls(); 2917 if (disableOthers) { 2918 return triggerConnectAndReturnStatus(internalNetId, callingUid); 2919 } else { 2920 return mWifiThreadRunner.call( 2921 () -> mWifiConfigManager.enableNetwork( 2922 internalNetId, false, callingUid, packageName), 2923 false); 2924 } 2925 } 2926 2927 /** 2928 * See {@link android.net.wifi.WifiManager#disableNetwork(int)} 2929 * @param netId the integer that identifies the network configuration 2930 * to the supplicant 2931 * @return {@code true} if the operation succeeded 2932 */ 2933 @Override disableNetwork(int netId, String packageName)2934 public boolean disableNetwork(int netId, String packageName) { 2935 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 2936 return false; 2937 } 2938 if (!isTargetSdkLessThanQOrPrivileged( 2939 packageName, Binder.getCallingPid(), Binder.getCallingUid())) { 2940 mLog.info("disableNetwork not allowed for uid=%") 2941 .c(Binder.getCallingUid()).flush(); 2942 return false; 2943 } 2944 final int internalNetId = removeSecurityTypeFromNetworkId(netId); 2945 int callingUid = Binder.getCallingUid(); 2946 mLog.info("disableNetwork uid=%").c(callingUid).flush(); 2947 return mWifiThreadRunner.call( 2948 () -> mWifiConfigManager.disableNetwork( 2949 internalNetId, callingUid, packageName), false); 2950 } 2951 2952 /** 2953 * See 2954 * {@link android.net.wifi.WifiManager#startRestrictingAutoJoinToSubscriptionId(int)} 2955 * @param subscriptionId the subscription ID of the carrier whose merged wifi networks won't be 2956 * disabled. 2957 */ 2958 @Override 2959 @RequiresApi(Build.VERSION_CODES.S) startRestrictingAutoJoinToSubscriptionId(int subscriptionId)2960 public void startRestrictingAutoJoinToSubscriptionId(int subscriptionId) { 2961 if (!SdkLevel.isAtLeastS()) { 2962 throw new UnsupportedOperationException(); 2963 } 2964 if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { 2965 throw new SecurityException(TAG + ": Permission denied"); 2966 } 2967 2968 mLog.info("startRestrictingAutoJoinToSubscriptionId=% uid=%").c(subscriptionId) 2969 .c(Binder.getCallingUid()).flush(); 2970 mWifiThreadRunner.post(() -> { 2971 mWifiConfigManager 2972 .startRestrictingAutoJoinToSubscriptionId(subscriptionId); 2973 // always disconnect here and rely on auto-join to find the appropriate carrier network 2974 // to join. Even if we are currently connected to the carrier-merged wifi, it's still 2975 // better to disconnect here because it's possible that carrier wifi offload is 2976 // disabled. 2977 mActiveModeWarden.getPrimaryClientModeManager().disconnect(); 2978 }); 2979 } 2980 2981 /** 2982 * See {@link android.net.wifi.WifiManager#stopRestrictingAutoJoinToSubscriptionId()} 2983 */ 2984 @Override 2985 @RequiresApi(Build.VERSION_CODES.S) stopRestrictingAutoJoinToSubscriptionId()2986 public void stopRestrictingAutoJoinToSubscriptionId() { 2987 if (!SdkLevel.isAtLeastS()) { 2988 throw new UnsupportedOperationException(); 2989 } 2990 if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { 2991 throw new SecurityException(TAG + ": Permission denied"); 2992 } 2993 2994 mLog.info("stopRestrictingAutoJoinToSubscriptionId uid=%") 2995 .c(Binder.getCallingUid()).flush(); 2996 mWifiThreadRunner.post(() -> 2997 mWifiConfigManager.stopRestrictingAutoJoinToSubscriptionId()); 2998 } 2999 3000 /** 3001 * See {@link android.net.wifi.WifiManager#allowAutojoinGlobal(boolean)} 3002 * @param choice the OEM's choice to allow auto-join 3003 */ 3004 @Override allowAutojoinGlobal(boolean choice)3005 public void allowAutojoinGlobal(boolean choice) { 3006 enforceNetworkSettingsPermission(); 3007 3008 int callingUid = Binder.getCallingUid(); 3009 mLog.info("allowAutojoinGlobal=% uid=%").c(choice).c(callingUid).flush(); 3010 mWifiThreadRunner.post(() -> mWifiConnectivityManager.setAutoJoinEnabledExternal(choice)); 3011 mLastCallerInfoManager.put(LastCallerInfoManager.AUTOJOIN_GLOBAL, Process.myTid(), 3012 callingUid, Binder.getCallingPid(), "<unknown>", choice); 3013 } 3014 3015 /** 3016 * See {@link android.net.wifi.WifiManager#allowAutojoin(int, boolean)} 3017 * @param netId the integer that identifies the network configuration 3018 * @param choice the user's choice to allow auto-join 3019 */ 3020 @Override allowAutojoin(int netId, boolean choice)3021 public void allowAutojoin(int netId, boolean choice) { 3022 enforceNetworkSettingsPermission(); 3023 3024 final int internalNetId = removeSecurityTypeFromNetworkId(netId); 3025 int callingUid = Binder.getCallingUid(); 3026 mLog.info("allowAutojoin=% uid=%").c(choice).c(callingUid).flush(); 3027 mWifiThreadRunner.post(() -> { 3028 WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(internalNetId); 3029 if (config == null) { 3030 return; 3031 } 3032 if (config.fromWifiNetworkSpecifier) { 3033 Log.e(TAG, "Auto-join configuration is not permitted for NetworkSpecifier " 3034 + "connections: " + config); 3035 return; 3036 } 3037 if (config.isPasspoint() && !config.isEphemeral()) { 3038 Log.e(TAG, 3039 "Auto-join configuration for a non-ephemeral Passpoint network should be " 3040 + "configured using FQDN: " 3041 + config); 3042 return; 3043 } 3044 // If the network is a suggestion, store the auto-join configure to the 3045 // WifiNetWorkSuggestionsManager. 3046 if (config.fromWifiNetworkSuggestion) { 3047 if (!mWifiNetworkSuggestionsManager 3048 .allowNetworkSuggestionAutojoin(config, choice)) { 3049 return; 3050 } 3051 } 3052 // even for Suggestion, modify the current ephemeral configuration so that 3053 // existing configuration auto-connection is updated correctly 3054 if (choice != config.allowAutojoin) { 3055 mWifiConfigManager.allowAutojoin(internalNetId, choice); 3056 // do not log this metrics for passpoint networks again here since it's already 3057 // logged in PasspointManager. 3058 if (!config.isPasspoint()) { 3059 mWifiMetrics.logUserActionEvent(choice 3060 ? UserActionEvent.EVENT_CONFIGURE_AUTO_CONNECT_ON 3061 : UserActionEvent.EVENT_CONFIGURE_AUTO_CONNECT_OFF, internalNetId); 3062 } 3063 } 3064 }); 3065 } 3066 3067 /** 3068 * See {@link android.net.wifi.WifiManager#allowAutojoinPasspoint(String, boolean)} 3069 * @param fqdn the FQDN that identifies the passpoint configuration 3070 * @param enableAutojoin true to enable auto-join, false to disable 3071 */ 3072 @Override allowAutojoinPasspoint(String fqdn, boolean enableAutojoin)3073 public void allowAutojoinPasspoint(String fqdn, boolean enableAutojoin) { 3074 enforceNetworkSettingsPermission(); 3075 if (fqdn == null) { 3076 throw new IllegalArgumentException("FQDN cannot be null"); 3077 } 3078 3079 int callingUid = Binder.getCallingUid(); 3080 mLog.info("allowAutojoinPasspoint=% uid=%").c(enableAutojoin).c(callingUid).flush(); 3081 mWifiThreadRunner.post( 3082 () -> mPasspointManager.enableAutojoin(null, fqdn, enableAutojoin)); 3083 } 3084 3085 /** 3086 * See {@link android.net.wifi.WifiManager 3087 * #setMacRandomizationSettingPasspointEnabled(String, boolean)} 3088 * @param fqdn the FQDN that identifies the passpoint configuration 3089 * @param enable true to enable mac randomization, false to disable 3090 */ 3091 @Override setMacRandomizationSettingPasspointEnabled(String fqdn, boolean enable)3092 public void setMacRandomizationSettingPasspointEnabled(String fqdn, boolean enable) { 3093 enforceNetworkSettingsPermission(); 3094 if (fqdn == null) { 3095 throw new IllegalArgumentException("FQDN cannot be null"); 3096 } 3097 3098 int callingUid = Binder.getCallingUid(); 3099 mLog.info("setMacRandomizationSettingPasspointEnabled=% uid=%") 3100 .c(enable).c(callingUid).flush(); 3101 mWifiThreadRunner.post( 3102 () -> mPasspointManager.enableMacRandomization(fqdn, enable)); 3103 } 3104 3105 /** 3106 * See {@link android.net.wifi.WifiManager#setPasspointMeteredOverride(String, boolean)} 3107 * @param fqdn the FQDN that identifies the passpoint configuration 3108 * @param meteredOverride One of the values in {@link MeteredOverride} 3109 */ 3110 @Override setPasspointMeteredOverride(String fqdn, int meteredOverride)3111 public void setPasspointMeteredOverride(String fqdn, int meteredOverride) { 3112 enforceNetworkSettingsPermission(); 3113 if (fqdn == null) { 3114 throw new IllegalArgumentException("FQDN cannot be null"); 3115 } 3116 3117 int callingUid = Binder.getCallingUid(); 3118 mLog.info("setPasspointMeteredOverride=% uid=%") 3119 .c(meteredOverride).c(callingUid).flush(); 3120 mWifiThreadRunner.post( 3121 () -> mPasspointManager.setMeteredOverride(fqdn, meteredOverride)); 3122 } 3123 3124 /** 3125 * Provides backward compatibility for apps using 3126 * {@link WifiManager#getConnectionInfo()}, {@link WifiManager#getDhcpInfo()} when a 3127 * secondary STA is created as a result of a request from their app (peer to peer 3128 * WifiNetworkSpecifier request or oem paid/private suggestion). 3129 */ getClientModeManagerIfSecondaryCmmRequestedByCallerPresent( int callingUid, @NonNull String callingPackageName)3130 private ClientModeManager getClientModeManagerIfSecondaryCmmRequestedByCallerPresent( 3131 int callingUid, @NonNull String callingPackageName) { 3132 List<ConcreteClientModeManager> secondaryCmms = 3133 mActiveModeWarden.getClientModeManagersInRoles( 3134 ROLE_CLIENT_LOCAL_ONLY, ROLE_CLIENT_SECONDARY_LONG_LIVED); 3135 for (ConcreteClientModeManager cmm : secondaryCmms) { 3136 WorkSource reqWs = cmm.getRequestorWs(); 3137 // If there are more than 1 secondary CMM for same app, return any one (should not 3138 // happen currently since we don't support 3 STA's concurrently). 3139 if (reqWs.equals(new WorkSource(callingUid, callingPackageName))) { 3140 mLog.info("getConnectionInfo providing secondary CMM info").flush(); 3141 return cmm; 3142 } 3143 } 3144 // No secondary CMM's created for the app, return primary CMM. 3145 return mActiveModeWarden.getPrimaryClientModeManager(); 3146 } 3147 3148 /** 3149 * See {@link android.net.wifi.WifiManager#getConnectionInfo()} 3150 * @return the Wi-Fi information, contained in {@link WifiInfo}. 3151 */ 3152 @Override getConnectionInfo(String callingPackage, String callingFeatureId)3153 public WifiInfo getConnectionInfo(String callingPackage, String callingFeatureId) { 3154 enforceAccessPermission(); 3155 int uid = Binder.getCallingUid(); 3156 if (isVerboseLoggingEnabled()) { 3157 mLog.info("getConnectionInfo uid=%").c(uid).flush(); 3158 } 3159 long ident = Binder.clearCallingIdentity(); 3160 try { 3161 WifiInfo wifiInfo = mWifiThreadRunner.call( 3162 () -> getClientModeManagerIfSecondaryCmmRequestedByCallerPresent( 3163 uid, callingPackage) 3164 .syncRequestConnectionInfo(), new WifiInfo()); 3165 long redactions = wifiInfo.getApplicableRedactions(); 3166 if (mWifiPermissionsUtil.checkLocalMacAddressPermission(uid)) { 3167 if (isVerboseLoggingEnabled()) { 3168 Log.v(TAG, "Clearing REDACT_FOR_LOCAL_MAC_ADDRESS for " + callingPackage 3169 + "(uid=" + uid + ")"); 3170 } 3171 redactions &= ~NetworkCapabilities.REDACT_FOR_LOCAL_MAC_ADDRESS; 3172 } 3173 if (mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { 3174 if (isVerboseLoggingEnabled()) { 3175 Log.v(TAG, "Clearing REDACT_FOR_NETWORK_SETTINGS for " + callingPackage 3176 + "(uid=" + uid + ")"); 3177 } 3178 redactions &= ~NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS; 3179 } 3180 try { 3181 if (isVerboseLoggingEnabled()) { 3182 Log.v(TAG, "Clearing REDACT_FOR_ACCESS_FINE_LOCATION for " + callingPackage 3183 + "(uid=" + uid + ")"); 3184 } 3185 mWifiPermissionsUtil.enforceCanAccessScanResults(callingPackage, callingFeatureId, 3186 uid, null); 3187 redactions &= ~NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION; 3188 } catch (SecurityException ignored) { 3189 if (isVerboseLoggingEnabled()) { 3190 Log.v(TAG, "Keeping REDACT_FOR_ACCESS_FINE_LOCATION:" + ignored); 3191 } 3192 } 3193 WifiInfo wifiInfoCopy = wifiInfo.makeCopy(redactions); 3194 wifiInfoCopy.setNetworkId(addSecurityTypeToNetworkId(wifiInfoCopy.getNetworkId(), 3195 convertWifiInfoSecurityTypeToWifiConfiguration( 3196 wifiInfoCopy.getCurrentSecurityType()))); 3197 return wifiInfoCopy; 3198 } finally { 3199 Binder.restoreCallingIdentity(ident); 3200 } 3201 } 3202 3203 /** 3204 * Return the results of the most recent access point scan, in the form of 3205 * a list of {@link ScanResult} objects. 3206 * @return the list of results 3207 */ 3208 @Override getScanResults(String callingPackage, String callingFeatureId)3209 public List<ScanResult> getScanResults(String callingPackage, String callingFeatureId) { 3210 enforceAccessPermission(); 3211 int uid = Binder.getCallingUid(); 3212 long ident = Binder.clearCallingIdentity(); 3213 if (isVerboseLoggingEnabled()) { 3214 mLog.info("getScanResults uid=%").c(uid).flush(); 3215 } 3216 try { 3217 mWifiPermissionsUtil.enforceCanAccessScanResults(callingPackage, callingFeatureId, 3218 uid, null); 3219 List<ScanResult> scanResults = mWifiThreadRunner.call( 3220 mScanRequestProxy::getScanResults, Collections.emptyList()); 3221 return scanResults; 3222 } catch (SecurityException e) { 3223 Log.w(TAG, "Permission violation - getScanResults not allowed for uid=" 3224 + uid + ", packageName=" + callingPackage + ", reason=" + e); 3225 return new ArrayList<>(); 3226 } finally { 3227 Binder.restoreCallingIdentity(ident); 3228 } 3229 } 3230 3231 /** 3232 * Return the filtered ScanResults which may be authenticated by the suggested network 3233 * configurations. 3234 * @return The map of {@link WifiNetworkSuggestion} and the list of {@link ScanResult} which 3235 * may be authenticated by the corresponding network configuration. 3236 */ 3237 @Override 3238 @NonNull getMatchingScanResults( @onNull List<WifiNetworkSuggestion> networkSuggestions, @Nullable List<ScanResult> scanResults, String callingPackage, String callingFeatureId)3239 public Map<WifiNetworkSuggestion, List<ScanResult>> getMatchingScanResults( 3240 @NonNull List<WifiNetworkSuggestion> networkSuggestions, 3241 @Nullable List<ScanResult> scanResults, 3242 String callingPackage, String callingFeatureId) { 3243 enforceAccessPermission(); 3244 int uid = Binder.getCallingUid(); 3245 long ident = Binder.clearCallingIdentity(); 3246 try { 3247 mWifiPermissionsUtil.enforceCanAccessScanResults(callingPackage, callingFeatureId, 3248 uid, null); 3249 3250 return mWifiThreadRunner.call( 3251 () -> { 3252 if (!ScanResultUtil.validateScanResultList(scanResults)) { 3253 return mWifiNetworkSuggestionsManager.getMatchingScanResults( 3254 networkSuggestions, mScanRequestProxy.getScanResults()); 3255 } else { 3256 return mWifiNetworkSuggestionsManager.getMatchingScanResults( 3257 networkSuggestions, scanResults); 3258 } 3259 }, 3260 Collections.emptyMap()); 3261 } catch (SecurityException e) { 3262 Log.w(TAG, "Permission violation - getMatchingScanResults not allowed for uid=" 3263 + uid + ", packageName=" + callingPackage + ", reason + e"); 3264 } finally { 3265 Binder.restoreCallingIdentity(ident); 3266 } 3267 3268 return Collections.emptyMap(); 3269 } 3270 3271 /** 3272 * Add or update a Passpoint configuration. 3273 * 3274 * @param config The Passpoint configuration to be added 3275 * @return true on success or false on failure 3276 */ 3277 @Override 3278 public boolean addOrUpdatePasspointConfiguration( 3279 PasspointConfiguration config, String packageName) { 3280 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 3281 return false; 3282 } 3283 int callingUid = Binder.getCallingUid(); 3284 if (!isTargetSdkLessThanROrPrivileged( 3285 packageName, Binder.getCallingPid(), callingUid)) { 3286 mLog.info("addOrUpdatePasspointConfiguration not allowed for uid=%") 3287 .c(Binder.getCallingUid()).flush(); 3288 return false; 3289 } 3290 mLog.info("addorUpdatePasspointConfiguration uid=%").c(callingUid).flush(); 3291 return mWifiThreadRunner.call( 3292 () -> mPasspointManager.addOrUpdateProvider(config, callingUid, packageName, 3293 false, true), false); 3294 } 3295 3296 /** 3297 * Remove the Passpoint configuration identified by its FQDN (Fully Qualified Domain Name). 3298 * 3299 * @param fqdn The FQDN of the Passpoint configuration to be removed 3300 * @return true on success or false on failure 3301 */ 3302 @Override 3303 public boolean removePasspointConfiguration(String fqdn, String packageName) { 3304 return removePasspointConfigurationInternal(fqdn, null); 3305 } 3306 3307 /** 3308 * Remove a Passpoint profile based on either FQDN (multiple matching profiles) or a unique 3309 * identifier (one matching profile). 3310 * 3311 * @param fqdn The FQDN of the Passpoint configuration to be removed 3312 * @param uniqueId The unique identifier of the Passpoint configuration to be removed 3313 * @return true on success or false on failure 3314 */ 3315 private boolean removePasspointConfigurationInternal(String fqdn, String uniqueId) { 3316 final int uid = Binder.getCallingUid(); 3317 boolean privileged = false; 3318 if (mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) 3319 || mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(uid)) { 3320 privileged = true; 3321 } 3322 mLog.info("removePasspointConfigurationInternal uid=%").c(Binder.getCallingUid()).flush(); 3323 final boolean privilegedFinal = privileged; 3324 return mWifiThreadRunner.call( 3325 () -> mPasspointManager.removeProvider(uid, privilegedFinal, uniqueId, fqdn), 3326 false); 3327 } 3328 3329 /** 3330 * Return the list of the installed Passpoint configurations. 3331 * 3332 * An empty list will be returned when no configuration is installed. 3333 * @param packageName String name of the calling package 3334 * @return A list of {@link PasspointConfiguration}. 3335 */ 3336 @Override 3337 public List<PasspointConfiguration> getPasspointConfigurations(String packageName) { 3338 final int uid = Binder.getCallingUid(); 3339 boolean privileged = false; 3340 if (mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) 3341 || mWifiPermissionsUtil.checkNetworkSetupWizardPermission(uid)) { 3342 privileged = true; 3343 } 3344 if (isVerboseLoggingEnabled()) { 3345 mLog.info("getPasspointConfigurations uid=%").c(Binder.getCallingUid()).flush(); 3346 } 3347 final boolean privilegedFinal = privileged; 3348 return mWifiThreadRunner.call( 3349 () -> mPasspointManager.getProviderConfigs(uid, privilegedFinal), 3350 Collections.emptyList()); 3351 } 3352 3353 /** 3354 * Query for a Hotspot 2.0 release 2 OSU icon 3355 * @param bssid The BSSID of the AP 3356 * @param fileName Icon file name 3357 */ 3358 @Override 3359 public void queryPasspointIcon(long bssid, String fileName) { 3360 enforceAccessPermission(); 3361 mLog.info("queryPasspointIcon uid=%").c(Binder.getCallingUid()).flush(); 3362 mWifiThreadRunner.post(() -> { 3363 mActiveModeWarden.getPrimaryClientModeManager().syncQueryPasspointIcon(bssid, fileName); 3364 }); 3365 } 3366 3367 /** 3368 * Match the currently associated network against the SP matching the given FQDN 3369 * @param fqdn FQDN of the SP 3370 * @return ordinal [HomeProvider, RoamingProvider, Incomplete, None, Declined] 3371 */ 3372 @Override 3373 public int matchProviderWithCurrentNetwork(String fqdn) { 3374 mLog.info("matchProviderWithCurrentNetwork uid=%").c(Binder.getCallingUid()).flush(); 3375 return 0; 3376 } 3377 3378 /** 3379 * Get the country code 3380 * @return Get the best choice country code for wifi, regardless of if it was set or 3381 * not. 3382 * Returns null when there is no country code available. 3383 */ 3384 @Override 3385 public String getCountryCode() { 3386 enforceNetworkSettingsPermission(); 3387 if (isVerboseLoggingEnabled()) { 3388 mLog.info("getCountryCode uid=%").c(Binder.getCallingUid()).flush(); 3389 } 3390 return mCountryCode.getCountryCode(); 3391 } 3392 3393 /** 3394 * Set the Wifi country code. This call will override the country code set by telephony. 3395 * @param countryCode A 2-Character alphanumeric country code. 3396 * 3397 */ 3398 @RequiresApi(Build.VERSION_CODES.S) 3399 @Override 3400 public void setOverrideCountryCode(@NonNull String countryCode) { 3401 if (!SdkLevel.isAtLeastS()) { 3402 throw new UnsupportedOperationException(); 3403 } 3404 mContext.enforceCallingOrSelfPermission( 3405 Manifest.permission.MANAGE_WIFI_COUNTRY_CODE, "WifiService"); 3406 if (!WifiCountryCode.isValid(countryCode)) { 3407 throw new IllegalArgumentException("Country code must be a 2-Character alphanumeric" 3408 + " code. But got countryCode " + countryCode 3409 + " instead"); 3410 } 3411 if (isVerboseLoggingEnabled()) { 3412 mLog.info("setOverrideCountryCode uid=% countryCode=%") 3413 .c(Binder.getCallingUid()).c(countryCode).flush(); 3414 } 3415 // Post operation to handler thread 3416 mWifiThreadRunner.post(() -> mCountryCode.setOverrideCountryCode(countryCode)); 3417 } 3418 3419 /** 3420 * Clear the country code previously set through setOverrideCountryCode method. 3421 * 3422 */ 3423 @RequiresApi(Build.VERSION_CODES.S) 3424 @Override 3425 public void clearOverrideCountryCode() { 3426 if (!SdkLevel.isAtLeastS()) { 3427 throw new UnsupportedOperationException(); 3428 } 3429 mContext.enforceCallingOrSelfPermission( 3430 Manifest.permission.MANAGE_WIFI_COUNTRY_CODE, "WifiService"); 3431 if (isVerboseLoggingEnabled()) { 3432 mLog.info("clearCountryCode uid=%").c(Binder.getCallingUid()).flush(); 3433 } 3434 // Post operation to handler thread 3435 mWifiThreadRunner.post(() -> mCountryCode.clearOverrideCountryCode()); 3436 } 3437 3438 /** 3439 * Change the default country code previously set from ro.boot.wificountrycode. 3440 * @param countryCode A 2-Character alphanumeric country code. 3441 * 3442 */ 3443 @RequiresApi(Build.VERSION_CODES.S) 3444 @Override 3445 public void setDefaultCountryCode(@NonNull String countryCode) { 3446 if (!SdkLevel.isAtLeastS()) { 3447 throw new UnsupportedOperationException(); 3448 } 3449 mContext.enforceCallingOrSelfPermission( 3450 Manifest.permission.MANAGE_WIFI_COUNTRY_CODE, "WifiService"); 3451 if (!WifiCountryCode.isValid(countryCode)) { 3452 throw new IllegalArgumentException("Country code must be a 2-Character alphanumeric" 3453 + " code. But got countryCode " + countryCode 3454 + " instead"); 3455 } 3456 if (isVerboseLoggingEnabled()) { 3457 mLog.info("setDefaultCountryCode uid=% countryCode=%") 3458 .c(Binder.getCallingUid()).c(countryCode).flush(); 3459 } 3460 // Post operation to handler thread 3461 mWifiThreadRunner.post(() -> mCountryCode.setDefaultCountryCode(countryCode)); 3462 } 3463 3464 @Override 3465 public boolean is24GHzBandSupported() { 3466 if (isVerboseLoggingEnabled()) { 3467 mLog.info("is24GHzBandSupported uid=%").c(Binder.getCallingUid()).flush(); 3468 } 3469 3470 return is24GhzBandSupportedInternal(); 3471 } 3472 3473 private boolean is24GhzBandSupportedInternal() { 3474 if (mContext.getResources().getBoolean(R.bool.config_wifi24ghzSupport)) { 3475 return true; 3476 } 3477 return mWifiThreadRunner.call( 3478 () -> mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_24_GHZ).length > 0, 3479 false); 3480 } 3481 3482 3483 @Override 3484 public boolean is5GHzBandSupported() { 3485 if (isVerboseLoggingEnabled()) { 3486 mLog.info("is5GHzBandSupported uid=%").c(Binder.getCallingUid()).flush(); 3487 } 3488 3489 return is5GhzBandSupportedInternal(); 3490 } 3491 3492 private boolean is5GhzBandSupportedInternal() { 3493 if (mContext.getResources().getBoolean(R.bool.config_wifi5ghzSupport)) { 3494 return true; 3495 } 3496 return mWifiThreadRunner.call( 3497 () -> mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ).length > 0, 3498 false); 3499 } 3500 3501 @Override 3502 public boolean is6GHzBandSupported() { 3503 if (isVerboseLoggingEnabled()) { 3504 mLog.info("is6GHzBandSupported uid=%").c(Binder.getCallingUid()).flush(); 3505 } 3506 3507 return is6GhzBandSupportedInternal(); 3508 } 3509 3510 private boolean is6GhzBandSupportedInternal() { 3511 if (mContext.getResources().getBoolean(R.bool.config_wifi6ghzSupport)) { 3512 return true; 3513 } 3514 return mWifiThreadRunner.call( 3515 () -> mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_6_GHZ).length > 0, 3516 false); 3517 } 3518 3519 @Override 3520 public boolean is60GHzBandSupported() { 3521 if (!SdkLevel.isAtLeastS()) { 3522 throw new UnsupportedOperationException(); 3523 } 3524 3525 if (isVerboseLoggingEnabled()) { 3526 mLog.info("is60GHzBandSupported uid=%").c(Binder.getCallingUid()).flush(); 3527 } 3528 3529 return is60GhzBandSupportedInternal(); 3530 } 3531 3532 private boolean is60GhzBandSupportedInternal() { 3533 if (mContext.getResources().getBoolean(R.bool.config_wifi60ghzSupport)) { 3534 return true; 3535 } 3536 return mWifiThreadRunner.call( 3537 () -> mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_60_GHZ).length > 0, 3538 false); 3539 } 3540 3541 @Override 3542 public boolean isWifiStandardSupported(@WifiStandard int standard) { 3543 return mWifiThreadRunner.call( 3544 () -> mActiveModeWarden.getPrimaryClientModeManager().isWifiStandardSupported( 3545 standard), false); 3546 } 3547 3548 /** 3549 * Return the DHCP-assigned addresses from the last successful DHCP request, 3550 * if any. 3551 * @return the DHCP information 3552 * @deprecated 3553 */ 3554 @Override 3555 public DhcpInfo getDhcpInfo(@NonNull String packageName) { 3556 enforceAccessPermission(); 3557 int callingUid = Binder.getCallingUid(); 3558 if (isVerboseLoggingEnabled()) { 3559 mLog.info("getDhcpInfo uid=%").c(callingUid).flush(); 3560 } 3561 DhcpResultsParcelable dhcpResults = mWifiThreadRunner.call( 3562 () -> getClientModeManagerIfSecondaryCmmRequestedByCallerPresent( 3563 callingUid, packageName) 3564 .syncGetDhcpResultsParcelable(), new DhcpResultsParcelable()); 3565 3566 DhcpInfo info = new DhcpInfo(); 3567 3568 if (dhcpResults.baseConfiguration != null) { 3569 if (dhcpResults.baseConfiguration.getIpAddress() != null 3570 && dhcpResults.baseConfiguration.getIpAddress().getAddress() 3571 instanceof Inet4Address) { 3572 info.ipAddress = Inet4AddressUtils.inet4AddressToIntHTL( 3573 (Inet4Address) dhcpResults.baseConfiguration.getIpAddress().getAddress()); 3574 } 3575 3576 if (dhcpResults.baseConfiguration.getGateway() != null) { 3577 info.gateway = Inet4AddressUtils.inet4AddressToIntHTL( 3578 (Inet4Address) dhcpResults.baseConfiguration.getGateway()); 3579 } 3580 3581 int dnsFound = 0; 3582 for (InetAddress dns : dhcpResults.baseConfiguration.getDnsServers()) { 3583 if (dns instanceof Inet4Address) { 3584 if (dnsFound == 0) { 3585 info.dns1 = Inet4AddressUtils.inet4AddressToIntHTL((Inet4Address) dns); 3586 } else { 3587 info.dns2 = Inet4AddressUtils.inet4AddressToIntHTL((Inet4Address) dns); 3588 } 3589 if (++dnsFound > 1) break; 3590 } 3591 } 3592 } 3593 String serverAddress = dhcpResults.serverAddress; 3594 if (serverAddress != null) { 3595 InetAddress serverInetAddress = InetAddresses.parseNumericAddress(serverAddress); 3596 info.serverAddress = 3597 Inet4AddressUtils.inet4AddressToIntHTL((Inet4Address) serverInetAddress); 3598 } 3599 info.leaseDuration = dhcpResults.leaseDuration; 3600 3601 return info; 3602 } 3603 3604 /** 3605 * enable TDLS for the local NIC to remote NIC 3606 * The APPs don't know the remote MAC address to identify NIC though, 3607 * so we need to do additional work to find it from remote IP address 3608 */ 3609 3610 private static class TdlsTaskParams { 3611 String mRemoteIpAddress; 3612 boolean mEnable; 3613 } 3614 3615 private class TdlsTask extends AsyncTask<TdlsTaskParams, Integer, Integer> { 3616 @Override 3617 protected Integer doInBackground(TdlsTaskParams... params) { 3618 3619 // Retrieve parameters for the call 3620 TdlsTaskParams param = params[0]; 3621 String remoteIpAddress = param.mRemoteIpAddress.trim(); 3622 boolean enable = param.mEnable; 3623 3624 // Get MAC address of Remote IP 3625 String macAddress = null; 3626 3627 try (BufferedReader reader = new BufferedReader(new FileReader("/proc/net/arp"))) { 3628 // Skip over the line bearing column titles 3629 reader.readLine(); 3630 3631 String line; 3632 while ((line = reader.readLine()) != null) { 3633 String[] tokens = line.split("[ ]+"); 3634 if (tokens.length < 6) { 3635 continue; 3636 } 3637 3638 // ARP column format is 3639 // Address HWType HWAddress Flags Mask IFace 3640 String ip = tokens[0]; 3641 String mac = tokens[3]; 3642 3643 if (remoteIpAddress.equals(ip)) { 3644 macAddress = mac; 3645 break; 3646 } 3647 } 3648 3649 if (macAddress == null) { 3650 Log.w(TAG, "Did not find remoteAddress {" + remoteIpAddress + "} in " 3651 + "/proc/net/arp"); 3652 } else { 3653 enableTdlsWithMacAddress(macAddress, enable); 3654 } 3655 3656 } catch (FileNotFoundException e) { 3657 Log.e(TAG, "Could not open /proc/net/arp to lookup mac address"); 3658 } catch (IOException e) { 3659 Log.e(TAG, "Could not read /proc/net/arp to lookup mac address"); 3660 } 3661 return 0; 3662 } 3663 } 3664 3665 @Override 3666 public void enableTdls(String remoteAddress, boolean enable) { 3667 if (remoteAddress == null) { 3668 throw new IllegalArgumentException("remoteAddress cannot be null"); 3669 } 3670 mLog.info("enableTdls uid=% enable=%").c(Binder.getCallingUid()).c(enable).flush(); 3671 TdlsTaskParams params = new TdlsTaskParams(); 3672 params.mRemoteIpAddress = remoteAddress; 3673 params.mEnable = enable; 3674 new TdlsTask().execute(params); 3675 } 3676 3677 3678 @Override 3679 public void enableTdlsWithMacAddress(String remoteMacAddress, boolean enable) { 3680 mLog.info("enableTdlsWithMacAddress uid=% enable=%") 3681 .c(Binder.getCallingUid()) 3682 .c(enable) 3683 .flush(); 3684 if (remoteMacAddress == null) { 3685 throw new IllegalArgumentException("remoteMacAddress cannot be null"); 3686 } 3687 mWifiThreadRunner.post(() -> 3688 mActiveModeWarden.getPrimaryClientModeManager().enableTdls( 3689 remoteMacAddress, enable)); 3690 } 3691 3692 /** 3693 * Temporarily disable a network, should be trigger when user disconnect a network 3694 */ 3695 @Override 3696 public void disableEphemeralNetwork(String network, String packageName) { 3697 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE, 3698 "WifiService"); 3699 if (!isPrivileged(Binder.getCallingPid(), Binder.getCallingUid())) { 3700 mLog.info("disableEphemeralNetwork not allowed for uid=%") 3701 .c(Binder.getCallingUid()).flush(); 3702 return; 3703 } 3704 mLog.info("disableEphemeralNetwork uid=%").c(Binder.getCallingUid()).flush(); 3705 mWifiThreadRunner.post(() -> mWifiConfigManager.userTemporarilyDisabledNetwork(network, 3706 Binder.getCallingUid())); 3707 } 3708 3709 private void removeAppStateInternal(int uid, @NonNull String pkgName) { 3710 ApplicationInfo ai = new ApplicationInfo(); 3711 ai.packageName = pkgName; 3712 ai.uid = uid; 3713 mWifiConfigManager.removeNetworksForApp(ai); 3714 mScanRequestProxy.clearScanRequestTimestampsForApp(pkgName, uid); 3715 3716 // Remove all suggestions from the package. 3717 mWifiNetworkSuggestionsManager.removeApp(pkgName); 3718 mWifiInjector.getWifiNetworkFactory().removeUserApprovedAccessPointsForApp( 3719 pkgName); 3720 3721 // Remove all Passpoint profiles from package. 3722 mWifiInjector.getPasspointManager().removePasspointProviderWithPackage( 3723 pkgName); 3724 } 3725 3726 private void registerForBroadcasts() { 3727 IntentFilter intentFilter = new IntentFilter(); 3728 intentFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED); 3729 intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); 3730 intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 3731 intentFilter.addDataScheme("package"); 3732 mContext.registerReceiver(new BroadcastReceiver() { 3733 @Override 3734 public void onReceive(Context context, Intent intent) { 3735 int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); 3736 Uri uri = intent.getData(); 3737 if (uid == -1 || uri == null) { 3738 Log.e(TAG, "Uid or Uri is missing for action:" + intent.getAction()); 3739 return; 3740 } 3741 String pkgName = uri.getSchemeSpecificPart(); 3742 PackageManager pm = context.getPackageManager(); 3743 PackageInfo packageInfo = null; 3744 try { 3745 packageInfo = pm.getPackageInfo(pkgName, 0); 3746 } catch (PackageManager.NameNotFoundException e) { 3747 Log.w(TAG, "Couldn't get PackageInfo for package:" + pkgName); 3748 } 3749 // If package is not removed or disabled, just ignore. 3750 if (packageInfo != null 3751 && packageInfo.applicationInfo != null 3752 && packageInfo.applicationInfo.enabled) { 3753 return; 3754 } 3755 Log.d(TAG, "Remove settings for package:" + pkgName); 3756 // Call the method in the main Wifi thread. 3757 mWifiThreadRunner.post(() -> { 3758 removeAppStateInternal(uid, pkgName); 3759 }); 3760 } 3761 }, intentFilter); 3762 } 3763 3764 private void registerForCarrierConfigChange() { 3765 IntentFilter filter = new IntentFilter(); 3766 filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); 3767 mContext.registerReceiver(new BroadcastReceiver() { 3768 @Override 3769 public void onReceive(Context context, Intent intent) { 3770 final int subId = SubscriptionManager.getActiveDataSubscriptionId(); 3771 // post operation to handler thread 3772 mWifiThreadRunner.post(() -> { 3773 Log.d(TAG, "ACTION_CARRIER_CONFIG_CHANGED, active subId: " + subId); 3774 mTetheredSoftApTracker.updateSoftApCapabilityWhenCarrierConfigChanged(subId); 3775 mActiveModeWarden.updateSoftApCapability( 3776 mTetheredSoftApTracker.getSoftApCapability()); 3777 }); 3778 } 3779 }, filter); 3780 3781 WifiPhoneStateListener phoneStateListener = new WifiPhoneStateListener( 3782 mWifiInjector.getWifiHandlerThread().getLooper()); 3783 3784 mContext.getSystemService(TelephonyManager.class).listen( 3785 phoneStateListener, PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE); 3786 } 3787 3788 @Override 3789 public int handleShellCommand(@NonNull ParcelFileDescriptor in, 3790 @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err, 3791 @NonNull String[] args) { 3792 WifiShellCommand shellCommand = new WifiShellCommand(mWifiInjector, this, mContext, 3793 mWifiGlobals, mWifiThreadRunner); 3794 return shellCommand.exec(this, in.getFileDescriptor(), out.getFileDescriptor(), 3795 err.getFileDescriptor(), args); 3796 } 3797 3798 private void updateWifiMetrics() { 3799 mWifiThreadRunner.run(() -> { 3800 mWifiMetrics.updateSavedNetworks( 3801 mWifiConfigManager.getSavedNetworks(Process.WIFI_UID)); 3802 mActiveModeWarden.updateMetrics(); 3803 mPasspointManager.updateMetrics(); 3804 }); 3805 boolean isEnhancedMacRandEnabled = mFrameworkFacade.getIntegerSetting(mContext, 3806 WifiConfigManager.ENHANCED_MAC_RANDOMIZATION_FEATURE_FORCE_ENABLE_FLAG, 0) == 1 3807 ? true : false; 3808 mWifiMetrics.setEnhancedMacRandomizationForceEnabled(isEnhancedMacRandEnabled); 3809 mWifiMetrics.setIsScanningAlwaysEnabled( 3810 mSettingsStore.isScanAlwaysAvailableToggleEnabled()); 3811 mWifiMetrics.setVerboseLoggingEnabled(isVerboseLoggingEnabled()); 3812 mWifiMetrics.setWifiWakeEnabled(mWifiInjector.getWakeupController().isEnabled()); 3813 } 3814 3815 @Override 3816 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 3817 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 3818 != PERMISSION_GRANTED) { 3819 pw.println("Permission Denial: can't dump WifiService from from pid=" 3820 + Binder.getCallingPid() 3821 + ", uid=" + Binder.getCallingUid()); 3822 return; 3823 } 3824 if (args != null && args.length > 0 && WifiMetrics.PROTO_DUMP_ARG.equals(args[0])) { 3825 // WifiMetrics proto bytes were requested. Dump only these. 3826 updateWifiMetrics(); 3827 mWifiMetrics.dump(fd, pw, args); 3828 } else if (args != null && args.length > 0 && IpClientUtil.DUMP_ARG.equals(args[0])) { 3829 // IpClient dump was requested. Pass it along and take no further action. 3830 String[] ipClientArgs = new String[args.length - 1]; 3831 System.arraycopy(args, 1, ipClientArgs, 0, ipClientArgs.length); 3832 mActiveModeWarden.getPrimaryClientModeManager().dumpIpClient(fd, pw, ipClientArgs); 3833 } else if (args != null && args.length > 0 && WifiScoreReport.DUMP_ARG.equals(args[0])) { 3834 mActiveModeWarden.getPrimaryClientModeManager().dumpWifiScoreReport(fd, pw, args); 3835 } else if (args != null && args.length > 0 && WifiScoreCard.DUMP_ARG.equals(args[0])) { 3836 WifiScoreCard wifiScoreCard = mWifiInjector.getWifiScoreCard(); 3837 String networkListBase64 = mWifiThreadRunner.call(() -> 3838 wifiScoreCard.getNetworkListBase64(true), ""); 3839 pw.println(networkListBase64); 3840 } else { 3841 pw.println("Verbose logging is " + (isVerboseLoggingEnabled() ? "on" : "off")); 3842 pw.println("Stay-awake conditions: " + 3843 mFacade.getIntegerSetting(mContext, 3844 Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0)); 3845 pw.println("mInIdleMode " + mInIdleMode); 3846 pw.println("mScanPending " + mScanPending); 3847 pw.println("SettingsStore:"); 3848 mSettingsStore.dump(fd, pw, args); 3849 mActiveModeWarden.dump(fd, pw, args); 3850 mMakeBeforeBreakManager.dump(fd, pw, args); 3851 pw.println(); 3852 mWifiTrafficPoller.dump(fd, pw, args); 3853 pw.println(); 3854 pw.println("Locks held:"); 3855 mWifiLockManager.dump(pw); 3856 pw.println(); 3857 mWifiMulticastLockManager.dump(pw); 3858 pw.println(); 3859 WifiScoreCard wifiScoreCard = mWifiInjector.getWifiScoreCard(); 3860 String networkListBase64 = mWifiThreadRunner.call(() -> 3861 wifiScoreCard.getNetworkListBase64(true), ""); 3862 pw.println("WifiScoreCard:"); 3863 pw.println(networkListBase64); 3864 3865 updateWifiMetrics(); 3866 mWifiMetrics.dump(fd, pw, args); 3867 3868 pw.println(); 3869 mWifiThreadRunner.run(() -> mWifiNetworkSuggestionsManager.dump(fd, pw, args)); 3870 pw.println(); 3871 mWifiBackupRestore.dump(fd, pw, args); 3872 pw.println(); 3873 pw.println("ScoringParams: " + mWifiInjector.getScoringParams()); 3874 pw.println(); 3875 mWifiThreadRunner.run(() -> { 3876 mWifiInjector.getWifiNetworkScoreCache().dumpWithLatestScanResults( 3877 fd, pw, args, mScanRequestProxy.getScanResults()); 3878 mWifiInjector.getSettingsConfigStore().dump(fd, pw, args); 3879 }); 3880 pw.println(); 3881 mCountryCode.dump(fd, pw, args); 3882 mWifiInjector.getWifiNetworkFactory().dump(fd, pw, args); 3883 mWifiInjector.getUntrustedWifiNetworkFactory().dump(fd, pw, args); 3884 mWifiInjector.getOemWifiNetworkFactory().dump(fd, pw, args); 3885 pw.println("Wlan Wake Reasons:" + mWifiNative.getWlanWakeReasonCount()); 3886 pw.println(); 3887 mWifiConfigManager.dump(fd, pw, args); 3888 pw.println(); 3889 mPasspointManager.dump(pw); 3890 pw.println(); 3891 mWifiInjector.getWifiDiagnostics().captureBugReportData( 3892 WifiDiagnostics.REPORT_REASON_USER_ACTION); 3893 mWifiInjector.getWifiDiagnostics().dump(fd, pw, args); 3894 mWifiConnectivityManager.dump(fd, pw, args); 3895 mWifiThreadRunner.run(() -> { 3896 mWifiHealthMonitor.dump(fd, pw, args); 3897 }); 3898 mWifiThreadRunner.run(() -> { 3899 mWifiScoreCard.dump(fd, pw, args); 3900 }); 3901 mWifiInjector.getWakeupController().dump(fd, pw, args); 3902 mWifiInjector.getWifiLastResortWatchdog().dump(fd, pw, args); 3903 mWifiInjector.getAdaptiveConnectivityEnabledSettingObserver().dump(fd, pw, args); 3904 mWifiInjector.getWifiGlobals().dump(fd, pw, args); 3905 mWifiInjector.getSarManager().dump(fd, pw, args); 3906 pw.println(); 3907 mLastCallerInfoManager.dump(pw); 3908 pw.println(); 3909 mWifiInjector.getLinkProbeManager().dump(fd, pw, args); 3910 } 3911 } 3912 3913 @Override 3914 public boolean acquireWifiLock(IBinder binder, int lockMode, String tag, WorkSource ws) { 3915 mLog.info("acquireWifiLock uid=% lockMode=%") 3916 .c(Binder.getCallingUid()) 3917 .c(lockMode).flush(); 3918 3919 // Check on permission to make this call 3920 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null); 3921 3922 // If no UID is provided in worksource, use the calling UID 3923 WorkSource updatedWs = (ws == null || ws.isEmpty()) 3924 ? new WorkSource(Binder.getCallingUid()) : ws; 3925 3926 if (!WifiLockManager.isValidLockMode(lockMode)) { 3927 throw new IllegalArgumentException("lockMode =" + lockMode); 3928 } 3929 3930 return mWifiThreadRunner.call(() -> 3931 mWifiLockManager.acquireWifiLock(lockMode, tag, binder, updatedWs), false); 3932 } 3933 3934 @Override 3935 public void updateWifiLockWorkSource(IBinder binder, WorkSource ws) { 3936 mLog.info("updateWifiLockWorkSource uid=%").c(Binder.getCallingUid()).flush(); 3937 3938 // Check on permission to make this call 3939 mContext.enforceCallingOrSelfPermission( 3940 android.Manifest.permission.UPDATE_DEVICE_STATS, null); 3941 3942 // If no UID is provided in worksource, use the calling UID 3943 WorkSource updatedWs = (ws == null || ws.isEmpty()) 3944 ? new WorkSource(Binder.getCallingUid()) : ws; 3945 3946 mWifiThreadRunner.run(() -> 3947 mWifiLockManager.updateWifiLockWorkSource(binder, updatedWs)); 3948 } 3949 3950 @Override 3951 public boolean releaseWifiLock(IBinder binder) { 3952 mLog.info("releaseWifiLock uid=%").c(Binder.getCallingUid()).flush(); 3953 3954 // Check on permission to make this call 3955 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null); 3956 3957 return mWifiThreadRunner.call(() -> 3958 mWifiLockManager.releaseWifiLock(binder), false); 3959 } 3960 3961 @Override 3962 public void initializeMulticastFiltering() { 3963 enforceMulticastChangePermission(); 3964 mLog.info("initializeMulticastFiltering uid=%").c(Binder.getCallingUid()).flush(); 3965 mWifiMulticastLockManager.initializeFiltering(); 3966 } 3967 3968 @Override 3969 public void acquireMulticastLock(IBinder binder, String tag) { 3970 enforceMulticastChangePermission(); 3971 mLog.info("acquireMulticastLock uid=%").c(Binder.getCallingUid()).flush(); 3972 mWifiMulticastLockManager.acquireLock(binder, tag); 3973 } 3974 3975 @Override 3976 public void releaseMulticastLock(String tag) { 3977 enforceMulticastChangePermission(); 3978 mLog.info("releaseMulticastLock uid=%").c(Binder.getCallingUid()).flush(); 3979 mWifiMulticastLockManager.releaseLock(tag); 3980 } 3981 3982 @Override 3983 public boolean isMulticastEnabled() { 3984 enforceAccessPermission(); 3985 if (isVerboseLoggingEnabled()) { 3986 mLog.info("isMulticastEnabled uid=%").c(Binder.getCallingUid()).flush(); 3987 } 3988 return mWifiMulticastLockManager.isMulticastEnabled(); 3989 } 3990 3991 @Override 3992 public void enableVerboseLogging(int verbose) { 3993 enforceAccessPermission(); 3994 enforceNetworkSettingsPermission(); 3995 mLog.info("enableVerboseLogging uid=% verbose=%") 3996 .c(Binder.getCallingUid()) 3997 .c(verbose).flush(); 3998 boolean enabled = verbose > 0; 3999 mWifiInjector.getSettingsConfigStore().put(WIFI_VERBOSE_LOGGING_ENABLED, enabled); 4000 onVerboseLoggingStatusChanged(enabled); 4001 enableVerboseLoggingInternal(verbose); 4002 } 4003 4004 private void onVerboseLoggingStatusChanged(boolean enabled) { 4005 int itemCount = mRegisteredWifiLoggingStatusListeners.beginBroadcast(); 4006 for (int i = 0; i < itemCount; i++) { 4007 try { 4008 mRegisteredWifiLoggingStatusListeners.getBroadcastItem(i) 4009 .onStatusChanged(enabled); 4010 } catch (RemoteException e) { 4011 Log.e(TAG, "onVerboseLoggingStatusChanged: RemoteException -- ", e); 4012 } 4013 4014 } 4015 mRegisteredWifiLoggingStatusListeners.finishBroadcast(); 4016 } 4017 4018 private boolean isVerboseLoggingEnabled() { 4019 return WifiManager.VERBOSE_LOGGING_LEVEL_DISABLED != mVerboseLoggingLevel; 4020 } 4021 4022 private void enableVerboseLoggingInternal(int verbose) { 4023 if (verbose > WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED 4024 && mBuildProperties.isUserBuild()) { 4025 throw new SecurityException(TAG + ": Not allowed for the user build."); 4026 } 4027 mVerboseLoggingLevel = verbose; 4028 4029 // Update wifi globals before sending the verbose logging change. 4030 mWifiThreadRunner.removeCallbacks(mAutoDisableShowKeyVerboseLoggingModeRunnable); 4031 if (WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY == mVerboseLoggingLevel) { 4032 mWifiGlobals.setShowKeyVerboseLoggingModeEnabled(true); 4033 mWifiThreadRunner.postDelayed(mAutoDisableShowKeyVerboseLoggingModeRunnable, 4034 AUTO_DISABLE_SHOW_KEY_COUNTDOWN_MILLIS); 4035 } else { 4036 // Ensure the show key mode is disabled. 4037 mWifiGlobals.setShowKeyVerboseLoggingModeEnabled(false); 4038 } 4039 4040 mActiveModeWarden.enableVerboseLogging(isVerboseLoggingEnabled()); 4041 mWifiLockManager.enableVerboseLogging(verbose); 4042 mWifiMulticastLockManager.enableVerboseLogging(verbose); 4043 mWifiInjector.enableVerboseLogging(verbose); 4044 mWifiInjector.getSarManager().enableVerboseLogging(verbose); 4045 } 4046 4047 @Override 4048 public int getVerboseLoggingLevel() { 4049 if (isVerboseLoggingEnabled()) { 4050 mLog.info("getVerboseLoggingLevel uid=%").c(Binder.getCallingUid()).flush(); 4051 } 4052 return mVerboseLoggingLevel; 4053 } 4054 4055 private Runnable mAutoDisableShowKeyVerboseLoggingModeRunnable = new Runnable() { 4056 @Override 4057 public void run() { 4058 // If still enabled, fallback to the regular verbose logging mode. 4059 if (isVerboseLoggingEnabled()) { 4060 enableVerboseLoggingInternal(WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED); 4061 } 4062 } 4063 }; 4064 4065 @Override 4066 public void factoryReset(String packageName) { 4067 enforceNetworkSettingsPermission(); 4068 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 4069 return; 4070 } 4071 mLog.info("factoryReset uid=%").c(Binder.getCallingUid()).flush(); 4072 if (mUserManager.hasUserRestrictionForUser( 4073 UserManager.DISALLOW_NETWORK_RESET, 4074 UserHandle.getUserHandleForUid(Binder.getCallingUid()))) { 4075 return; 4076 } 4077 if (!mUserManager.hasUserRestrictionForUser( 4078 UserManager.DISALLOW_CONFIG_TETHERING, 4079 UserHandle.getUserHandleForUid(Binder.getCallingUid()))) { 4080 // Turn mobile hotspot off 4081 stopSoftApInternal(WifiManager.IFACE_IP_MODE_UNSPECIFIED); 4082 } 4083 4084 if (mUserManager.hasUserRestrictionForUser( 4085 UserManager.DISALLOW_CONFIG_WIFI, 4086 UserHandle.getUserHandleForUid(Binder.getCallingUid()))) { 4087 return; 4088 } 4089 // Delete all Wifi SSIDs 4090 List<WifiConfiguration> networks = mWifiThreadRunner.call( 4091 () -> mWifiConfigManager.getSavedNetworks(Process.WIFI_UID), 4092 Collections.emptyList()); 4093 for (WifiConfiguration network : networks) { 4094 removeNetwork(network.networkId, packageName); 4095 } 4096 // Delete all Passpoint configurations 4097 List<PasspointConfiguration> configs = mWifiThreadRunner.call( 4098 () -> mPasspointManager.getProviderConfigs(Process.WIFI_UID /* ignored */, true), 4099 Collections.emptyList()); 4100 for (PasspointConfiguration config : configs) { 4101 removePasspointConfigurationInternal(null, config.getUniqueId()); 4102 } 4103 mWifiThreadRunner.post(() -> { 4104 mPasspointManager.clearAnqpRequestsAndFlushCache(); 4105 mWifiConfigManager.clearUserTemporarilyDisabledList(); 4106 mWifiConfigManager.removeAllEphemeralOrPasspointConfiguredNetworks(); 4107 mWifiInjector.getWifiNetworkFactory().clear(); 4108 mWifiNetworkSuggestionsManager.clear(); 4109 mWifiInjector.getWifiScoreCard().clear(); 4110 mWifiHealthMonitor.clear(); 4111 mWifiCarrierInfoManager.clear(); 4112 notifyFactoryReset(); 4113 }); 4114 } 4115 4116 /** 4117 * Notify the Factory Reset Event to application who may installed wifi configurations. 4118 */ 4119 private void notifyFactoryReset() { 4120 Intent intent = new Intent(WifiManager.ACTION_NETWORK_SETTINGS_RESET); 4121 4122 // Retrieve list of broadcast receivers for this broadcast & send them directed broadcasts 4123 // to wake them up (if they're in background). 4124 List<ResolveInfo> resolveInfos = 4125 mContext.getPackageManager().queryBroadcastReceiversAsUser( 4126 intent, 0, 4127 UserHandle.of(mWifiInjector.getWifiPermissionsWrapper().getCurrentUser())); 4128 if (resolveInfos == null || resolveInfos.isEmpty()) return; // No need to send broadcast. 4129 4130 for (ResolveInfo resolveInfo : resolveInfos) { 4131 Intent intentToSend = new Intent(intent); 4132 intentToSend.setComponent(new ComponentName( 4133 resolveInfo.activityInfo.applicationInfo.packageName, 4134 resolveInfo.activityInfo.name)); 4135 mContext.sendBroadcastAsUser(intentToSend, UserHandle.CURRENT, 4136 android.Manifest.permission.NETWORK_CARRIER_PROVISIONING); 4137 } 4138 } 4139 4140 @Override 4141 public Network getCurrentNetwork() { 4142 if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { 4143 throw new SecurityException(TAG + ": Permission denied"); 4144 } 4145 if (isVerboseLoggingEnabled()) { 4146 mLog.info("getCurrentNetwork uid=%").c(Binder.getCallingUid()).flush(); 4147 } 4148 return getPrimaryClientModeManagerBlockingThreadSafe().syncGetCurrentNetwork(); 4149 } 4150 4151 public static String toHexString(String s) { 4152 if (s == null) { 4153 return "null"; 4154 } 4155 StringBuilder sb = new StringBuilder(); 4156 sb.append('\'').append(s).append('\''); 4157 for (int n = 0; n < s.length(); n++) { 4158 sb.append(String.format(" %02x", s.charAt(n) & 0xffff)); 4159 } 4160 return sb.toString(); 4161 } 4162 4163 /** 4164 * Retrieve the data to be backed to save the current state. 4165 * 4166 * @return Raw byte stream of the data to be backed up. 4167 */ 4168 @Override 4169 public byte[] retrieveBackupData() { 4170 enforceNetworkSettingsPermission(); 4171 mLog.info("retrieveBackupData uid=%").c(Binder.getCallingUid()).flush(); 4172 Log.d(TAG, "Retrieving backup data"); 4173 List<WifiConfiguration> wifiConfigurations = mWifiThreadRunner.call( 4174 () -> mWifiConfigManager.getConfiguredNetworksWithPasswords(), null); 4175 byte[] backupData = 4176 mWifiBackupRestore.retrieveBackupDataFromConfigurations(wifiConfigurations); 4177 Log.d(TAG, "Retrieved backup data"); 4178 return backupData; 4179 } 4180 4181 /** 4182 * Helper method to restore networks retrieved from backup data. 4183 * 4184 * @param configurations list of WifiConfiguration objects parsed from the backup data. 4185 */ 4186 private void restoreNetworks(List<WifiConfiguration> configurations) { 4187 if (configurations == null) { 4188 Log.e(TAG, "Backup data parse failed"); 4189 return; 4190 } 4191 int callingUid = Binder.getCallingUid(); 4192 mWifiThreadRunner.run( 4193 () -> { 4194 for (WifiConfiguration configuration : configurations) { 4195 int networkId = 4196 mWifiConfigManager.addOrUpdateNetwork(configuration, callingUid) 4197 .getNetworkId(); 4198 if (networkId == WifiConfiguration.INVALID_NETWORK_ID) { 4199 Log.e(TAG, "Restore network failed: " 4200 + configuration.getProfileKey()); 4201 continue; 4202 } 4203 // Enable all networks restored. 4204 mWifiConfigManager.enableNetwork(networkId, false, callingUid, null); 4205 // Restore auto-join param. 4206 mWifiConfigManager.allowAutojoin(networkId, configuration.allowAutojoin); 4207 } 4208 }); 4209 } 4210 4211 /** 4212 * Restore state from the backed up data. 4213 * 4214 * @param data Raw byte stream of the backed up data. 4215 */ 4216 @Override 4217 public void restoreBackupData(byte[] data) { 4218 enforceNetworkSettingsPermission(); 4219 mLog.info("restoreBackupData uid=%").c(Binder.getCallingUid()).flush(); 4220 Log.d(TAG, "Restoring backup data"); 4221 List<WifiConfiguration> wifiConfigurations = 4222 mWifiBackupRestore.retrieveConfigurationsFromBackupData(data); 4223 restoreNetworks(wifiConfigurations); 4224 Log.d(TAG, "Restored backup data"); 4225 } 4226 4227 /** 4228 * Retrieve the soft ap config data to be backed to save current config data. 4229 * 4230 * @return Raw byte stream of the data to be backed up. 4231 */ 4232 @Override 4233 public byte[] retrieveSoftApBackupData() { 4234 enforceNetworkSettingsPermission(); 4235 mLog.info("retrieveSoftApBackupData uid=%").c(Binder.getCallingUid()).flush(); 4236 SoftApConfiguration config = mWifiThreadRunner.call(mWifiApConfigStore::getApConfiguration, 4237 new SoftApConfiguration.Builder().build()); 4238 byte[] backupData = 4239 mSoftApBackupRestore.retrieveBackupDataFromSoftApConfiguration(config); 4240 Log.d(TAG, "Retrieved soft ap backup data"); 4241 return backupData; 4242 } 4243 4244 /** 4245 * Restore soft ap config from the backed up data. 4246 * 4247 * @param data Raw byte stream of the backed up data. 4248 * @return restored SoftApConfiguration or Null if data is invalid. 4249 */ 4250 @Override 4251 public SoftApConfiguration restoreSoftApBackupData(byte[] data) { 4252 enforceNetworkSettingsPermission(); 4253 mLog.info("restoreSoftApBackupData uid=%").c(Binder.getCallingUid()).flush(); 4254 SoftApConfiguration softApConfig = 4255 mSoftApBackupRestore.retrieveSoftApConfigurationFromBackupData(data); 4256 if (softApConfig != null) { 4257 mWifiThreadRunner.post(() -> mWifiApConfigStore.setApConfiguration( 4258 mWifiApConfigStore.resetToDefaultForUnsupportedConfig( 4259 mWifiApConfigStore.upgradeSoftApConfiguration(softApConfig)))); 4260 Log.d(TAG, "Restored soft ap backup data"); 4261 } 4262 return softApConfig; 4263 } 4264 4265 4266 /** 4267 * Restore state from the older supplicant back up data. 4268 * The old backup data was essentially a backup of wpa_supplicant.conf & ipconfig.txt file. 4269 * 4270 * @param supplicantData Raw byte stream of wpa_supplicant.conf 4271 * @param ipConfigData Raw byte stream of ipconfig.txt 4272 */ 4273 public void restoreSupplicantBackupData(byte[] supplicantData, byte[] ipConfigData) { 4274 enforceNetworkSettingsPermission(); 4275 mLog.trace("restoreSupplicantBackupData uid=%").c(Binder.getCallingUid()).flush(); 4276 Log.d(TAG, "Restoring supplicant backup data"); 4277 List<WifiConfiguration> wifiConfigurations = 4278 mWifiBackupRestore.retrieveConfigurationsFromSupplicantBackupData( 4279 supplicantData, ipConfigData); 4280 restoreNetworks(wifiConfigurations); 4281 Log.d(TAG, "Restored supplicant backup data"); 4282 } 4283 4284 /** 4285 * Starts subscription provisioning with a provider. 4286 * 4287 * @param provider {@link OsuProvider} the provider to provision with 4288 * @param callback {@link IProvisioningCallback} the callback object to inform status 4289 */ 4290 @Override 4291 public void startSubscriptionProvisioning(OsuProvider provider, 4292 IProvisioningCallback callback) { 4293 if (provider == null) { 4294 throw new IllegalArgumentException("Provider must not be null"); 4295 } 4296 if (callback == null) { 4297 throw new IllegalArgumentException("Callback must not be null"); 4298 } 4299 if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { 4300 throw new SecurityException(TAG + ": Permission denied"); 4301 } 4302 final int uid = Binder.getCallingUid(); 4303 mLog.trace("startSubscriptionProvisioning uid=%").c(uid).flush(); 4304 if (getPrimaryClientModeManagerBlockingThreadSafe() 4305 .syncStartSubscriptionProvisioning(uid, provider, callback)) { 4306 mLog.trace("Subscription provisioning started with %") 4307 .c(provider.toString()).flush(); 4308 } 4309 } 4310 4311 /** 4312 * See 4313 * {@link WifiManager#registerTrafficStateCallback(Executor, WifiManager.TrafficStateCallback)} 4314 * 4315 * @param callback Traffic State callback to register 4316 * 4317 * @throws SecurityException if the caller does not have permission to register a callback 4318 * @throws RemoteException if remote exception happens 4319 * @throws IllegalArgumentException if the arguments are null or invalid 4320 */ 4321 @Override 4322 public void registerTrafficStateCallback(ITrafficStateCallback callback) { 4323 // verify arguments 4324 if (callback == null) { 4325 throw new IllegalArgumentException("Callback must not be null"); 4326 } 4327 enforceNetworkSettingsPermission(); 4328 if (isVerboseLoggingEnabled()) { 4329 mLog.info("registerTrafficStateCallback uid=%").c(Binder.getCallingUid()).flush(); 4330 } 4331 // Post operation to handler thread 4332 mWifiThreadRunner.post(() -> mWifiTrafficPoller.addCallback(callback)); 4333 } 4334 4335 /** 4336 * see {@link android.net.wifi.WifiManager#unregisterTrafficStateCallback( 4337 * WifiManager.TrafficStateCallback)} 4338 * 4339 * @param callback Traffic State callback to unregister 4340 * 4341 * @throws SecurityException if the caller does not have permission to register a callback 4342 */ 4343 @Override 4344 public void unregisterTrafficStateCallback(ITrafficStateCallback callback) { 4345 enforceNetworkSettingsPermission(); 4346 if (isVerboseLoggingEnabled()) { 4347 mLog.info("unregisterTrafficStateCallback uid=%").c(Binder.getCallingUid()).flush(); 4348 } 4349 // Post operation to handler thread 4350 mWifiThreadRunner.post(() -> mWifiTrafficPoller.removeCallback(callback)); 4351 } 4352 4353 private long getSupportedFeaturesInternal() { 4354 long supportedFeatureSet = mWifiThreadRunner.call( 4355 () -> mActiveModeWarden.getPrimaryClientModeManager().getSupportedFeatures(), 4356 0L); 4357 // Mask the feature set against system properties. 4358 boolean rttSupported = mContext.getPackageManager().hasSystemFeature( 4359 PackageManager.FEATURE_WIFI_RTT); 4360 if (!rttSupported) { 4361 // flags filled in by vendor HAL, remove if overlay disables it. 4362 supportedFeatureSet &= 4363 ~(WifiManager.WIFI_FEATURE_D2D_RTT | WifiManager.WIFI_FEATURE_D2AP_RTT); 4364 } 4365 if (!mContext.getResources().getBoolean( 4366 R.bool.config_wifi_p2p_mac_randomization_supported)) { 4367 // flags filled in by vendor HAL, remove if overlay disables it. 4368 supportedFeatureSet &= ~WifiManager.WIFI_FEATURE_P2P_RAND_MAC; 4369 } 4370 if (mContext.getResources().getBoolean( 4371 R.bool.config_wifi_connected_mac_randomization_supported)) { 4372 // no corresponding flags in vendor HAL, set if overlay enables it. 4373 supportedFeatureSet |= WifiManager.WIFI_FEATURE_CONNECTED_RAND_MAC; 4374 } 4375 if (ApConfigUtil.isApMacRandomizationSupported(mContext)) { 4376 // no corresponding flags in vendor HAL, set if overlay enables it. 4377 supportedFeatureSet |= WifiManager.WIFI_FEATURE_AP_RAND_MAC; 4378 } 4379 if (SdkLevel.isAtLeastS()) { 4380 if (ApConfigUtil.isBridgedModeSupported(mContext)) { 4381 // The bridged mode requires the kernel network modules support. 4382 // It doesn't relate the vendor HAL, set if overlay enables it. 4383 supportedFeatureSet |= WifiManager.WIFI_FEATURE_BRIDGED_AP; 4384 } 4385 if (mContext.getResources().getBoolean( 4386 R.bool.config_wifiStaWithBridgedSoftApConcurrencySupported)) { 4387 // The bridged mode requires the kernel network modules support. 4388 // It doesn't relate the vendor HAL, set if overlay enables it. 4389 supportedFeatureSet |= WifiManager.WIFI_FEATURE_STA_BRIDGED_AP; 4390 } 4391 } 4392 supportedFeatureSet |= mWifiThreadRunner.call( 4393 () -> { 4394 long concurrencyFeatureSet = 0L; 4395 if (mActiveModeWarden.isStaApConcurrencySupported()) { 4396 concurrencyFeatureSet |= WifiManager.WIFI_FEATURE_AP_STA; 4397 } 4398 if (mActiveModeWarden.isStaStaConcurrencySupportedForLocalOnlyConnections()) { 4399 concurrencyFeatureSet |= WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY; 4400 } 4401 if (mActiveModeWarden.isStaStaConcurrencySupportedForMbb()) { 4402 concurrencyFeatureSet |= WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MBB; 4403 } 4404 if (mActiveModeWarden.isStaStaConcurrencySupportedForRestrictedConnections()) { 4405 concurrencyFeatureSet |= WifiManager.WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED; 4406 } 4407 return concurrencyFeatureSet; 4408 }, 0L); 4409 return supportedFeatureSet; 4410 } 4411 4412 private static boolean hasAutomotiveFeature(Context context) { 4413 return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE); 4414 } 4415 4416 /** 4417 * See 4418 * {@link WifiManager#registerNetworkRequestMatchCallback( 4419 * Executor, WifiManager.NetworkRequestMatchCallback)} 4420 * 4421 * @param callback Network Request Match callback to register 4422 * 4423 * @throws SecurityException if the caller does not have permission to register a callback 4424 * @throws RemoteException if remote exception happens 4425 * @throws IllegalArgumentException if the arguments are null or invalid 4426 */ 4427 @Override 4428 public void registerNetworkRequestMatchCallback(INetworkRequestMatchCallback callback) { 4429 // verify arguments 4430 if (callback == null) { 4431 throw new IllegalArgumentException("Callback must not be null"); 4432 } 4433 enforceNetworkSettingsPermission(); 4434 if (isVerboseLoggingEnabled()) { 4435 mLog.info("registerNetworkRequestMatchCallback uid=%") 4436 .c(Binder.getCallingUid()).flush(); 4437 } 4438 // Post operation to handler thread 4439 mWifiThreadRunner.post(() -> 4440 mWifiInjector.getWifiNetworkFactory().addCallback(callback)); 4441 } 4442 4443 /** 4444 * see {@link android.net.wifi.WifiManager#unregisterNetworkRequestMatchCallback( 4445 * WifiManager.NetworkRequestMatchCallback)} 4446 * 4447 * @param callback Network Request Match callback to unregister 4448 * 4449 * @throws SecurityException if the caller does not have permission to register a callback 4450 */ 4451 @Override 4452 public void unregisterNetworkRequestMatchCallback(INetworkRequestMatchCallback callback) { 4453 enforceNetworkSettingsPermission(); 4454 if (isVerboseLoggingEnabled()) { 4455 mLog.info("unregisterNetworkRequestMatchCallback uid=%") 4456 .c(Binder.getCallingUid()).flush(); 4457 } 4458 // Post operation to handler thread 4459 mWifiThreadRunner.post(() -> 4460 mWifiInjector.getWifiNetworkFactory().removeCallback(callback)); 4461 } 4462 4463 /** 4464 * See {@link android.net.wifi.WifiManager#addNetworkSuggestions(List)} 4465 * 4466 * @param networkSuggestions List of network suggestions to be added. 4467 * @param callingPackageName Package Name of the app adding the suggestions. 4468 * @param callingFeatureId Feature in the calling package 4469 * @throws SecurityException if the caller does not have permission. 4470 * @return One of status codes from {@link WifiManager.NetworkSuggestionsStatusCode}. 4471 */ 4472 @Override 4473 public int addNetworkSuggestions( 4474 List<WifiNetworkSuggestion> networkSuggestions, String callingPackageName, 4475 String callingFeatureId) { 4476 if (enforceChangePermission(callingPackageName) != MODE_ALLOWED) { 4477 return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_APP_DISALLOWED; 4478 } 4479 if (isVerboseLoggingEnabled()) { 4480 mLog.info("addNetworkSuggestions uid=%").c(Binder.getCallingUid()).flush(); 4481 } 4482 int callingUid = Binder.getCallingUid(); 4483 4484 int success = mWifiThreadRunner.call(() -> mWifiNetworkSuggestionsManager.add( 4485 networkSuggestions, callingUid, callingPackageName, callingFeatureId), 4486 WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL); 4487 if (success != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) { 4488 Log.e(TAG, "Failed to add network suggestions"); 4489 } 4490 return success; 4491 } 4492 4493 /** 4494 * See {@link android.net.wifi.WifiManager#removeNetworkSuggestions(List)} 4495 * 4496 * @param networkSuggestions List of network suggestions to be removed. 4497 * @param callingPackageName Package Name of the app removing the suggestions. 4498 * @throws SecurityException if the caller does not have permission. 4499 * @return One of status codes from {@link WifiManager.NetworkSuggestionsStatusCode}. 4500 */ 4501 @Override 4502 public int removeNetworkSuggestions( 4503 List<WifiNetworkSuggestion> networkSuggestions, String callingPackageName) { 4504 if (enforceChangePermission(callingPackageName) != MODE_ALLOWED) { 4505 return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_APP_DISALLOWED; 4506 } 4507 if (isVerboseLoggingEnabled()) { 4508 mLog.info("removeNetworkSuggestions uid=%").c(Binder.getCallingUid()).flush(); 4509 } 4510 int callingUid = Binder.getCallingUid(); 4511 4512 int success = mWifiThreadRunner.call(() -> mWifiNetworkSuggestionsManager.remove( 4513 networkSuggestions, callingUid, callingPackageName), 4514 WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL); 4515 if (success != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) { 4516 Log.e(TAG, "Failed to remove network suggestions"); 4517 } 4518 return success; 4519 } 4520 4521 /** 4522 * See {@link android.net.wifi.WifiManager#getNetworkSuggestions()} 4523 * @param callingPackageName Package Name of the app getting the suggestions. 4524 * @return a list of network suggestions suggested by this app 4525 */ 4526 @Override 4527 public List<WifiNetworkSuggestion> getNetworkSuggestions(String callingPackageName) { 4528 int callingUid = Binder.getCallingUid(); 4529 mAppOps.checkPackage(callingUid, callingPackageName); 4530 enforceAccessPermission(); 4531 if (isVerboseLoggingEnabled()) { 4532 mLog.info("getNetworkSuggestionList uid=%").c(Binder.getCallingUid()).flush(); 4533 } 4534 return mWifiThreadRunner.call(() -> 4535 mWifiNetworkSuggestionsManager.get(callingPackageName, callingUid), 4536 Collections.emptyList()); 4537 } 4538 4539 /** 4540 * Gets the factory Wi-Fi MAC addresses. 4541 * @throws SecurityException if the caller does not have permission. 4542 * @return Array of String representing Wi-Fi MAC addresses, or empty array if failed. 4543 */ 4544 @Override 4545 public String[] getFactoryMacAddresses() { 4546 final int uid = Binder.getCallingUid(); 4547 if (!mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { 4548 throw new SecurityException("App not allowed to get Wi-Fi factory MAC address " 4549 + "(uid = " + uid + ")"); 4550 } 4551 String result = mWifiThreadRunner.call( 4552 () -> mActiveModeWarden.getPrimaryClientModeManager().getFactoryMacAddress(), 4553 null); 4554 // result can be empty array if either: WifiThreadRunner.call() timed out, or 4555 // ClientModeImpl.getFactoryMacAddress() returned null. 4556 // In this particular instance, we don't differentiate the two types of nulls. 4557 if (result == null) { 4558 return new String[0]; 4559 } 4560 return new String[]{result}; 4561 } 4562 4563 /** 4564 * Sets the current device mobility state. 4565 * @param state the new device mobility state 4566 */ 4567 @Override 4568 public void setDeviceMobilityState(@DeviceMobilityState int state) { 4569 mContext.enforceCallingOrSelfPermission( 4570 android.Manifest.permission.WIFI_SET_DEVICE_MOBILITY_STATE, "WifiService"); 4571 4572 if (isVerboseLoggingEnabled()) { 4573 mLog.info("setDeviceMobilityState uid=% state=%") 4574 .c(Binder.getCallingUid()) 4575 .c(state) 4576 .flush(); 4577 } 4578 // Post operation to handler thread 4579 mWifiThreadRunner.post(() -> { 4580 mWifiConnectivityManager.setDeviceMobilityState(state); 4581 mWifiHealthMonitor.setDeviceMobilityState(state); 4582 mWifiDataStall.setDeviceMobilityState(state); 4583 }); 4584 } 4585 4586 /** 4587 * Proxy for the final native call of the parent class. Enables mocking of 4588 * the function. 4589 */ 4590 public int getMockableCallingUid() { 4591 return getCallingUid(); 4592 } 4593 4594 /** 4595 * Start DPP in Configurator-Initiator role. The current device will initiate DPP bootstrapping 4596 * with a peer, and send the SSID and password of the selected network. 4597 * 4598 * @param binder Caller's binder context 4599 * @param packageName Package name of the calling app 4600 * @param enrolleeUri URI of the Enrollee obtained externally (e.g. QR code scanning) 4601 * @param selectedNetworkId Selected network ID to be sent to the peer 4602 * @param netRole The network role of the enrollee 4603 * @param callback Callback for status updates 4604 */ 4605 @Override 4606 public void startDppAsConfiguratorInitiator(IBinder binder, @NonNull String packageName, 4607 String enrolleeUri, int selectedNetworkId, int netRole, IDppCallback callback) { 4608 // verify arguments 4609 if (binder == null) { 4610 throw new IllegalArgumentException("Binder must not be null"); 4611 } 4612 if (TextUtils.isEmpty(enrolleeUri)) { 4613 throw new IllegalArgumentException("Enrollee URI must not be null or empty"); 4614 } 4615 if (selectedNetworkId < 0) { 4616 throw new IllegalArgumentException("Selected network ID invalid"); 4617 } 4618 if (callback == null) { 4619 throw new IllegalArgumentException("Callback must not be null"); 4620 } 4621 4622 final int uid = getMockableCallingUid(); 4623 4624 int callingUid = Binder.getCallingUid(); 4625 mAppOps.checkPackage(callingUid, packageName); 4626 if (!isSettingsOrSuw(Binder.getCallingPid(), callingUid)) { 4627 throw new SecurityException(TAG + ": Permission denied"); 4628 } 4629 // Stop MBB (if in progress) when DPP is initiated. Otherwise, DPP operation will fail 4630 // when the previous primary iface is removed after MBB completion. 4631 mWifiThreadRunner.post(() -> 4632 mMakeBeforeBreakManager.stopAllSecondaryTransientClientModeManagers(() -> 4633 mDppManager.startDppAsConfiguratorInitiator( 4634 uid, packageName, 4635 mActiveModeWarden.getPrimaryClientModeManager().getInterfaceName(), 4636 binder, enrolleeUri, 4637 removeSecurityTypeFromNetworkId(selectedNetworkId), netRole, 4638 callback))); 4639 } 4640 4641 /** 4642 * Start DPP in Enrollee-Initiator role. The current device will initiate DPP bootstrapping 4643 * with a peer, and receive the SSID and password from the peer configurator. 4644 * 4645 * @param binder Caller's binder context 4646 * @param configuratorUri URI of the Configurator obtained externally (e.g. QR code scanning) 4647 * @param callback Callback for status updates 4648 */ 4649 @Override 4650 public void startDppAsEnrolleeInitiator(IBinder binder, String configuratorUri, 4651 IDppCallback callback) { 4652 // verify arguments 4653 if (binder == null) { 4654 throw new IllegalArgumentException("Binder must not be null"); 4655 } 4656 if (TextUtils.isEmpty(configuratorUri)) { 4657 throw new IllegalArgumentException("Enrollee URI must not be null or empty"); 4658 } 4659 if (callback == null) { 4660 throw new IllegalArgumentException("Callback must not be null"); 4661 } 4662 4663 final int uid = getMockableCallingUid(); 4664 4665 if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { 4666 throw new SecurityException(TAG + ": Permission denied"); 4667 } 4668 4669 // Stop MBB (if in progress) when DPP is initiated. Otherwise, DPP operation will fail 4670 // when the previous primary iface is removed after MBB completion. 4671 mWifiThreadRunner.post(() -> 4672 mMakeBeforeBreakManager.stopAllSecondaryTransientClientModeManagers(() -> 4673 mDppManager.startDppAsEnrolleeInitiator(uid, 4674 mActiveModeWarden.getPrimaryClientModeManager().getInterfaceName(), 4675 binder, configuratorUri, callback))); 4676 } 4677 4678 /** 4679 * Start DPP in Enrollee-Responder role. The current device will generate the 4680 * bootstrap code and wait for the peer device to start the DPP authentication process. 4681 * 4682 * @param binder Caller's binder context 4683 * @param deviceInfo Device specific info to display in QR code(e.g. Easy_connect_demo) 4684 * @param curve Elliptic curve cryptography type used to generate DPP public/private key pair. 4685 * @param callback Callback for status updates 4686 */ 4687 @Override 4688 @RequiresApi(Build.VERSION_CODES.S) 4689 public void startDppAsEnrolleeResponder(IBinder binder, @Nullable String deviceInfo, 4690 @WifiManager.EasyConnectCryptographyCurve int curve, IDppCallback callback) { 4691 if (!SdkLevel.isAtLeastS()) { 4692 throw new UnsupportedOperationException(); 4693 } 4694 // verify arguments 4695 if (binder == null) { 4696 throw new IllegalArgumentException("Binder must not be null"); 4697 } 4698 if (callback == null) { 4699 throw new IllegalArgumentException("Callback must not be null"); 4700 } 4701 4702 final int uid = getMockableCallingUid(); 4703 4704 if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { 4705 throw new SecurityException(TAG + ": Permission denied"); 4706 } 4707 4708 if (deviceInfo != null) { 4709 int deviceInfoLen = deviceInfo.length(); 4710 if (deviceInfoLen > WifiManager.getEasyConnectMaxAllowedResponderDeviceInfoLength()) { 4711 throw new IllegalArgumentException("Device info length: " + deviceInfoLen 4712 + " must be less than " 4713 + WifiManager.getEasyConnectMaxAllowedResponderDeviceInfoLength()); 4714 } 4715 char c; 4716 for (int i = 0; i < deviceInfoLen; i++) { 4717 c = deviceInfo.charAt(i); 4718 if (c < '!' || c > '~' || c == ';') { 4719 throw new IllegalArgumentException("Allowed Range of ASCII characters in" 4720 + "deviceInfo - %x20-7E; semicolon and space are not allowed!" 4721 + "Found c: " + c); 4722 } 4723 } 4724 } 4725 4726 // Stop MBB (if in progress) when DPP is initiated. Otherwise, DPP operation will fail 4727 // when the previous primary iface is removed after MBB completion. 4728 mWifiThreadRunner.post(() -> 4729 mMakeBeforeBreakManager.stopAllSecondaryTransientClientModeManagers(() -> 4730 mDppManager.startDppAsEnrolleeResponder(uid, 4731 mActiveModeWarden.getPrimaryClientModeManager().getInterfaceName(), 4732 binder, deviceInfo, curve, callback))); 4733 } 4734 4735 /** 4736 * Stop or abort a current DPP session. 4737 */ 4738 @Override 4739 public void stopDppSession() throws RemoteException { 4740 if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { 4741 throw new SecurityException(TAG + ": Permission denied"); 4742 } 4743 final int uid = getMockableCallingUid(); 4744 4745 mWifiThreadRunner.post(() -> mDppManager.stopDppSession(uid)); 4746 } 4747 4748 /** 4749 * see {@link android.net.wifi.WifiManager#addWifiVerboseLoggingStatusChangedListener(Executor, 4750 * WifiManager.WifiVerboseLoggingStatusChangedListener)} 4751 * 4752 * @param listener IWifiVerboseLoggingStatusChangedListener listener to add 4753 * 4754 * @throws SecurityException if the caller does not have permission to add a listener. 4755 * @throws IllegalArgumentException if the argument is null. 4756 */ 4757 @Override 4758 public void addWifiVerboseLoggingStatusChangedListener( 4759 IWifiVerboseLoggingStatusChangedListener listener) { 4760 if (listener == null) { 4761 throw new IllegalArgumentException("Listener must not be null"); 4762 } 4763 enforceAccessPermission(); 4764 // Post operation to handler thread 4765 mWifiThreadRunner.post(() -> 4766 mRegisteredWifiLoggingStatusListeners.register(listener)); 4767 } 4768 4769 /** 4770 * see {@link android.net.wifi.WifiManager#unregisterWifiVerboseLoggingStatusCallback 4771 * (WifiManager.WifiVerboseLoggingStatusCallback)} 4772 * 4773 * @param listener the listener to be removed. 4774 * 4775 * @throws SecurityException if the caller does not have permission to add a listener. 4776 * @throws IllegalArgumentException if the argument is null. 4777 */ 4778 @Override 4779 public void removeWifiVerboseLoggingStatusChangedListener( 4780 IWifiVerboseLoggingStatusChangedListener listener) { 4781 if (listener == null) { 4782 throw new IllegalArgumentException("Listener must not be null"); 4783 } 4784 enforceAccessPermission(); 4785 // Post operation to handler thread 4786 mWifiThreadRunner.post(() -> 4787 mRegisteredWifiLoggingStatusListeners.unregister(listener)); 4788 } 4789 4790 /** 4791 * see {@link android.net.wifi.WifiManager#addOnWifiUsabilityStatsListener(Executor, 4792 * WifiManager.OnWifiUsabilityStatsListener)} 4793 * 4794 * @param listener WifiUsabilityStatsEntry listener to add 4795 * 4796 * @throws SecurityException if the caller does not have permission to add a listener 4797 * @throws RemoteException if remote exception happens 4798 * @throws IllegalArgumentException if the arguments are null or invalid 4799 */ 4800 @Override 4801 public void addOnWifiUsabilityStatsListener(IOnWifiUsabilityStatsListener listener) { 4802 if (listener == null) { 4803 throw new IllegalArgumentException("Listener must not be null"); 4804 } 4805 mContext.enforceCallingOrSelfPermission( 4806 android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE, "WifiService"); 4807 if (isVerboseLoggingEnabled()) { 4808 mLog.info("addOnWifiUsabilityStatsListener uid=%") 4809 .c(Binder.getCallingUid()).flush(); 4810 } 4811 // Post operation to handler thread 4812 mWifiThreadRunner.post(() -> 4813 mWifiMetrics.addOnWifiUsabilityListener(listener)); 4814 } 4815 4816 /** 4817 * see {@link android.net.wifi.WifiManager#removeOnWifiUsabilityStatsListener 4818 * (WifiManager.OnWifiUsabilityStatsListener)} 4819 * 4820 * @param listener listener to be removed. 4821 * 4822 * @throws SecurityException if the caller does not have permission to add a listener 4823 */ 4824 @Override 4825 public void removeOnWifiUsabilityStatsListener(IOnWifiUsabilityStatsListener listener) { 4826 mContext.enforceCallingOrSelfPermission( 4827 android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE, "WifiService"); 4828 if (isVerboseLoggingEnabled()) { 4829 mLog.info("removeOnWifiUsabilityStatsListener uid=%") 4830 .c(Binder.getCallingUid()).flush(); 4831 } 4832 // Post operation to handler thread 4833 mWifiThreadRunner.post(() -> 4834 mWifiMetrics.removeOnWifiUsabilityListener(listener)); 4835 } 4836 4837 /** 4838 * Updates the Wi-Fi usability score. 4839 * @param seqNum Sequence number of the Wi-Fi usability score. 4840 * @param score The Wi-Fi usability score. 4841 * @param predictionHorizonSec Prediction horizon of the Wi-Fi usability score in second. 4842 */ 4843 @Override 4844 public void updateWifiUsabilityScore(int seqNum, int score, int predictionHorizonSec) { 4845 mContext.enforceCallingOrSelfPermission( 4846 android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE, "WifiService"); 4847 4848 if (isVerboseLoggingEnabled()) { 4849 mLog.info("updateWifiUsabilityScore uid=% seqNum=% score=% predictionHorizonSec=%") 4850 .c(Binder.getCallingUid()) 4851 .c(seqNum) 4852 .c(score) 4853 .c(predictionHorizonSec) 4854 .flush(); 4855 } 4856 // Post operation to handler thread 4857 mWifiThreadRunner.post(() -> { 4858 String ifaceName = mActiveModeWarden.getPrimaryClientModeManager().getInterfaceName(); 4859 mWifiMetrics.incrementWifiUsabilityScoreCount( 4860 ifaceName, seqNum, score, predictionHorizonSec); 4861 }); 4862 } 4863 4864 /** 4865 * Notify interested parties if a wifi config has been changed. 4866 * 4867 * @param wifiCredentialEventType WIFI_CREDENTIAL_SAVED or WIFI_CREDENTIAL_FORGOT 4868 * @param config Must have a WifiConfiguration object to succeed 4869 */ 4870 private void broadcastWifiCredentialChanged(int wifiCredentialEventType, 4871 WifiConfiguration config) { 4872 Intent intent = new Intent(WifiManager.WIFI_CREDENTIAL_CHANGED_ACTION); 4873 if (config != null && config.SSID != null && mWifiPermissionsUtil.isLocationModeEnabled()) { 4874 intent.putExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_SSID, config.SSID); 4875 } 4876 intent.putExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_EVENT_TYPE, 4877 wifiCredentialEventType); 4878 mContext.createContextAsUser(UserHandle.CURRENT, 0) 4879 .sendBroadcastWithMultiplePermissions( 4880 intent, 4881 new String[]{ 4882 android.Manifest.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE, 4883 android.Manifest.permission.ACCESS_FINE_LOCATION, 4884 }); 4885 } 4886 4887 /** 4888 * Connects to a network. 4889 * 4890 * If the supplied config is not null, then the netId argument will be ignored and the config 4891 * will be saved (or updated if its networkId or profile key already exist) and connected to. 4892 * 4893 * If the supplied config is null, then the netId argument will be matched to a saved config to 4894 * be connected to. 4895 * 4896 * @param config New or existing config to add/update and connect to 4897 * @param netId Network ID of existing config to connect to if the supplied config is null 4898 * @param callback Listener to notify action result 4899 * 4900 * see: {@link WifiManager#connect(WifiConfiguration, WifiManager.ActionListener)} 4901 * {@link WifiManager#connect(int, WifiManager.ActionListener)} 4902 */ 4903 @Override 4904 public void connect(WifiConfiguration config, int netId, @Nullable IActionListener callback) { 4905 int uid = Binder.getCallingUid(); 4906 if (!isPrivileged(Binder.getCallingPid(), uid)) { 4907 throw new SecurityException(TAG + ": Permission denied"); 4908 } 4909 if (config != null) { 4910 config.networkId = removeSecurityTypeFromNetworkId(config.networkId); 4911 } 4912 final int netIdArg = removeSecurityTypeFromNetworkId(netId); 4913 mLog.info("connect uid=%").c(uid).flush(); 4914 mWifiThreadRunner.post(() -> { 4915 ActionListenerWrapper wrapper = new ActionListenerWrapper(callback); 4916 final NetworkUpdateResult result; 4917 // if connecting using WifiConfiguration, save the network first 4918 if (config != null) { 4919 if (mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { 4920 mWifiMetrics.logUserActionEvent( 4921 UserActionEvent.EVENT_ADD_OR_UPDATE_NETWORK, config.networkId); 4922 } 4923 result = mWifiConfigManager.addOrUpdateNetwork(config, uid); 4924 if (!result.isSuccess()) { 4925 Log.e(TAG, "connect adding/updating config=" + config + " failed"); 4926 wrapper.sendFailure(WifiManager.ERROR); 4927 return; 4928 } 4929 broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_SAVED, config); 4930 } else { 4931 if (mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { 4932 mWifiMetrics.logUserActionEvent( 4933 UserActionEvent.EVENT_MANUAL_CONNECT, netIdArg); 4934 } 4935 result = new NetworkUpdateResult(netIdArg); 4936 } 4937 WifiConfiguration configuration = mWifiConfigManager 4938 .getConfiguredNetwork(result.getNetworkId()); 4939 if (configuration == null) { 4940 Log.e(TAG, "connect to Invalid network Id=" + netIdArg); 4941 wrapper.sendFailure(WifiManager.ERROR); 4942 return; 4943 } 4944 if (configuration.enterpriseConfig != null 4945 && configuration.enterpriseConfig.isAuthenticationSimBased()) { 4946 int subId = mWifiCarrierInfoManager.getBestMatchSubscriptionId(configuration); 4947 if (!mWifiCarrierInfoManager.isSimReady(subId)) { 4948 Log.e(TAG, "connect to SIM-based config=" + configuration 4949 + "while SIM is absent"); 4950 wrapper.sendFailure(WifiManager.ERROR); 4951 return; 4952 } 4953 if (mWifiCarrierInfoManager.requiresImsiEncryption(subId) 4954 && !mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(subId)) { 4955 Log.e(TAG, "Imsi protection required but not available for Network=" 4956 + configuration); 4957 wrapper.sendFailure(WifiManager.ERROR); 4958 return; 4959 } 4960 } 4961 mMakeBeforeBreakManager.stopAllSecondaryTransientClientModeManagers(() -> 4962 mConnectHelper.connectToNetwork(result, wrapper, uid)); 4963 }); 4964 } 4965 4966 /** 4967 * see {@link android.net.wifi.WifiManager#save(WifiConfiguration, 4968 * WifiManager.ActionListener)} 4969 */ 4970 @Override 4971 public void save(WifiConfiguration config, @Nullable IActionListener callback) { 4972 int uid = Binder.getCallingUid(); 4973 if (!isPrivileged(Binder.getCallingPid(), uid)) { 4974 throw new SecurityException(TAG + ": Permission denied"); 4975 } 4976 if (config != null) { 4977 config.networkId = removeSecurityTypeFromNetworkId(config.networkId); 4978 } 4979 mLog.info("save uid=%").c(uid).flush(); 4980 mWifiThreadRunner.post(() -> { 4981 ActionListenerWrapper wrapper = new ActionListenerWrapper(callback); 4982 NetworkUpdateResult result = 4983 mWifiConfigManager.updateBeforeSaveNetwork(config, uid); 4984 if (result.isSuccess()) { 4985 broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_SAVED, config); 4986 mMakeBeforeBreakManager.stopAllSecondaryTransientClientModeManagers(() -> 4987 mActiveModeWarden.getPrimaryClientModeManager() 4988 .saveNetwork(result, wrapper, uid)); 4989 if (mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { 4990 mWifiMetrics.logUserActionEvent( 4991 UserActionEvent.EVENT_ADD_OR_UPDATE_NETWORK, config.networkId); 4992 } 4993 } else { 4994 wrapper.sendFailure(WifiManager.ERROR); 4995 } 4996 }); 4997 } 4998 4999 /** 5000 * see {@link android.net.wifi.WifiManager#forget(int, WifiManager.ActionListener)} 5001 */ 5002 @Override 5003 public void forget(int netId, @Nullable IActionListener callback) { 5004 int uid = Binder.getCallingUid(); 5005 if (!isPrivileged(Binder.getCallingPid(), uid)) { 5006 throw new SecurityException(TAG + ": Permission denied"); 5007 } 5008 final int internalNetId = removeSecurityTypeFromNetworkId(netId); 5009 mLog.info("forget uid=%").c(Binder.getCallingUid()).flush(); 5010 if (mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { 5011 // It's important to log this metric before the actual forget executes because 5012 // the netId becomes invalid after the forget operation. 5013 mWifiMetrics.logUserActionEvent(UserActionEvent.EVENT_FORGET_WIFI, internalNetId); 5014 } 5015 mWifiThreadRunner.post(() -> { 5016 WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(internalNetId); 5017 boolean success = mWifiConfigManager.removeNetwork(internalNetId, uid, null); 5018 ActionListenerWrapper wrapper = new ActionListenerWrapper(callback); 5019 if (success) { 5020 wrapper.sendSuccess(); 5021 broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_FORGOT, config); 5022 } else { 5023 Log.e(TAG, "Failed to remove network"); 5024 wrapper.sendFailure(WifiManager.ERROR); 5025 } 5026 }); 5027 } 5028 5029 /** 5030 * See {@link WifiManager#registerScanResultsCallback(WifiManager.ScanResultsCallback)} 5031 */ 5032 public void registerScanResultsCallback(@NonNull IScanResultsCallback callback) { 5033 if (callback == null) { 5034 throw new IllegalArgumentException("callback must not be null"); 5035 } 5036 enforceAccessPermission(); 5037 5038 if (isVerboseLoggingEnabled()) { 5039 mLog.info("registerScanResultsCallback uid=%").c(Binder.getCallingUid()).flush(); 5040 } 5041 mWifiThreadRunner.post(() -> { 5042 if (!mWifiInjector.getScanRequestProxy().registerScanResultsCallback(callback)) { 5043 Log.e(TAG, "registerScanResultsCallback: Failed to register callback"); 5044 } 5045 }); 5046 } 5047 5048 /** 5049 * See {@link WifiManager#registerScanResultsCallback(WifiManager.ScanResultsCallback)} 5050 */ 5051 public void unregisterScanResultsCallback(@NonNull IScanResultsCallback callback) { 5052 if (isVerboseLoggingEnabled()) { 5053 mLog.info("unregisterScanResultCallback uid=%").c(Binder.getCallingUid()).flush(); 5054 } 5055 enforceAccessPermission(); 5056 // post operation to handler thread 5057 mWifiThreadRunner.post(() -> mWifiInjector.getScanRequestProxy() 5058 .unregisterScanResultsCallback(callback)); 5059 5060 } 5061 5062 /** 5063 * See {@link WifiManager#addSuggestionConnectionStatusListener(Executor, 5064 * SuggestionConnectionStatusListener)} 5065 */ 5066 public void registerSuggestionConnectionStatusListener( 5067 @NonNull ISuggestionConnectionStatusListener listener, String packageName, 5068 @Nullable String featureId) { 5069 if (listener == null) { 5070 throw new IllegalArgumentException("listener must not be null"); 5071 } 5072 final int uid = Binder.getCallingUid(); 5073 mWifiPermissionsUtil.checkPackage(uid, packageName); 5074 enforceAccessPermission(); 5075 enforceLocationPermission(packageName, featureId, uid); 5076 if (isVerboseLoggingEnabled()) { 5077 mLog.info("registerSuggestionConnectionStatusListener uid=%").c(uid).flush(); 5078 } 5079 mWifiThreadRunner.post(() -> 5080 mWifiNetworkSuggestionsManager 5081 .registerSuggestionConnectionStatusListener(listener, packageName, uid)); 5082 } 5083 5084 /** 5085 * See {@link WifiManager#removeSuggestionConnectionStatusListener( 5086 * SuggestionConnectionStatusListener)} 5087 */ 5088 public void unregisterSuggestionConnectionStatusListener( 5089 @NonNull ISuggestionConnectionStatusListener listener, String packageName) { 5090 enforceAccessPermission(); 5091 int uid = Binder.getCallingUid(); 5092 if (isVerboseLoggingEnabled()) { 5093 mLog.info("unregisterSuggestionConnectionStatusListener uid=%") 5094 .c(uid).flush(); 5095 } 5096 mWifiThreadRunner.post(() -> 5097 mWifiNetworkSuggestionsManager 5098 .unregisterSuggestionConnectionStatusListener(listener, packageName, uid)); 5099 } 5100 5101 @Override 5102 public int calculateSignalLevel(int rssi) { 5103 return RssiUtil.calculateSignalLevel(mContext, rssi); 5104 } 5105 5106 /** 5107 * See {@link android.net.wifi.WifiManager#setWifiConnectedNetworkScorer(Executor, 5108 * WifiManager.WifiConnectedNetworkScorer)} 5109 * 5110 * @param binder IBinder instance to allow cleanup if the app dies. 5111 * @param scorer Wifi connected network scorer to set. 5112 * @return true Scorer is set successfully. 5113 * 5114 * @throws RemoteException if remote exception happens 5115 * @throws IllegalArgumentException if the arguments are null or invalid 5116 */ 5117 @Override 5118 public boolean setWifiConnectedNetworkScorer(IBinder binder, 5119 IWifiConnectedNetworkScorer scorer) { 5120 if (binder == null) { 5121 throw new IllegalArgumentException("Binder must not be null"); 5122 } 5123 if (scorer == null) { 5124 throw new IllegalArgumentException("Scorer must not be null"); 5125 } 5126 mContext.enforceCallingOrSelfPermission( 5127 android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE, "WifiService"); 5128 if (isVerboseLoggingEnabled()) { 5129 mLog.info("setWifiConnectedNetworkScorer uid=%").c(Binder.getCallingUid()).flush(); 5130 } 5131 // Post operation to handler thread 5132 return mWifiThreadRunner.call( 5133 () -> mActiveModeWarden.setWifiConnectedNetworkScorer(binder, scorer), false); 5134 } 5135 5136 /** 5137 * See {@link WifiManager#clearWifiConnectedNetworkScorer()} 5138 */ 5139 @Override 5140 public void clearWifiConnectedNetworkScorer() { 5141 mContext.enforceCallingOrSelfPermission( 5142 android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE, "WifiService"); 5143 if (isVerboseLoggingEnabled()) { 5144 mLog.info("clearWifiConnectedNetworkScorer uid=%").c(Binder.getCallingUid()).flush(); 5145 } 5146 // Post operation to handler thread 5147 mWifiThreadRunner.post(() -> mActiveModeWarden.clearWifiConnectedNetworkScorer()); 5148 } 5149 5150 /** 5151 * See {@link android.net.wifi.WifiManager#setScanThrottleEnabled(boolean)} 5152 */ 5153 @Override 5154 public void setScanThrottleEnabled(boolean enable) { 5155 enforceNetworkSettingsPermission(); 5156 mLog.info("setScanThrottleEnabled uid=% verbose=%") 5157 .c(Binder.getCallingUid()) 5158 .c(enable).flush(); 5159 mWifiThreadRunner.post(()-> mScanRequestProxy.setScanThrottleEnabled(enable)); 5160 } 5161 5162 /** 5163 * See {@link android.net.wifi.WifiManager#isScanThrottleEnabled()} 5164 */ 5165 @Override 5166 public boolean isScanThrottleEnabled() { 5167 enforceAccessPermission(); 5168 if (isVerboseLoggingEnabled()) { 5169 mLog.info("isScanThrottleEnabled uid=%").c(Binder.getCallingUid()).flush(); 5170 } 5171 return mWifiThreadRunner.call(()-> mScanRequestProxy.isScanThrottleEnabled(), true); 5172 } 5173 5174 /** 5175 * See {@link android.net.wifi.WifiManager#setAutoWakeupEnabled(boolean)} 5176 */ 5177 @Override 5178 public void setAutoWakeupEnabled(boolean enable) { 5179 enforceNetworkSettingsPermission(); 5180 mLog.info("setWalkeupEnabled uid=% verbose=%") 5181 .c(Binder.getCallingUid()) 5182 .c(enable).flush(); 5183 mWifiThreadRunner.post(()-> mWifiInjector.getWakeupController().setEnabled(enable)); 5184 } 5185 5186 /** 5187 * See {@link android.net.wifi.WifiManager#isAutoWakeupEnabled()} 5188 */ 5189 @Override 5190 public boolean isAutoWakeupEnabled() { 5191 enforceAccessPermission(); 5192 if (isVerboseLoggingEnabled()) { 5193 mLog.info("isAutoWakeupEnabled uid=%").c(Binder.getCallingUid()).flush(); 5194 } 5195 return mWifiThreadRunner.call(()-> mWifiInjector.getWakeupController().isEnabled(), false); 5196 } 5197 5198 /** 5199 * See {@link android.net.wifi.WifiManager#setCarrierNetworkOffloadEnabled(int, boolean, boolean)} 5200 */ 5201 @Override 5202 public void setCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged, 5203 boolean enabled) { 5204 if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { 5205 throw new SecurityException(TAG + ": Permission denied"); 5206 } 5207 if (isVerboseLoggingEnabled()) { 5208 mLog.info("setCarrierNetworkOffloadEnabled uid=%").c(Binder.getCallingUid()).flush(); 5209 } 5210 mWifiThreadRunner.post(() -> 5211 mWifiCarrierInfoManager.setCarrierNetworkOffloadEnabled(subscriptionId, merged, enabled)); 5212 } 5213 5214 /** 5215 * See {@link android.net.wifi.WifiManager#isCarrierNetworkOffloadEnabled(int, boolean)} 5216 */ 5217 @Override 5218 public boolean isCarrierNetworkOffloadEnabled(int subId, boolean merged) { 5219 enforceAccessPermission(); 5220 if (isVerboseLoggingEnabled()) { 5221 mLog.info("isCarrierNetworkOffload uid=%").c(Binder.getCallingUid()).flush(); 5222 } 5223 5224 return mWifiThreadRunner.call(()-> 5225 mWifiCarrierInfoManager.isCarrierNetworkOffloadEnabled(subId, merged), true); 5226 } 5227 5228 /** 5229 * See {@link android.net.wifi.WifiManager#addSuggestionUserApprovalStatusListener(Executor, 5230 * WifiManager.SuggestionUserApprovalStatusListener)} 5231 */ 5232 @Override 5233 public void addSuggestionUserApprovalStatusListener( 5234 ISuggestionUserApprovalStatusListener listener, String packageName) { 5235 if (listener == null) { 5236 throw new NullPointerException("listener must not be null"); 5237 } 5238 final int uid = Binder.getCallingUid(); 5239 enforceAccessPermission(); 5240 long callingIdentity = Binder.clearCallingIdentity(); 5241 try { 5242 if (!mWifiPermissionsUtil.doesUidBelongToCurrentUser(uid)) { 5243 Log.e(TAG, "UID " + uid + " not visible to the current user"); 5244 throw new SecurityException("UID " + uid + " not visible to the current user"); 5245 } 5246 } finally { 5247 // restore calling identity 5248 Binder.restoreCallingIdentity(callingIdentity); 5249 } 5250 if (isVerboseLoggingEnabled()) { 5251 mLog.info("addSuggestionUserApprovalStatusListener uid=%").c(uid).flush(); 5252 } 5253 mWifiThreadRunner.post(() -> mWifiNetworkSuggestionsManager 5254 .addSuggestionUserApprovalStatusListener(listener, packageName, uid)); 5255 } 5256 5257 /** 5258 * See {@link android.net.wifi.WifiManager#removeSuggestionUserApprovalStatusListener( 5259 * WifiManager.SuggestionUserApprovalStatusListener)} 5260 */ 5261 @Override 5262 public void removeSuggestionUserApprovalStatusListener( 5263 ISuggestionUserApprovalStatusListener listener, String packageName) { 5264 enforceAccessPermission(); 5265 int uid = Binder.getCallingUid(); 5266 long callingIdentity = Binder.clearCallingIdentity(); 5267 try { 5268 if (!mWifiPermissionsUtil.doesUidBelongToCurrentUser(uid)) { 5269 Log.e(TAG, "UID " + uid + " not visible to the current user"); 5270 throw new SecurityException("UID " + uid + " not visible to the current user"); 5271 } 5272 } finally { 5273 // restore calling identity 5274 Binder.restoreCallingIdentity(callingIdentity); 5275 } 5276 if (isVerboseLoggingEnabled()) { 5277 mLog.info("removeSuggestionUserApprovalStatusListener uid=%") 5278 .c(uid).flush(); 5279 } 5280 mWifiThreadRunner.post(() -> 5281 mWifiNetworkSuggestionsManager 5282 .removeSuggestionUserApprovalStatusListener(listener, packageName, uid)); 5283 } 5284 5285 /** 5286 * See {@link android.net.wifi.WifiManager#setEmergencyScanRequestInProgress(boolean)}. 5287 */ 5288 @Override 5289 public void setEmergencyScanRequestInProgress(boolean inProgress) { 5290 enforceNetworkStackPermission(); 5291 int uid = Binder.getCallingUid(); 5292 mLog.info("setEmergencyScanRequestInProgress uid=%").c(uid).flush(); 5293 mActiveModeWarden.setEmergencyScanRequestInProgress(inProgress); 5294 } 5295 5296 /** 5297 * See {@link android.net.wifi.WifiManager#removeAppState(int, String)}. 5298 */ 5299 @Override 5300 public void removeAppState(int targetAppUid, @NonNull String targetAppPackageName) { 5301 enforceNetworkSettingsPermission(); 5302 mLog.info("removeAppState uid=%").c(Binder.getCallingUid()).flush(); 5303 5304 mWifiThreadRunner.post(() -> { 5305 removeAppStateInternal(targetAppUid, targetAppPackageName); 5306 }); 5307 } 5308 5309 /** 5310 * See {@link android.net.wifi.WifiManager#setWifiScoringEnabled(boolean)}. 5311 */ 5312 @Override 5313 public boolean setWifiScoringEnabled(boolean enabled) { 5314 mContext.enforceCallingOrSelfPermission( 5315 android.Manifest.permission.NETWORK_SETTINGS, "WifiService"); 5316 // Post operation to handler thread 5317 return mWifiThreadRunner.call( 5318 () -> mSettingsStore.handleWifiScoringEnabled(enabled), false); 5319 } 5320 5321 @VisibleForTesting 5322 static boolean isValidBandForGetUsableChannels(@WifiScanner.WifiBand int band) { 5323 switch (band) { 5324 case WifiScanner.WIFI_BAND_UNSPECIFIED: 5325 case WifiScanner.WIFI_BAND_24_GHZ: 5326 case WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS: 5327 case WifiScanner.WIFI_BAND_BOTH_WITH_DFS: 5328 case WifiScanner.WIFI_BAND_6_GHZ: 5329 case WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_GHZ: 5330 case WifiScanner.WIFI_BAND_60_GHZ: 5331 case WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_60_GHZ: 5332 return true; 5333 default: 5334 return false; 5335 } 5336 } 5337 5338 /** 5339 * See {@link android.net.wifi.WifiManager#getUsableChannels(int, int) and 5340 * See {@link android.net.wifi.WifiManager#getAllowedChannels(int, int). 5341 * 5342 * @throws SecurityException if the caller does not have permission 5343 * or IllegalArgumentException if the band is invalid for this method. 5344 */ 5345 @Override 5346 public List<WifiAvailableChannel> getUsableChannels(@WifiScanner.WifiBand int band, 5347 @WifiAvailableChannel.OpMode int mode, @WifiAvailableChannel.Filter int filter) { 5348 // Location mode must be enabled 5349 if (!mWifiPermissionsUtil.isLocationModeEnabled()) { 5350 throw new SecurityException("Location mode is disabled for the device"); 5351 } 5352 final int uid = Binder.getCallingUid(); 5353 if (isVerboseLoggingEnabled()) { 5354 mLog.info("getUsableChannels uid=%").c(Binder.getCallingUid()).flush(); 5355 } 5356 if (!mWifiPermissionsUtil.checkCallersHardwareLocationPermission(uid)) { 5357 throw new SecurityException("UID " + uid + " does not have location h/w permission"); 5358 } 5359 if (!isValidBandForGetUsableChannels(band)) { 5360 throw new IllegalArgumentException("Unsupported band: " + band); 5361 } 5362 List<WifiAvailableChannel> channels = mWifiThreadRunner.call( 5363 () -> mWifiNative.getUsableChannels(band, mode, filter), null); 5364 if (channels == null) { 5365 throw new UnsupportedOperationException(); 5366 } 5367 return channels; 5368 } 5369 5370 private void resetNotificationManager() { 5371 mWifiInjector.getWifiNotificationManager().createNotificationChannels(); 5372 mWifiInjector.getOpenNetworkNotifier().clearPendingNotification(false); 5373 mWifiCarrierInfoManager.resetNotification(); 5374 mWifiNetworkSuggestionsManager.resetNotification(); 5375 mWifiInjector.getWakeupController().resetNotification(); 5376 } 5377 5378 /** 5379 * See {@link android.net.wifi.WifiManager#flushPasspointAnqpCache()}. 5380 */ 5381 @Override 5382 public void flushPasspointAnqpCache(@NonNull String packageName) { 5383 mWifiPermissionsUtil.checkPackage(Binder.getCallingUid(), packageName); 5384 5385 if (!isDeviceOrProfileOwner(Binder.getCallingUid(), packageName)) { 5386 enforceAnyPermissionOf(android.Manifest.permission.NETWORK_SETTINGS, 5387 android.Manifest.permission.NETWORK_MANAGED_PROVISIONING, 5388 android.Manifest.permission.NETWORK_CARRIER_PROVISIONING); 5389 } 5390 mWifiThreadRunner.post(mPasspointManager::clearAnqpRequestsAndFlushCache); 5391 } 5392 } 5393