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.ScanResult.WIFI_BAND_24_GHZ; 22 import static android.net.wifi.ScanResult.WIFI_BAND_5_GHZ; 23 import static android.net.wifi.ScanResult.WIFI_BAND_6_GHZ; 24 import static android.net.wifi.WifiManager.CHANNEL_DATA_KEY_FREQUENCY_MHZ; 25 import static android.net.wifi.WifiManager.CHANNEL_DATA_KEY_NUM_AP; 26 import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED; 27 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_GENERIC; 28 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_NO_CHANNEL; 29 import static android.net.wifi.WifiManager.NOT_OVERRIDE_EXISTING_NETWORKS_ON_RESTORE; 30 import static android.net.wifi.WifiManager.PnoScanResultsCallback.REGISTER_PNO_CALLBACK_PNO_NOT_SUPPORTED; 31 import static android.net.wifi.WifiManager.ROAMING_MODE_AGGRESSIVE; 32 import static android.net.wifi.WifiManager.SAP_START_FAILURE_GENERAL; 33 import static android.net.wifi.WifiManager.SAP_START_FAILURE_NO_CHANNEL; 34 import static android.net.wifi.WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS; 35 import static android.net.wifi.WifiManager.VERBOSE_LOGGING_LEVEL_WIFI_AWARE_ENABLED_ONLY; 36 import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED; 37 import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING; 38 import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED; 39 import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING; 40 import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED; 41 import static android.net.wifi.WifiManager.WIFI_INTERFACE_TYPE_AP; 42 import static android.net.wifi.WifiManager.WIFI_INTERFACE_TYPE_AWARE; 43 import static android.net.wifi.WifiManager.WIFI_INTERFACE_TYPE_DIRECT; 44 import static android.net.wifi.WifiManager.WIFI_INTERFACE_TYPE_STA; 45 import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED; 46 import static android.net.wifi.WifiManager.WifiStateChangedListener; 47 import static android.os.Process.WIFI_UID; 48 49 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_LOCAL_ONLY; 50 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_LONG_LIVED; 51 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_TRANSIENT; 52 import static com.android.server.wifi.ClientModeImpl.RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED; 53 import static com.android.server.wifi.ClientModeImpl.RESET_SIM_REASON_SIM_INSERTED; 54 import static com.android.server.wifi.ClientModeImpl.RESET_SIM_REASON_SIM_REMOVED; 55 import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_AP; 56 import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_AP_BRIDGE; 57 import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_NAN; 58 import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_P2P; 59 import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_STA; 60 import static com.android.server.wifi.ScanRequestProxy.createBroadcastOptionsForScanResultsAvailable; 61 import static com.android.server.wifi.SelfRecovery.REASON_API_CALL; 62 import static com.android.server.wifi.WifiSettingsConfigStore.D2D_ALLOWED_WHEN_INFRA_STA_DISABLED; 63 import static com.android.server.wifi.WifiSettingsConfigStore.SHOW_DIALOG_WHEN_THIRD_PARTY_APPS_ENABLE_WIFI; 64 import static com.android.server.wifi.WifiSettingsConfigStore.SHOW_DIALOG_WHEN_THIRD_PARTY_APPS_ENABLE_WIFI_SET_BY_API; 65 import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_AWARE_VERBOSE_LOGGING_ENABLED; 66 import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_STA_FACTORY_MAC_ADDRESS; 67 import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_VERBOSE_LOGGING_ENABLED; 68 import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_WEP_ALLOWED; 69 70 import android.Manifest; 71 import android.annotation.AnyThread; 72 import android.annotation.CheckResult; 73 import android.annotation.IntDef; 74 import android.annotation.NonNull; 75 import android.annotation.Nullable; 76 import android.app.AppOpsManager; 77 import android.app.admin.DevicePolicyManager; 78 import android.app.admin.WifiSsidPolicy; 79 import android.app.compat.CompatChanges; 80 import android.bluetooth.BluetoothAdapter; 81 import android.content.AttributionSource; 82 import android.content.BroadcastReceiver; 83 import android.content.ComponentName; 84 import android.content.Context; 85 import android.content.Intent; 86 import android.content.IntentFilter; 87 import android.content.ServiceConnection; 88 import android.content.pm.ApplicationInfo; 89 import android.content.pm.PackageInfo; 90 import android.content.pm.PackageManager; 91 import android.content.pm.ResolveInfo; 92 import android.content.res.Resources; 93 import android.hardware.wifi.WifiStatusCode; 94 import android.location.LocationManager; 95 import android.net.DhcpInfo; 96 import android.net.DhcpOption; 97 import android.net.DhcpResultsParcelable; 98 import android.net.InetAddresses; 99 import android.net.MacAddress; 100 import android.net.Network; 101 import android.net.NetworkCapabilities; 102 import android.net.NetworkStack; 103 import android.net.TetheringManager; 104 import android.net.Uri; 105 import android.net.ip.IpClientUtil; 106 import android.net.thread.ThreadNetworkController; 107 import android.net.thread.ThreadNetworkManager; 108 import android.net.wifi.BlockingOption; 109 import android.net.wifi.CoexUnsafeChannel; 110 import android.net.wifi.IActionListener; 111 import android.net.wifi.IBooleanListener; 112 import android.net.wifi.IByteArrayListener; 113 import android.net.wifi.ICoexCallback; 114 import android.net.wifi.IDppCallback; 115 import android.net.wifi.IIntegerListener; 116 import android.net.wifi.IInterfaceCreationInfoCallback; 117 import android.net.wifi.ILastCallerListener; 118 import android.net.wifi.IListListener; 119 import android.net.wifi.ILocalOnlyConnectionStatusListener; 120 import android.net.wifi.ILocalOnlyHotspotCallback; 121 import android.net.wifi.IMacAddressListListener; 122 import android.net.wifi.IMapListener; 123 import android.net.wifi.INetworkRequestMatchCallback; 124 import android.net.wifi.IOnWifiActivityEnergyInfoListener; 125 import android.net.wifi.IOnWifiDriverCountryCodeChangedListener; 126 import android.net.wifi.IOnWifiUsabilityStatsListener; 127 import android.net.wifi.IPnoScanResultsCallback; 128 import android.net.wifi.IScanResultsCallback; 129 import android.net.wifi.ISoftApCallback; 130 import android.net.wifi.IStringListener; 131 import android.net.wifi.ISubsystemRestartCallback; 132 import android.net.wifi.ISuggestionConnectionStatusListener; 133 import android.net.wifi.ISuggestionUserApprovalStatusListener; 134 import android.net.wifi.ITrafficStateCallback; 135 import android.net.wifi.ITwtCallback; 136 import android.net.wifi.ITwtCapabilitiesListener; 137 import android.net.wifi.ITwtStatsListener; 138 import android.net.wifi.IWifiBandsListener; 139 import android.net.wifi.IWifiConnectedNetworkScorer; 140 import android.net.wifi.IWifiLowLatencyLockListener; 141 import android.net.wifi.IWifiManager; 142 import android.net.wifi.IWifiNetworkSelectionConfigListener; 143 import android.net.wifi.IWifiNetworkStateChangedListener; 144 import android.net.wifi.IWifiStateChangedListener; 145 import android.net.wifi.IWifiVerboseLoggingStatusChangedListener; 146 import android.net.wifi.MscsParams; 147 import android.net.wifi.QosPolicyParams; 148 import android.net.wifi.ScanResult; 149 import android.net.wifi.SoftApCapability; 150 import android.net.wifi.SoftApConfiguration; 151 import android.net.wifi.SoftApInfo; 152 import android.net.wifi.SoftApState; 153 import android.net.wifi.WifiAnnotations.WifiStandard; 154 import android.net.wifi.WifiAvailableChannel; 155 import android.net.wifi.WifiBands; 156 import android.net.wifi.WifiClient; 157 import android.net.wifi.WifiConfiguration; 158 import android.net.wifi.WifiContext; 159 import android.net.wifi.WifiInfo; 160 import android.net.wifi.WifiManager; 161 import android.net.wifi.WifiManager.AddNetworkResult; 162 import android.net.wifi.WifiManager.CoexRestriction; 163 import android.net.wifi.WifiManager.DeviceMobilityState; 164 import android.net.wifi.WifiManager.LocalOnlyHotspotCallback; 165 import android.net.wifi.WifiManager.RoamingMode; 166 import android.net.wifi.WifiManager.SapClientBlockedReason; 167 import android.net.wifi.WifiManager.SuggestionConnectionStatusListener; 168 import android.net.wifi.WifiNetworkSelectionConfig; 169 import android.net.wifi.WifiNetworkSuggestion; 170 import android.net.wifi.WifiScanner; 171 import android.net.wifi.WifiSsid; 172 import android.net.wifi.hotspot2.IProvisioningCallback; 173 import android.net.wifi.hotspot2.OsuProvider; 174 import android.net.wifi.hotspot2.PasspointConfiguration; 175 import android.net.wifi.twt.TwtRequest; 176 import android.net.wifi.twt.TwtSession; 177 import android.net.wifi.twt.TwtSessionCallback; 178 import android.net.wifi.util.Environment; 179 import android.net.wifi.util.ScanResultUtil; 180 import android.net.wifi.util.WifiResourceCache; 181 import android.os.AsyncTask; 182 import android.os.Binder; 183 import android.os.Build; 184 import android.os.Bundle; 185 import android.os.Handler; 186 import android.os.HandlerThread; 187 import android.os.IBinder; 188 import android.os.Looper; 189 import android.os.ParcelFileDescriptor; 190 import android.os.PersistableBundle; 191 import android.os.PowerManager; 192 import android.os.Process; 193 import android.os.RemoteCallbackList; 194 import android.os.RemoteException; 195 import android.os.UserHandle; 196 import android.os.UserManager; 197 import android.os.WorkSource; 198 import android.os.connectivity.WifiActivityEnergyInfo; 199 import android.provider.Settings; 200 import android.telephony.CarrierConfigManager; 201 import android.telephony.PhoneStateListener; 202 import android.telephony.SubscriptionManager; 203 import android.telephony.TelephonyManager; 204 import android.text.TextUtils; 205 import android.util.ArraySet; 206 import android.util.EventLog; 207 import android.util.Log; 208 import android.util.Pair; 209 import android.util.SparseArray; 210 import android.util.SparseIntArray; 211 import android.uwb.UwbManager; 212 213 import androidx.annotation.RequiresApi; 214 215 import com.android.internal.annotations.GuardedBy; 216 import com.android.internal.annotations.VisibleForTesting; 217 import com.android.modules.utils.HandlerExecutor; 218 import com.android.modules.utils.ParceledListSlice; 219 import com.android.modules.utils.StringParceledListSlice; 220 import com.android.modules.utils.build.SdkLevel; 221 import com.android.net.module.util.Inet4AddressUtils; 222 import com.android.server.wifi.coex.CoexManager; 223 import com.android.server.wifi.entitlement.PseudonymInfo; 224 import com.android.server.wifi.hotspot2.PasspointManager; 225 import com.android.server.wifi.hotspot2.PasspointProvider; 226 import com.android.server.wifi.proto.WifiStatsLog; 227 import com.android.server.wifi.proto.nano.WifiMetricsProto.UserActionEvent; 228 import com.android.server.wifi.util.ActionListenerWrapper; 229 import com.android.server.wifi.util.ApConfigUtil; 230 import com.android.server.wifi.util.FeatureBitsetUtils; 231 import com.android.server.wifi.util.GeneralUtil.Mutable; 232 import com.android.server.wifi.util.LastCallerInfoManager; 233 import com.android.server.wifi.util.RssiUtil; 234 import com.android.server.wifi.util.WifiPermissionsUtil; 235 import com.android.server.wifi.util.WorkSourceHelper; 236 import com.android.wifi.flags.FeatureFlags; 237 import com.android.wifi.resources.R; 238 239 import org.json.JSONArray; 240 import org.json.JSONException; 241 242 import java.io.BufferedReader; 243 import java.io.FileDescriptor; 244 import java.io.FileNotFoundException; 245 import java.io.FileReader; 246 import java.io.IOException; 247 import java.io.PrintWriter; 248 import java.lang.annotation.Retention; 249 import java.lang.annotation.RetentionPolicy; 250 import java.net.Inet4Address; 251 import java.net.InetAddress; 252 import java.security.GeneralSecurityException; 253 import java.security.KeyStore; 254 import java.security.cert.CertPath; 255 import java.security.cert.CertPathValidator; 256 import java.security.cert.CertificateFactory; 257 import java.security.cert.PKIXParameters; 258 import java.security.cert.X509Certificate; 259 import java.util.ArrayList; 260 import java.util.Arrays; 261 import java.util.BitSet; 262 import java.util.Collections; 263 import java.util.HashMap; 264 import java.util.HashSet; 265 import java.util.List; 266 import java.util.Map; 267 import java.util.Objects; 268 import java.util.Optional; 269 import java.util.Set; 270 import java.util.concurrent.CountDownLatch; 271 import java.util.concurrent.Executor; 272 import java.util.concurrent.TimeUnit; 273 import java.util.function.BiConsumer; 274 import java.util.function.Consumer; 275 import java.util.function.IntConsumer; 276 277 /** 278 * WifiService handles remote WiFi operation requests by implementing 279 * the IWifiManager interface. 280 */ 281 public class WifiServiceImpl extends IWifiManager.Stub { 282 private static final String TAG = "WifiService"; 283 private static final boolean VDBG = false; 284 285 /** Max wait time for posting blocking runnables */ 286 private static final int RUN_WITH_SCISSORS_TIMEOUT_MILLIS = 4000; 287 @VisibleForTesting 288 static final int AUTO_DISABLE_SHOW_KEY_COUNTDOWN_MILLIS = 24 * 60 * 60 * 1000; 289 private static final int CHANNEL_USAGE_WEAK_SCAN_RSSI_DBM = -80; 290 291 private static final int SCORER_BINDING_STATE_INVALID = -1; 292 // The system is brining up the scorer service. 293 private static final int SCORER_BINDING_STATE_BRINGING_UP = 0; 294 private static final int SCORER_BINDING_STATE_CONNECTED = 1; 295 private static final int SCORER_BINDING_STATE_DISCONNECTED = 2; 296 private static final int SCORER_BINDING_STATE_BINDING_DIED = 3; 297 // A null binder is received. 298 private static final int SCORER_BINDING_STATE_NULL_BINDING = 4; 299 // The system couldn't find the service to bind to. 300 private static final int SCORER_BINDING_STATE_NO_SERVICE = 5; 301 // The app has cleared the Wi-Fi scorer. So the service is unbound. 302 private static final int SCORER_BINDING_STATE_CLEARED = 6; 303 // The app has set a new Wi-Fi scorer. Rebind to the service. 304 public static final int SCORER_BINDING_STATE_REBINDING = 7; 305 306 @IntDef(prefix = { "SCORER_BINDING_STATE_" }, value = { 307 SCORER_BINDING_STATE_INVALID, 308 SCORER_BINDING_STATE_BRINGING_UP, 309 SCORER_BINDING_STATE_CONNECTED, 310 SCORER_BINDING_STATE_DISCONNECTED, 311 SCORER_BINDING_STATE_BINDING_DIED, 312 SCORER_BINDING_STATE_NULL_BINDING, 313 SCORER_BINDING_STATE_NO_SERVICE, 314 SCORER_BINDING_STATE_CLEARED, 315 SCORER_BINDING_STATE_REBINDING 316 317 }) 318 @Retention(RetentionPolicy.SOURCE) 319 private @interface ScorerBindingState {} 320 321 private @ScorerBindingState int mLastScorerBindingState = SCORER_BINDING_STATE_INVALID; 322 @VisibleForTesting 323 ScorerServiceConnection mScorerServiceConnection; 324 325 private final ActiveModeWarden mActiveModeWarden; 326 private final ScanRequestProxy mScanRequestProxy; 327 328 private final WifiContext mContext; 329 private final FrameworkFacade mFacade; 330 private final Clock mClock; 331 private final PowerManager mPowerManager; 332 private final AppOpsManager mAppOps; 333 private final UserManager mUserManager; 334 private final WifiCountryCode mCountryCode; 335 336 /** Polls traffic stats and notifies clients */ 337 private final WifiTrafficPoller mWifiTrafficPoller; 338 /** Tracks the persisted states for wi-fi & airplane mode */ 339 private final WifiSettingsStore mSettingsStore; 340 /** Logs connection events and some general router and scan stats */ 341 private final WifiMetrics mWifiMetrics; 342 343 private final WifiInjector mWifiInjector; 344 /** Backup/Restore Module */ 345 private final WifiBackupRestore mWifiBackupRestore; 346 private final SoftApBackupRestore mSoftApBackupRestore; 347 private final WifiSettingsBackupRestore mWifiSettingsBackupRestore; 348 private final BackupRestoreController mBackupRestoreController; 349 private final CoexManager mCoexManager; 350 private final WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager; 351 private final WifiConfigManager mWifiConfigManager; 352 private final HalDeviceManager mHalDeviceManager; 353 private final WifiBlocklistMonitor mWifiBlocklistMonitor; 354 private final PasspointManager mPasspointManager; 355 private final WifiLog mLog; 356 private final WifiConnectivityManager mWifiConnectivityManager; 357 private final ConnectHelper mConnectHelper; 358 private final WifiGlobals mWifiGlobals; 359 private final WifiCarrierInfoManager mWifiCarrierInfoManager; 360 private final WifiPseudonymManager mWifiPseudonymManager; 361 private final WifiNetworkFactory mWifiNetworkFactory; 362 private @WifiManager.VerboseLoggingLevel int mVerboseLoggingLevel = 363 WifiManager.VERBOSE_LOGGING_LEVEL_DISABLED; 364 private boolean mVerboseLoggingEnabled = false; 365 private final RemoteCallbackList<IWifiVerboseLoggingStatusChangedListener> 366 mRegisteredWifiLoggingStatusListeners = new RemoteCallbackList<>(); 367 368 private final FrameworkFacade mFrameworkFacade; 369 370 private final WifiPermissionsUtil mWifiPermissionsUtil; 371 372 private final TetheredSoftApTracker mTetheredSoftApTracker; 373 374 private final LohsSoftApTracker mLohsSoftApTracker; 375 376 private final BuildProperties mBuildProperties; 377 378 private final DefaultClientModeManager mDefaultClientModeManager; 379 380 private final WepNetworkUsageController mWepNetworkUsageController; 381 382 private final FeatureFlags mFeatureFlags; 383 @VisibleForTesting 384 public final CountryCodeTracker mCountryCodeTracker; 385 private final MultiInternetManager mMultiInternetManager; 386 private final DeviceConfigFacade mDeviceConfigFacade; 387 private boolean mIsWifiServiceStarted = false; 388 private static final String PACKAGE_NAME_NOT_AVAILABLE = "Not Available"; 389 private static final String CERT_INSTALLER_PKG = "com.android.certinstaller"; 390 391 private final WifiSettingsConfigStore mSettingsConfigStore; 392 private final WifiResourceCache mResourceCache; 393 private boolean mIsUsdSupported = false; 394 395 /** 396 * Callback for use with LocalOnlyHotspot to unregister requesting applications upon death. 397 */ 398 public final class LocalOnlyRequestorCallback 399 implements LocalOnlyHotspotRequestInfo.RequestingApplicationDeathCallback { 400 /** 401 * Called with requesting app has died. 402 */ 403 @Override onLocalOnlyHotspotRequestorDeath(LocalOnlyHotspotRequestInfo requestor)404 public void onLocalOnlyHotspotRequestorDeath(LocalOnlyHotspotRequestInfo requestor) { 405 mLog.trace("onLocalOnlyHotspotRequestorDeath pid=%") 406 .c(requestor.getPid()).flush(); 407 mLohsSoftApTracker.stopByRequest(requestor); 408 } 409 } 410 411 /** 412 * Listen for phone call state events to get active data subcription id. 413 */ 414 private class WifiPhoneStateListener extends PhoneStateListener { WifiPhoneStateListener(Looper looper)415 WifiPhoneStateListener(Looper looper) { 416 super(new HandlerExecutor(new Handler(looper))); 417 } 418 419 @Override onActiveDataSubscriptionIdChanged(int subId)420 public void onActiveDataSubscriptionIdChanged(int subId) { 421 // post operation to handler thread 422 mWifiThreadRunner.post(() -> { 423 Log.d(TAG, "OBSERVED active data subscription change, subId: " + subId); 424 mTetheredSoftApTracker.updateSoftApCapabilityWhenCarrierConfigChanged(subId); 425 mActiveModeWarden.updateSoftApCapability( 426 mTetheredSoftApTracker.getSoftApCapability(), 427 WifiManager.IFACE_IP_MODE_TETHERED); 428 }, this.getClass().getSimpleName() + "#onActiveDataSubscriptionIdChanged"); 429 } 430 } 431 432 private class ScorerServiceConnection implements ServiceConnection { 433 @Override onServiceConnected(ComponentName name, IBinder binder)434 public void onServiceConnected(ComponentName name, IBinder binder) { 435 Log.i(TAG, "ScorerServiceConnection.onServiceConnected(" + name + ", " + binder + ")"); 436 if (binder == null) { 437 mWifiThreadRunner.post(() -> unbindScorerService(SCORER_BINDING_STATE_NULL_BINDING), 438 "ScorerServiceConnection#onServiceConnected"); 439 } else { 440 mWifiThreadRunner.post(() -> { 441 mLastScorerBindingState = SCORER_BINDING_STATE_CONNECTED; 442 }, "ScorerServiceConnection#onServiceConnected"); 443 } 444 } 445 @Override onServiceDisconnected(ComponentName name)446 public void onServiceDisconnected(ComponentName name) { 447 Log.w(TAG, "ScorerServiceConnection.onServiceDisconnected(" + name + ")"); 448 mWifiThreadRunner.post(() -> unbindScorerService(SCORER_BINDING_STATE_DISCONNECTED), 449 "ScorerServiceConnection#onServiceDisconnected"); 450 } 451 452 @Override onBindingDied(ComponentName name)453 public void onBindingDied(ComponentName name) { 454 Log.w(TAG, "ScorerServiceConnection.onBindingDied(" + name + ")"); 455 mWifiThreadRunner.post(() -> unbindScorerService(SCORER_BINDING_STATE_BINDING_DIED), 456 "ScorerServiceConnection#onBindingDied"); 457 } 458 459 @Override onNullBinding(ComponentName name)460 public void onNullBinding(ComponentName name) { 461 Log.i(TAG, "Wifi scorer service " + name + " - onNullBinding"); 462 mWifiThreadRunner.post(() -> unbindScorerService(SCORER_BINDING_STATE_NULL_BINDING), 463 "ScorerServiceConnection#onNullBinding"); 464 } 465 } 466 467 /** 468 * Bind to the scorer service to prevent the process of the external scorer from freezing. 469 */ bindScorerService(int scorerUid)470 private void bindScorerService(int scorerUid) { 471 if (mScorerServiceConnection != null) { 472 Log.i(TAG, "bindScorerService() service is already bound. Unbind it now."); 473 unbindScorerService(SCORER_BINDING_STATE_REBINDING); 474 } 475 476 mLastScorerBindingState = SCORER_BINDING_STATE_NO_SERVICE; 477 PackageManager pm = mContext.getPackageManager(); 478 if (pm == null) { 479 Log.e(TAG, "PackageManager is null!"); 480 return; 481 } else { 482 String[] packageNames = pm.getPackagesForUid(scorerUid); 483 for (String packageName : packageNames) { 484 if (!TextUtils.isEmpty(packageName)) { 485 mScorerServiceConnection = new ScorerServiceConnection(); 486 if (bindScorerServiceAsSystemUser(packageName, mScorerServiceConnection)) { 487 mLastScorerBindingState = SCORER_BINDING_STATE_BRINGING_UP; 488 return; 489 } else { 490 unbindScorerService(SCORER_BINDING_STATE_NO_SERVICE); 491 } 492 } else { 493 Log.d(TAG, "bindScorerService() packageName is empty"); 494 } 495 } 496 } 497 } 498 bindScorerServiceAsSystemUser(@onNull String packageName, @NonNull ServiceConnection serviceConnection)499 private boolean bindScorerServiceAsSystemUser(@NonNull String packageName, 500 @NonNull ServiceConnection serviceConnection) { 501 Intent intent = new Intent("android.wifi.ScorerService"); 502 intent.setPackage(packageName); 503 try { 504 if (mContext.bindServiceAsUser(intent, serviceConnection, 505 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, 506 UserHandle.SYSTEM)) { 507 Log.i(TAG, "bindScorerServiceAsSystemUser(): Bringing up service: " + packageName); 508 return true; 509 } 510 } catch (SecurityException ex) { 511 Log.e(TAG, "Fail to bindServiceAsSystemUser(): " + ex); 512 } catch (Exception ex) { 513 // Just make sure that it won't crash WiFi process 514 Log.e(TAG, "Fail to bindServiceAsSystemUser(): " + ex); 515 } 516 return false; 517 } 518 519 /** 520 * Unbind scorer service to let the system freeze the process of the external scorer freely. 521 */ unbindScorerService(@corerBindingState int state)522 private void unbindScorerService(@ScorerBindingState int state) { 523 mLastScorerBindingState = state; 524 if (mScorerServiceConnection != null) { 525 Log.i(TAG, "unbindScorerService(" + state + ")"); 526 try { 527 mContext.unbindService(mScorerServiceConnection); 528 } catch (Exception e) { 529 Log.e(TAG, "Fail to unbindService! " + e); 530 } 531 mScorerServiceConnection = null; 532 } else { 533 Log.i(TAG, "unbindScorerService(" + state 534 + ") mScorerServiceConnection is already null."); 535 } 536 } 537 538 private final WifiLockManager mWifiLockManager; 539 private final WifiMulticastLockManager mWifiMulticastLockManager; 540 private final DppManager mDppManager; 541 private final WifiApConfigStore mWifiApConfigStore; 542 private final WifiThreadRunner mWifiThreadRunner; 543 private final HandlerThread mWifiHandlerThread; 544 private final MemoryStoreImpl mMemoryStoreImpl; 545 private final WifiScoreCard mWifiScoreCard; 546 private final WifiHealthMonitor mWifiHealthMonitor; 547 private final WifiDataStall mWifiDataStall; 548 private final WifiNative mWifiNative; 549 private final SimRequiredNotifier mSimRequiredNotifier; 550 private final MakeBeforeBreakManager mMakeBeforeBreakManager; 551 private final LastCallerInfoManager mLastCallerInfoManager; 552 private final @NonNull WifiDialogManager mWifiDialogManager; 553 private final WifiPulledAtomLogger mWifiPulledAtomLogger; 554 555 private final SparseArray<WifiDialogManager.DialogHandle> mWifiEnableRequestDialogHandles = 556 new SparseArray<>(); 557 558 private boolean mWifiTetheringDisallowed; 559 private boolean mIsBootComplete; 560 private boolean mIsLocationModeEnabled; 561 562 private WifiNetworkSelectionConfig mNetworkSelectionConfig; 563 private ApplicationQosPolicyRequestHandler mApplicationQosPolicyRequestHandler; 564 private final AfcManager mAfcManager; 565 private final TwtManager mTwtManager; 566 567 /** 568 * The wrapper of SoftApCallback is used in WifiService internally. 569 * see: {@code WifiManager.SoftApCallback} 570 */ 571 public abstract class SoftApCallbackInternal { 572 /** 573 * see: {@code WifiManager.SoftApCallback#onStateChanged(int, int)} 574 */ onStateChanged(SoftApState state)575 void onStateChanged(SoftApState state) {} 576 577 /** 578 * The callback which only is used in service internally and pass to WifiManager. 579 * It will base on the change to send corresponding callback as below: 580 * 1. onInfoChanged(SoftApInfo) 581 * 2. onInfoChanged(List<SoftApInfo>) 582 * 3. onConnectedClientsChanged(SoftApInfo, List<WifiClient>) 583 * 4. onConnectedClientsChanged(List<WifiClient>) 584 */ onConnectedClientsOrInfoChanged(Map<String, SoftApInfo> infos, Map<String, List<WifiClient>> clients, boolean isBridged)585 void onConnectedClientsOrInfoChanged(Map<String, SoftApInfo> infos, 586 Map<String, List<WifiClient>> clients, boolean isBridged) {} 587 588 /** 589 * see: 590 * {@code WifiManager.SoftApCallback#onClientsDisconnected(SoftApInfo, 591 * List<WifiClient>)} 592 */ onClientsDisconnected(@onNull SoftApInfo info, @NonNull List<WifiClient> clients)593 void onClientsDisconnected(@NonNull SoftApInfo info, 594 @NonNull List<WifiClient> clients) {} 595 596 /** 597 * see: {@code WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)} 598 */ onCapabilityChanged(@onNull SoftApCapability softApCapability)599 void onCapabilityChanged(@NonNull SoftApCapability softApCapability) {} 600 601 /** 602 * see: {@code WifiManager.SoftApCallback#onBlockedClientConnecting(WifiClient, int)} 603 */ onBlockedClientConnecting(@onNull WifiClient client, @SapClientBlockedReason int blockedReason)604 void onBlockedClientConnecting(@NonNull WifiClient client, 605 @SapClientBlockedReason int blockedReason) {} 606 607 /** 608 * Checks the AttributionSource of a callback and returns true if the AttributionSource 609 * has the correct permissions. This should be extended by child classes. 610 */ checkCallbackPermission(@ullable Object broadcastCookie)611 boolean checkCallbackPermission(@Nullable Object broadcastCookie) { 612 return true; 613 } 614 615 /** 616 * Notify register the state of soft AP changed. 617 */ notifyRegisterOnStateChanged(RemoteCallbackList<ISoftApCallback> callbacks, SoftApState state)618 public void notifyRegisterOnStateChanged(RemoteCallbackList<ISoftApCallback> callbacks, 619 SoftApState state) { 620 int itemCount = callbacks.beginBroadcast(); 621 for (int i = 0; i < itemCount; i++) { 622 try { 623 if (!checkCallbackPermission(callbacks.getBroadcastCookie(i))) { 624 continue; 625 } 626 callbacks.getBroadcastItem(i).onStateChanged(state); 627 } catch (RemoteException e) { 628 Log.e(TAG, "onStateChanged: remote exception -- " + e); 629 } 630 } 631 callbacks.finishBroadcast(); 632 } 633 634 /** 635 * Notify register the connected clients to soft AP changed. 636 * 637 * @param clients connected clients to soft AP 638 */ notifyRegisterOnConnectedClientsOrInfoChanged( RemoteCallbackList<ISoftApCallback> callbacks, Map<String, SoftApInfo> infos, Map<String, List<WifiClient>> clients, boolean isBridged)639 public void notifyRegisterOnConnectedClientsOrInfoChanged( 640 RemoteCallbackList<ISoftApCallback> callbacks, Map<String, SoftApInfo> infos, 641 Map<String, List<WifiClient>> clients, boolean isBridged) { 642 int itemCount = callbacks.beginBroadcast(); 643 for (int i = 0; i < itemCount; i++) { 644 try { 645 if (!checkCallbackPermission(callbacks.getBroadcastCookie(i))) { 646 continue; 647 } 648 callbacks.getBroadcastItem(i).onConnectedClientsOrInfoChanged( 649 ApConfigUtil.deepCopyForSoftApInfoMap(infos), 650 ApConfigUtil.deepCopyForWifiClientListMap( 651 clients), isBridged, false); 652 } catch (RemoteException e) { 653 Log.e(TAG, "onConnectedClientsOrInfoChanged: remote exception -- " + e); 654 } 655 } 656 callbacks.finishBroadcast(); 657 } 658 659 /** 660 * Notify register capability of softap changed. 661 * 662 * @param capability is the softap capability. {@link SoftApCapability} 663 */ notifyRegisterOnCapabilityChanged(RemoteCallbackList<ISoftApCallback> callbacks, SoftApCapability capability)664 public void notifyRegisterOnCapabilityChanged(RemoteCallbackList<ISoftApCallback> callbacks, 665 SoftApCapability capability) { 666 int itemCount = callbacks.beginBroadcast(); 667 for (int i = 0; i < itemCount; i++) { 668 try { 669 if (!checkCallbackPermission(callbacks.getBroadcastCookie(i))) { 670 continue; 671 } 672 callbacks.getBroadcastItem(i).onCapabilityChanged(capability); 673 } catch (RemoteException e) { 674 Log.e(TAG, "onCapabilityChanged: remote exception -- " + e); 675 } 676 } 677 callbacks.finishBroadcast(); 678 } 679 680 /** 681 * Notify register there was a client trying to connect but device blocked the client with 682 * specific reason. 683 * 684 * @param client the currently blocked client. 685 * @param blockedReason one of blocked reason from 686 * {@link SapClientBlockedReason} 687 */ notifyRegisterOnBlockedClientConnecting( RemoteCallbackList<ISoftApCallback> callbacks, WifiClient client, int blockedReason)688 public void notifyRegisterOnBlockedClientConnecting( 689 RemoteCallbackList<ISoftApCallback> callbacks, WifiClient client, 690 int blockedReason) { 691 int itemCount = callbacks.beginBroadcast(); 692 for (int i = 0; i < itemCount; i++) { 693 try { 694 if (!checkCallbackPermission(callbacks.getBroadcastCookie(i))) { 695 continue; 696 } 697 callbacks.getBroadcastItem(i).onBlockedClientConnecting(client, blockedReason); 698 } catch (RemoteException e) { 699 Log.e(TAG, "onBlockedClientConnecting: remote exception -- " + e); 700 } 701 } 702 callbacks.finishBroadcast(); 703 } 704 705 /** 706 * Notify register that clients have disconnected from a soft AP instance. 707 * 708 * @param info The {@link SoftApInfo} of the AP. 709 * @param clients The clients that have disconnected from the AP instance specified by 710 * {@code info}. 711 */ notifyRegisterOnClientsDisconnected( RemoteCallbackList<ISoftApCallback> callbacks, SoftApInfo info, List<WifiClient> clients)712 public void notifyRegisterOnClientsDisconnected( 713 RemoteCallbackList<ISoftApCallback> callbacks, SoftApInfo info, 714 List<WifiClient> clients) { 715 int itemCount = callbacks.beginBroadcast(); 716 for (int i = 0; i < itemCount; i++) { 717 try { 718 if (!checkCallbackPermission(callbacks.getBroadcastCookie(i))) { 719 continue; 720 } 721 callbacks.getBroadcastItem(i).onClientsDisconnected(new SoftApInfo(info), 722 clients); 723 } catch (RemoteException e) { 724 Log.e(TAG, "onClientsDisconnected: remote exception -- " + e); 725 } 726 } 727 callbacks.finishBroadcast(); 728 } 729 } 730 WifiServiceImpl(WifiContext context, WifiInjector wifiInjector)731 public WifiServiceImpl(WifiContext context, WifiInjector wifiInjector) { 732 mContext = context; 733 mResourceCache = mContext.getResourceCache(); 734 mWifiInjector = wifiInjector; 735 mClock = wifiInjector.getClock(); 736 737 mSettingsConfigStore = mWifiInjector.getSettingsConfigStore(); 738 mFacade = mWifiInjector.getFrameworkFacade(); 739 mWifiMetrics = mWifiInjector.getWifiMetrics(); 740 mWifiTrafficPoller = mWifiInjector.getWifiTrafficPoller(); 741 mUserManager = mWifiInjector.getUserManager(); 742 mCountryCode = mWifiInjector.getWifiCountryCode(); 743 mActiveModeWarden = mWifiInjector.getActiveModeWarden(); 744 mScanRequestProxy = mWifiInjector.getScanRequestProxy(); 745 mSettingsStore = mWifiInjector.getWifiSettingsStore(); 746 mPowerManager = mContext.getSystemService(PowerManager.class); 747 mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 748 mWifiLockManager = mWifiInjector.getWifiLockManager(); 749 mWifiMulticastLockManager = mWifiInjector.getWifiMulticastLockManager(); 750 mWifiBackupRestore = mWifiInjector.getWifiBackupRestore(); 751 mSoftApBackupRestore = mWifiInjector.getSoftApBackupRestore(); 752 mWifiSettingsBackupRestore = mWifiInjector.getWifiSettingsBackupRestore(); 753 mBackupRestoreController = mWifiInjector.getBackupRestoreController(); 754 mWifiApConfigStore = mWifiInjector.getWifiApConfigStore(); 755 mWifiPermissionsUtil = mWifiInjector.getWifiPermissionsUtil(); 756 mLog = mWifiInjector.makeLog(TAG); 757 mFrameworkFacade = wifiInjector.getFrameworkFacade(); 758 mTetheredSoftApTracker = new TetheredSoftApTracker(); 759 mActiveModeWarden.registerSoftApCallback(mTetheredSoftApTracker); 760 mLohsSoftApTracker = new LohsSoftApTracker(); 761 mActiveModeWarden.registerLohsCallback(mLohsSoftApTracker); 762 mWifiNetworkSuggestionsManager = mWifiInjector.getWifiNetworkSuggestionsManager(); 763 mWifiNetworkFactory = mWifiInjector.getWifiNetworkFactory(); 764 mDppManager = mWifiInjector.getDppManager(); 765 mWifiThreadRunner = mWifiInjector.getWifiThreadRunner(); 766 mWifiHandlerThread = mWifiInjector.getWifiHandlerThread(); 767 mWifiConfigManager = mWifiInjector.getWifiConfigManager(); 768 mHalDeviceManager = mWifiInjector.getHalDeviceManager(); 769 mWifiBlocklistMonitor = mWifiInjector.getWifiBlocklistMonitor(); 770 mPasspointManager = mWifiInjector.getPasspointManager(); 771 mWifiScoreCard = mWifiInjector.getWifiScoreCard(); 772 mWifiHealthMonitor = wifiInjector.getWifiHealthMonitor(); 773 mMemoryStoreImpl = new MemoryStoreImpl(mContext, mWifiInjector, 774 mWifiScoreCard, mWifiHealthMonitor); 775 mWifiConnectivityManager = wifiInjector.getWifiConnectivityManager(); 776 mWifiDataStall = wifiInjector.getWifiDataStall(); 777 mWifiNative = wifiInjector.getWifiNative(); 778 mCoexManager = wifiInjector.getCoexManager(); 779 mConnectHelper = wifiInjector.getConnectHelper(); 780 mWifiGlobals = wifiInjector.getWifiGlobals(); 781 mSimRequiredNotifier = wifiInjector.getSimRequiredNotifier(); 782 mWifiCarrierInfoManager = wifiInjector.getWifiCarrierInfoManager(); 783 mWifiPseudonymManager = wifiInjector.getWifiPseudonymManager(); 784 mMakeBeforeBreakManager = mWifiInjector.getMakeBeforeBreakManager(); 785 mLastCallerInfoManager = mWifiInjector.getLastCallerInfoManager(); 786 mWifiDialogManager = mWifiInjector.getWifiDialogManager(); 787 mBuildProperties = mWifiInjector.getBuildProperties(); 788 mDefaultClientModeManager = mWifiInjector.getDefaultClientModeManager(); 789 mCountryCodeTracker = new CountryCodeTracker(); 790 mWifiTetheringDisallowed = false; 791 mMultiInternetManager = mWifiInjector.getMultiInternetManager(); 792 mDeviceConfigFacade = mWifiInjector.getDeviceConfigFacade(); 793 mFeatureFlags = mDeviceConfigFacade.getFeatureFlags(); 794 mApplicationQosPolicyRequestHandler = mWifiInjector.getApplicationQosPolicyRequestHandler(); 795 mWifiPulledAtomLogger = mWifiInjector.getWifiPulledAtomLogger(); 796 mAfcManager = mWifiInjector.getAfcManager(); 797 mTwtManager = mWifiInjector.getTwtManager(); 798 mWepNetworkUsageController = mWifiInjector.getWepNetworkUsageController(); 799 if (Environment.isSdkAtLeastB()) { 800 mIsUsdSupported = mContext.getResources().getBoolean( 801 mContext.getResources().getIdentifier("config_deviceSupportsWifiUsd", "bool", 802 "android")); 803 } 804 } 805 806 /** 807 * Check if Wi-Fi needs to be enabled and start it if needed. 808 * 809 * This function is used only at boot time. 810 */ checkAndStartWifi()811 public void checkAndStartWifi() { 812 mWifiThreadRunner.post(() -> { 813 if (!mWifiConfigManager.loadFromStore()) { 814 Log.e(TAG, "Failed to load from config store"); 815 } 816 mWifiConfigManager.incrementNumRebootsSinceLastUse(); 817 // config store is read, check if verbose logging is enabled. 818 enableVerboseLoggingInternal( 819 mSettingsConfigStore.get(WIFI_VERBOSE_LOGGING_ENABLED) 820 ? WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED 821 : WifiManager.VERBOSE_LOGGING_LEVEL_DISABLED); 822 // Check if wi-fi needs to be enabled 823 boolean wifiEnabled = mSettingsStore.isWifiToggleEnabled(); 824 Log.i(TAG, 825 "WifiService starting up with Wi-Fi " + (wifiEnabled ? "enabled" : "disabled")); 826 827 mWifiInjector.getWifiScanAlwaysAvailableSettingsCompatibility().initialize(); 828 mWifiInjector.getWifiNotificationManager().createNotificationChannels(); 829 // Old design, flag is disabled. 830 if (!mFeatureFlags.wepDisabledInApm()) { 831 mWifiGlobals.setWepAllowed(mSettingsConfigStore.get(WIFI_WEP_ALLOWED)); 832 // Align the value between config store (i.e.WifiConfigStore.xml) and WifiGlobals. 833 mSettingsConfigStore.registerChangeListener(WIFI_WEP_ALLOWED, 834 (key, value) -> { 835 if (mWifiGlobals.isWepAllowed() != value) { 836 handleWepAllowedChanged(value); 837 Log.i(TAG, "Wep allowed is changed to " 838 + value); 839 } 840 }, 841 new Handler(mWifiHandlerThread.getLooper())); 842 } 843 mContext.registerReceiver( 844 new BroadcastReceiver() { 845 @Override 846 public void onReceive(Context context, Intent intent) { 847 int state = intent.getIntExtra(TelephonyManager.EXTRA_SIM_STATE, 848 TelephonyManager.SIM_STATE_UNKNOWN); 849 if (TelephonyManager.SIM_STATE_ABSENT == state) { 850 Log.d(TAG, "resetting networks because SIM was removed"); 851 resetCarrierNetworks(RESET_SIM_REASON_SIM_REMOVED); 852 } 853 } 854 }, 855 new IntentFilter(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED), 856 null, 857 new Handler(mWifiHandlerThread.getLooper())); 858 859 mContext.registerReceiver( 860 new BroadcastReceiver() { 861 @Override 862 public void onReceive(Context context, Intent intent) { 863 int state = intent.getIntExtra(TelephonyManager.EXTRA_SIM_STATE, 864 TelephonyManager.SIM_STATE_UNKNOWN); 865 if (TelephonyManager.SIM_STATE_LOADED == state) { 866 Log.d(TAG, "resetting networks because SIM was loaded"); 867 resetCarrierNetworks(RESET_SIM_REASON_SIM_INSERTED); 868 } 869 } 870 }, 871 new IntentFilter(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED), 872 null, 873 new Handler(mWifiHandlerThread.getLooper())); 874 875 mContext.registerReceiver( 876 new BroadcastReceiver() { 877 private int mLastSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 878 @Override 879 public void onReceive(Context context, Intent intent) { 880 final int subId = intent.getIntExtra("subscription", 881 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 882 if (subId != mLastSubId) { 883 Log.d(TAG, "resetting networks as default data SIM is changed"); 884 resetCarrierNetworks(RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED); 885 mLastSubId = subId; 886 mWifiDataStall.resetPhoneStateListener(); 887 } 888 } 889 }, 890 new IntentFilter(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED), 891 null, 892 new Handler(mWifiHandlerThread.getLooper())); 893 894 mContext.registerReceiver( 895 new BroadcastReceiver() { 896 @Override 897 public void onReceive(Context context, Intent intent) { 898 String countryCode = intent.getStringExtra( 899 TelephonyManager.EXTRA_NETWORK_COUNTRY); 900 Log.d(TAG, "Country code changed to :" + countryCode); 901 mCountryCode.setTelephonyCountryCodeAndUpdate(countryCode); 902 } 903 }, 904 new IntentFilter(TelephonyManager.ACTION_NETWORK_COUNTRY_CHANGED), 905 null, 906 new Handler(mWifiHandlerThread.getLooper())); 907 908 mContext.registerReceiver( 909 new BroadcastReceiver() { 910 @Override 911 public void onReceive(Context context, Intent intent) { 912 Log.d(TAG, "locale changed"); 913 resetNotificationManager(); 914 mResourceCache.handleLocaleChange(); 915 } 916 }, 917 new IntentFilter(Intent.ACTION_LOCALE_CHANGED), 918 null, 919 new Handler(mWifiHandlerThread.getLooper())); 920 921 if (SdkLevel.isAtLeastT()) { 922 mContext.registerReceiver( 923 new BroadcastReceiver() { 924 @Override 925 public void onReceive(Context context, Intent intent) { 926 Log.d(TAG, "user restrictions changed"); 927 onUserRestrictionsChanged(); 928 } 929 }, 930 new IntentFilter(UserManager.ACTION_USER_RESTRICTIONS_CHANGED), 931 null, 932 new Handler(mWifiHandlerThread.getLooper())); 933 mWifiTetheringDisallowed = mUserManager.getUserRestrictions() 934 .getBoolean(UserManager.DISALLOW_WIFI_TETHERING); 935 } 936 937 // Adding optimizations of only receiving broadcasts when wifi is enabled 938 // can result in race conditions when apps toggle wifi in the background 939 // without active user involvement. Always receive broadcasts. 940 registerForBroadcasts(); 941 mInIdleMode = mPowerManager.isDeviceIdleMode(); 942 943 mActiveModeWarden.start(); 944 registerForCarrierConfigChange(); 945 mWifiInjector.getAdaptiveConnectivityEnabledSettingObserver().initialize(); 946 mIsWifiServiceStarted = true; 947 }, TAG + "#checkAndStartWifi"); 948 } 949 setPulledAtomCallbacks()950 private void setPulledAtomCallbacks() { 951 mWifiPulledAtomLogger.setPullAtomCallback(WifiStatsLog.WIFI_MODULE_INFO); 952 mWifiPulledAtomLogger.setPullAtomCallback(WifiStatsLog.WIFI_SETTING_INFO); 953 mWifiPulledAtomLogger.setPullAtomCallback(WifiStatsLog.WIFI_COMPLEX_SETTING_INFO); 954 mWifiPulledAtomLogger.setPullAtomCallback(WifiStatsLog.WIFI_CONFIGURED_NETWORK_INFO); 955 } 956 updateLocationMode()957 private void updateLocationMode() { 958 mIsLocationModeEnabled = mWifiPermissionsUtil.isLocationModeEnabled(); 959 mWifiConnectivityManager.setLocationModeEnabled(mIsLocationModeEnabled); 960 mWifiNative.setLocationModeEnabled(mIsLocationModeEnabled); 961 } 962 963 /** 964 * Find which user restrictions have changed and take corresponding actions 965 */ 966 @VisibleForTesting onUserRestrictionsChanged()967 public void onUserRestrictionsChanged() { 968 final Bundle restrictions = mUserManager.getUserRestrictions(); 969 final boolean newWifiTetheringDisallowed = 970 restrictions.getBoolean(UserManager.DISALLOW_WIFI_TETHERING); 971 972 if (newWifiTetheringDisallowed != mWifiTetheringDisallowed) { 973 if (newWifiTetheringDisallowed) { 974 mLog.info("stopSoftAp DISALLOW_WIFI_TETHERING set").flush(); 975 stopSoftApInternal(WifiManager.IFACE_IP_MODE_TETHERED); 976 } 977 mWifiTetheringDisallowed = newWifiTetheringDisallowed; 978 } 979 } 980 resetCarrierNetworks(@lientModeImpl.ResetSimReason int resetReason)981 private void resetCarrierNetworks(@ClientModeImpl.ResetSimReason int resetReason) { 982 mResourceCache.reset(); 983 Log.d(TAG, "resetting carrier networks since SIM was changed"); 984 if (resetReason == RESET_SIM_REASON_SIM_INSERTED) { 985 // clear all SIM related notifications since some action was taken to address 986 // "missing" SIM issue 987 mSimRequiredNotifier.dismissSimRequiredNotification(); 988 } else { 989 mWifiConfigManager.resetSimNetworks(); 990 mWifiNetworkSuggestionsManager.resetSimNetworkSuggestions(); 991 mPasspointManager.resetSimPasspointNetwork(); 992 mWifiConfigManager.stopRestrictingAutoJoinToSubscriptionId(); 993 } 994 995 // do additional handling if we are current connected to a sim auth network 996 for (ClientModeManager cmm : mActiveModeWarden.getClientModeManagers()) { 997 cmm.resetSimAuthNetworks(resetReason); 998 } 999 mWifiThreadRunner.post(mWifiNetworkSuggestionsManager::updateCarrierPrivilegedApps, 1000 TAG + "#resetCarrierNetworks$1"); 1001 if (resetReason == RESET_SIM_REASON_SIM_INSERTED) { 1002 // clear the blocklists in case any SIM based network were disabled due to the SIM 1003 // not being available. 1004 mWifiConfigManager.enableTemporaryDisabledNetworks(); 1005 mWifiConnectivityManager.forceConnectivityScan(ClientModeImpl.WIFI_WORK_SOURCE); 1006 } else { 1007 // Remove ephemeral carrier networks from Carrier unprivileged Apps, which will lead to 1008 // a disconnection. Privileged App will handle by the 1009 // mWifiNetworkSuggestionsManager#updateCarrierPrivilegedApps 1010 mWifiThreadRunner.post(() -> mWifiConfigManager 1011 .removeEphemeralCarrierNetworks(mWifiCarrierInfoManager 1012 .getCurrentCarrierPrivilegedPackages()), 1013 TAG + "#resetCarrierNetworks$2"); 1014 } 1015 } 1016 handleBootCompleted()1017 public void handleBootCompleted() { 1018 mWifiThreadRunner.post(() -> { 1019 Log.d(TAG, "Handle boot completed"); 1020 mIsBootComplete = true; 1021 // Register for system broadcasts. 1022 IntentFilter intentFilter = new IntentFilter(); 1023 intentFilter.addAction(Intent.ACTION_USER_REMOVED); 1024 intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); 1025 intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); 1026 intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); 1027 intentFilter.addAction(Intent.ACTION_SHUTDOWN); 1028 mContext.registerReceiver( 1029 new BroadcastReceiver() { 1030 @Override 1031 public void onReceive(Context context, Intent intent) { 1032 String action = intent.getAction(); 1033 if (Intent.ACTION_USER_REMOVED.equals(action)) { 1034 UserHandle userHandle = 1035 intent.getParcelableExtra(Intent.EXTRA_USER); 1036 if (userHandle == null) { 1037 Log.e(TAG, 1038 "User removed broadcast received with no user handle"); 1039 return; 1040 } 1041 mWifiConfigManager 1042 .removeNetworksForUser(userHandle.getIdentifier()); 1043 } else if (BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED 1044 .equals(action)) { 1045 int state = intent.getIntExtra( 1046 BluetoothAdapter.EXTRA_CONNECTION_STATE, 1047 BluetoothAdapter.STATE_DISCONNECTED); 1048 boolean isConnected = 1049 state != BluetoothAdapter.STATE_DISCONNECTED; 1050 mWifiGlobals.setBluetoothConnected(isConnected); 1051 for (ClientModeManager cmm : 1052 mActiveModeWarden.getClientModeManagers()) { 1053 cmm.onBluetoothConnectionStateChanged(); 1054 } 1055 } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) { 1056 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 1057 BluetoothAdapter.STATE_OFF); 1058 boolean isEnabled = state != BluetoothAdapter.STATE_OFF; 1059 mWifiGlobals.setBluetoothEnabled(isEnabled); 1060 for (ClientModeManager cmm : 1061 mActiveModeWarden.getClientModeManagers()) { 1062 cmm.onBluetoothConnectionStateChanged(); 1063 } 1064 } else if (PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED 1065 .equals(action)) { 1066 handleIdleModeChanged(); 1067 } else if (Intent.ACTION_SHUTDOWN.equals(action)) { 1068 handleShutDown(); 1069 } 1070 } 1071 }, 1072 intentFilter, 1073 null, 1074 new Handler(mWifiHandlerThread.getLooper())); 1075 mMemoryStoreImpl.start(); 1076 mPasspointManager.initializeProvisioner( 1077 mWifiInjector.getPasspointProvisionerHandlerThread().getLooper()); 1078 mWifiInjector.getWifiNetworkFactory().register(); 1079 mWifiInjector.getUntrustedWifiNetworkFactory().register(); 1080 mWifiInjector.getRestrictedWifiNetworkFactory().register(); 1081 mWifiInjector.getOemWifiNetworkFactory().register(); 1082 mWifiInjector.getMultiInternetWifiNetworkFactory().register(); 1083 mWifiInjector.getWifiP2pConnection().handleBootCompleted(); 1084 // Start to listen country code change to avoid query supported channels causes boot 1085 // time increased. 1086 mCountryCode.registerListener(mCountryCodeTracker); 1087 mWifiInjector.getSarManager().handleBootCompleted(); 1088 mWifiInjector.getSsidTranslator().handleBootCompleted(); 1089 mWifiInjector.getPasspointManager().handleBootCompleted(); 1090 mWifiInjector.getInterfaceConflictManager().handleBootCompleted(); 1091 mWifiInjector.getHalDeviceManager().handleBootCompleted(); 1092 // HW capabilities is ready after boot completion. 1093 if (!mWifiGlobals.isInsecureEnterpriseConfigurationAllowed()) { 1094 mWifiConfigManager.updateTrustOnFirstUseFlag(isTrustOnFirstUseSupported()); 1095 } 1096 updateVerboseLoggingEnabled(); 1097 mWifiInjector.getWifiDeviceStateChangeManager().handleBootCompleted(); 1098 if (mFeatureFlags.wepDisabledInApm() 1099 && mWepNetworkUsageController != null) { 1100 mWepNetworkUsageController.handleBootCompleted(); 1101 } 1102 setPulledAtomCallbacks(); 1103 mTwtManager.registerWifiNativeTwtEvents(); 1104 mContext.registerReceiverForAllUsers( 1105 new BroadcastReceiver() { 1106 @Override 1107 public void onReceive(Context context, Intent intent) { 1108 if (mVerboseLoggingEnabled) { 1109 Log.v(TAG, "onReceive: MODE_CHANGED_ACTION: intent=" + intent); 1110 } 1111 updateLocationMode(); 1112 } 1113 }, 1114 new IntentFilter(LocationManager.MODE_CHANGED_ACTION), 1115 null, 1116 new Handler(mWifiHandlerThread.getLooper())); 1117 updateLocationMode(); 1118 1119 if (SdkLevel.isAtLeastT()) { 1120 UwbManager uwbManager = 1121 mContext.getSystemService(UwbManager.class); 1122 if (uwbManager != null) { 1123 uwbManager.registerAdapterStateCallback(new HandlerExecutor(new Handler( 1124 mWifiHandlerThread.getLooper())), new UwbAdapterStateListener()); 1125 } 1126 } 1127 1128 if (SdkLevel.isAtLeastV()) { 1129 ThreadNetworkManager threadManager = 1130 mContext.getSystemService(ThreadNetworkManager.class); 1131 if (threadManager != null) { 1132 List<ThreadNetworkController> threadNetworkControllers = 1133 threadManager.getAllThreadNetworkControllers(); 1134 if (threadNetworkControllers.size() > 0) { 1135 ThreadNetworkController threadNetworkController = 1136 threadNetworkControllers.get(0); 1137 if (threadNetworkController != null) { 1138 threadNetworkController.registerStateCallback( 1139 new HandlerExecutor(new Handler(mWifiHandlerThread.getLooper())), 1140 new ThreadStateListener()); 1141 } 1142 } 1143 } 1144 } 1145 }, TAG + "#handleBootCompleted"); 1146 } 1147 handleUserSwitch(int userId)1148 public void handleUserSwitch(int userId) { 1149 Log.d(TAG, "Handle user switch " + userId); 1150 1151 mWifiThreadRunner.post(() -> { 1152 mWifiConfigManager.handleUserSwitch(userId); 1153 resetNotificationManager(); 1154 }, TAG + "#handleUserSwitch"); 1155 } 1156 handleUserUnlock(int userId)1157 public void handleUserUnlock(int userId) { 1158 Log.d(TAG, "Handle user unlock " + userId); 1159 mWifiThreadRunner.post(() -> mWifiConfigManager.handleUserUnlock(userId), 1160 TAG + "#handleUserUnlock"); 1161 } 1162 handleUserStop(int userId)1163 public void handleUserStop(int userId) { 1164 Log.d(TAG, "Handle user stop " + userId); 1165 mWifiThreadRunner.post(() -> mWifiConfigManager.handleUserStop(userId), 1166 TAG + "#handleUserStop"); 1167 } 1168 1169 /** 1170 * See {@link android.net.wifi.WifiManager#startScan} 1171 * 1172 * @param packageName Package name of the app that requests wifi scan. 1173 * @param featureId The feature in the package 1174 */ 1175 @Override startScan(String packageName, String featureId)1176 public boolean startScan(String packageName, String featureId) { 1177 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 1178 return false; 1179 } 1180 int callingUid = Binder.getCallingUid(); 1181 mWifiPermissionsUtil.checkPackage(callingUid, packageName); 1182 1183 long ident = Binder.clearCallingIdentity(); 1184 mLog.info("startScan uid=%").c(callingUid).flush(); 1185 synchronized (this) { 1186 if (mInIdleMode) { 1187 // Need to send an immediate scan result broadcast in case the 1188 // caller is waiting for a result .. 1189 1190 // TODO: investigate if the logic to cancel scans when idle can move to 1191 // WifiScanningServiceImpl. This will 1 - clean up WifiServiceImpl and 2 - 1192 // avoid plumbing an awkward path to report a cancelled/failed scan. This will 1193 // be sent directly until b/31398592 is fixed. 1194 sendFailedScanBroadcast(); 1195 mScanPending = true; 1196 return false; 1197 } 1198 } 1199 try { 1200 mWifiPermissionsUtil.enforceCanAccessScanResults(packageName, featureId, callingUid, 1201 null); 1202 mLastCallerInfoManager.put(WifiManager.API_START_SCAN, Process.myTid(), 1203 callingUid, Binder.getCallingPid(), packageName, true); 1204 Boolean scanSuccess = mWifiThreadRunner.call(() -> 1205 mScanRequestProxy.startScan(callingUid, packageName), null, 1206 TAG + "#startScan"); 1207 if (scanSuccess == null) { 1208 sendFailedScanBroadcast(); 1209 return false; 1210 } 1211 if (!scanSuccess) { 1212 Log.e(TAG, "Failed to start scan"); 1213 return false; 1214 } 1215 } catch (SecurityException e) { 1216 Log.w(TAG, "Permission violation - startScan not allowed for" 1217 + " uid=" + callingUid + ", packageName=" + packageName + ", reason=" + e); 1218 return false; 1219 } finally { 1220 Binder.restoreCallingIdentity(ident); 1221 } 1222 return true; 1223 } 1224 1225 // Send a failed scan broadcast to indicate the current scan request failed. sendFailedScanBroadcast()1226 private void sendFailedScanBroadcast() { 1227 // clear calling identity to send broadcast 1228 long callingIdentity = Binder.clearCallingIdentity(); 1229 try { 1230 final boolean scanSucceeded = false; 1231 Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); 1232 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1233 intent.putExtra(WifiManager.EXTRA_RESULTS_UPDATED, scanSucceeded); 1234 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, null, 1235 createBroadcastOptionsForScanResultsAvailable(scanSucceeded)); 1236 } finally { 1237 // restore calling identity 1238 Binder.restoreCallingIdentity(callingIdentity); 1239 } 1240 1241 } 1242 1243 /** 1244 * WPS support in Client mode is deprecated. Return null. 1245 */ 1246 @Override getCurrentNetworkWpsNfcConfigurationToken()1247 public String getCurrentNetworkWpsNfcConfigurationToken() { 1248 // while CLs are in flight, return null here, will be removed (b/72423090) 1249 enforceNetworkStackPermission(); 1250 if (mVerboseLoggingEnabled) { 1251 mLog.info("getCurrentNetworkWpsNfcConfigurationToken uid=%") 1252 .c(Binder.getCallingUid()).flush(); 1253 } 1254 return null; 1255 } 1256 1257 private boolean mInIdleMode; 1258 private boolean mScanPending; 1259 handleIdleModeChanged()1260 private void handleIdleModeChanged() { 1261 boolean doScan = false; 1262 synchronized (this) { 1263 boolean idle = mPowerManager.isDeviceIdleMode(); 1264 if (mInIdleMode != idle) { 1265 mInIdleMode = idle; 1266 if (!idle) { // exiting doze mode 1267 if (mScanPending) { 1268 mScanPending = false; 1269 doScan = true; 1270 } 1271 } 1272 mActiveModeWarden.onIdleModeChanged(idle); 1273 } 1274 } 1275 if (doScan) { 1276 // Someone requested a scan while we were idle; do a full scan now. 1277 // A security check of the caller's identity was made when the request arrived via 1278 // Binder. Now we'll pass the current process's identity to startScan(). 1279 startScan(mContext.getOpPackageName(), mContext.getAttributionTag()); 1280 } 1281 } 1282 handleShutDown()1283 private void handleShutDown() { 1284 if (mVerboseLoggingEnabled) { 1285 Log.v(TAG, "handleShutDown"); 1286 } 1287 // Direct call to notify ActiveModeWarden as soon as possible with the assumption that 1288 // notifyShuttingDown() doesn't have codes that may cause concurrentModificationException, 1289 // e.g., access to a collection. 1290 mActiveModeWarden.notifyShuttingDown(); 1291 1292 // There is no explicit disconnection event in clientModeImpl during shutdown. 1293 // Call resetConnectionState() so that connection duration is calculated 1294 // before memory store write triggered by mMemoryStoreImpl.stop(). 1295 mWifiScoreCard.resetAllConnectionStates(); 1296 mMemoryStoreImpl.stop(); 1297 mWifiConfigManager.writeDataToStorage(); 1298 mWifiNetworkSuggestionsManager.handleShutDown(); 1299 } 1300 checkNetworkSettingsPermission(int pid, int uid)1301 private boolean checkNetworkSettingsPermission(int pid, int uid) { 1302 return mContext.checkPermission(android.Manifest.permission.NETWORK_SETTINGS, pid, uid) 1303 == PERMISSION_GRANTED; 1304 } 1305 checkNetworkSetupWizardPermission(int pid, int uid)1306 private boolean checkNetworkSetupWizardPermission(int pid, int uid) { 1307 return mContext.checkPermission(android.Manifest.permission.NETWORK_SETUP_WIZARD, pid, uid) 1308 == PackageManager.PERMISSION_GRANTED; 1309 } 1310 checkMainlineNetworkStackPermission(int pid, int uid)1311 private boolean checkMainlineNetworkStackPermission(int pid, int uid) { 1312 return mContext.checkPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, pid, uid) 1313 == PackageManager.PERMISSION_GRANTED; 1314 } 1315 checkNetworkStackPermission(int pid, int uid)1316 private boolean checkNetworkStackPermission(int pid, int uid) { 1317 return mContext.checkPermission(android.Manifest.permission.NETWORK_STACK, pid, uid) 1318 == PackageManager.PERMISSION_GRANTED; 1319 } 1320 checkNetworkManagedProvisioningPermission(int pid, int uid)1321 private boolean checkNetworkManagedProvisioningPermission(int pid, int uid) { 1322 return mContext.checkPermission(android.Manifest.permission.NETWORK_MANAGED_PROVISIONING, 1323 pid, uid) == PackageManager.PERMISSION_GRANTED; 1324 } 1325 checkManageDeviceAdminsPermission(int pid, int uid)1326 private boolean checkManageDeviceAdminsPermission(int pid, int uid) { 1327 return mContext.checkPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS, 1328 pid, uid) == PackageManager.PERMISSION_GRANTED; 1329 } 1330 1331 /** 1332 * Helper method to check if the entity initiating the binder call has any of the signature only 1333 * permissions. Not to be confused with the concept of privileged apps, which are system apps 1334 * with allow-listed "privileged" permissions. 1335 */ isPrivileged(int pid, int uid)1336 private boolean isPrivileged(int pid, int uid) { 1337 return checkNetworkSettingsPermission(pid, uid) 1338 || checkNetworkSetupWizardPermission(pid, uid) 1339 || checkNetworkStackPermission(pid, uid) 1340 || checkNetworkManagedProvisioningPermission(pid, uid) 1341 || mWifiPermissionsUtil.isSignedWithPlatformKey(uid); 1342 } 1343 1344 /** 1345 * Helper method to check if the entity initiating the binder call has setup wizard or settings 1346 * permissions. 1347 */ isSettingsOrSuw(int pid, int uid)1348 private boolean isSettingsOrSuw(int pid, int uid) { 1349 return checkNetworkSettingsPermission(pid, uid) 1350 || checkNetworkSetupWizardPermission(pid, uid); 1351 } 1352 1353 /** Helper method to check if the entity initiating the binder call is a DO/PO app. */ isDeviceOrProfileOwner(int uid, String packageName)1354 private boolean isDeviceOrProfileOwner(int uid, String packageName) { 1355 return mWifiPermissionsUtil.isDeviceOwner(uid, packageName) 1356 || mWifiPermissionsUtil.isProfileOwner(uid, packageName); 1357 } 1358 enforceNetworkSettingsPermission()1359 private void enforceNetworkSettingsPermission() { 1360 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.NETWORK_SETTINGS, 1361 "WifiService"); 1362 } 1363 checkAnyPermissionOf(String... permissions)1364 private boolean checkAnyPermissionOf(String... permissions) { 1365 for (String permission : permissions) { 1366 if (mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED) { 1367 return true; 1368 } 1369 } 1370 return false; 1371 } 1372 enforceAnyPermissionOf(String... permissions)1373 private void enforceAnyPermissionOf(String... permissions) { 1374 if (!checkAnyPermissionOf(permissions)) { 1375 throw new SecurityException("Requires one of the following permissions: " 1376 + String.join(", ", permissions) + "."); 1377 } 1378 } 1379 enforceNetworkStackPermission()1380 private void enforceNetworkStackPermission() { 1381 // TODO(b/142554155): Only check for MAINLINE_NETWORK_STACK permission 1382 boolean granted = mContext.checkCallingOrSelfPermission( 1383 android.Manifest.permission.NETWORK_STACK) 1384 == PackageManager.PERMISSION_GRANTED; 1385 if (granted) { 1386 return; 1387 } 1388 mContext.enforceCallingOrSelfPermission( 1389 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, "WifiService"); 1390 } 1391 enforceAccessPermission()1392 private void enforceAccessPermission() { 1393 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE, 1394 "WifiService"); 1395 } 1396 enforceRestartWifiSubsystemPermission()1397 private void enforceRestartWifiSubsystemPermission() { 1398 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RESTART_WIFI_SUBSYSTEM, 1399 "WifiService"); 1400 } 1401 1402 /** 1403 * Checks whether the caller can change the wifi state. 1404 * Possible results: 1405 * 1. Operation is allowed. No exception thrown, and AppOpsManager.MODE_ALLOWED returned. 1406 * 2. Operation is not allowed, and caller must be told about this. SecurityException is thrown. 1407 * 3. Operation is not allowed, and caller must not be told about this (i.e. must silently 1408 * ignore the operation). No exception is thrown, and AppOpsManager.MODE_IGNORED returned. 1409 */ 1410 @CheckResult enforceChangePermission(String callingPackage)1411 private int enforceChangePermission(String callingPackage) { 1412 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); 1413 if (checkNetworkSettingsPermission(Binder.getCallingPid(), Binder.getCallingUid())) { 1414 return MODE_ALLOWED; 1415 } 1416 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE, 1417 "WifiService"); 1418 1419 return mAppOps.noteOp( 1420 AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Binder.getCallingUid(), callingPackage); 1421 } 1422 enforceReadCredentialPermission()1423 private void enforceReadCredentialPermission() { 1424 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.READ_WIFI_CREDENTIAL, 1425 "WifiService"); 1426 } 1427 enforceMulticastChangePermission()1428 private void enforceMulticastChangePermission() { 1429 mContext.enforceCallingOrSelfPermission( 1430 android.Manifest.permission.CHANGE_WIFI_MULTICAST_STATE, 1431 "WifiService"); 1432 } 1433 enforceConnectivityInternalPermission()1434 private void enforceConnectivityInternalPermission() { 1435 mContext.enforceCallingOrSelfPermission( 1436 android.Manifest.permission.CONNECTIVITY_INTERNAL, 1437 "ConnectivityService"); 1438 } 1439 enforceLocationPermission(String pkgName, @Nullable String featureId, int uid)1440 private void enforceLocationPermission(String pkgName, @Nullable String featureId, int uid) { 1441 mWifiPermissionsUtil.enforceLocationPermission(pkgName, featureId, uid); 1442 } 1443 enforceCoarseLocationPermission(@ullable String pkgName, @Nullable String featureId, int uid)1444 private void enforceCoarseLocationPermission(@Nullable String pkgName, 1445 @Nullable String featureId, int uid) { 1446 mWifiPermissionsUtil.enforceCoarseLocationPermission(pkgName, featureId, uid); 1447 } 1448 enforceLocationPermissionInManifest(int uid, boolean isCoarseOnly)1449 private void enforceLocationPermissionInManifest(int uid, boolean isCoarseOnly) { 1450 mWifiPermissionsUtil.enforceLocationPermissionInManifest(uid, isCoarseOnly); 1451 } 1452 1453 /** 1454 * Validates if the calling user is valid. 1455 * 1456 * @throws a {@link SecurityException} if the calling user is not valid. 1457 */ enforceValidCallingUser()1458 private void enforceValidCallingUser() { 1459 if (!isValidCallingUser()) { 1460 throw new SecurityException( 1461 "Calling user " + Binder.getCallingUserHandle() + " is not the SYSTEM user, " 1462 + "the current user, or a profile of the current user, " 1463 + "thus not allowed to make changes to WIFI."); 1464 } 1465 } 1466 1467 /** 1468 * Checks if the calling user is valid on Automotive devices.. 1469 * 1470 * @return true if any of the following conditions are true: 1471 * <li>The device is not an Automotive device. 1472 * <li>the calling user is the system user. 1473 * <li>the calling user is the current user. 1474 * <li>the calling user belongs to the same profile group as the current user. 1475 */ isValidCallingUser()1476 private boolean isValidCallingUser() { 1477 // TODO(b/360488316): Ideally UserManager#isVisibleBackgroundUsersEnabled() should be used 1478 // but it is a hidden API. We rely on FEATURE_AUTOMOTIVE only, because we cannot access 1479 // the RRO config for R.bool.config_multiuserVisibleBackgroundUsers. 1480 if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) { 1481 return true; 1482 } 1483 UserHandle callingUser = Binder.getCallingUserHandle(); 1484 1485 final long ident = Binder.clearCallingIdentity(); 1486 try { 1487 UserHandle currentUser = 1488 UserHandle.of(mWifiInjector.getWifiPermissionsWrapper().getCurrentUser()); 1489 if (UserHandle.SYSTEM.equals(callingUser) 1490 || callingUser.equals(currentUser) 1491 || mUserManager.isSameProfileGroup(callingUser, currentUser)) { 1492 return true; 1493 } 1494 } finally { 1495 Binder.restoreCallingIdentity(ident); 1496 } 1497 1498 return false; 1499 } 1500 1501 /** 1502 * Helper method to check if the app is allowed to access public API's deprecated in 1503 * {@link Build.VERSION_CODES#Q}. 1504 * Note: Invoke mAppOps.checkPackage(uid, packageName) before to ensure correct package name. 1505 */ isTargetSdkLessThanQOrPrivileged(String packageName, int pid, int uid)1506 private boolean isTargetSdkLessThanQOrPrivileged(String packageName, int pid, int uid) { 1507 return (mWifiPermissionsUtil.isTargetSdkLessThan(packageName, Build.VERSION_CODES.Q, uid) 1508 && !isGuestUser()) 1509 || isPrivileged(pid, uid) 1510 || mWifiPermissionsUtil.isAdmin(uid, packageName) 1511 || mWifiPermissionsUtil.isSystem(packageName, uid); 1512 } 1513 isGuestUser()1514 private boolean isGuestUser() { 1515 long ident = Binder.clearCallingIdentity(); 1516 try { 1517 return mWifiPermissionsUtil.isGuestUser(); 1518 } finally { 1519 Binder.restoreCallingIdentity(ident); 1520 } 1521 } 1522 1523 /** 1524 * Helper method to check if the app is allowed to access public API's deprecated in 1525 * {@link Build.VERSION_CODES#R}. 1526 * Note: Invoke mAppOps.checkPackage(uid, packageName) before to ensure correct package name. 1527 */ isTargetSdkLessThanROrPrivileged(String packageName, int pid, int uid)1528 private boolean isTargetSdkLessThanROrPrivileged(String packageName, int pid, int uid) { 1529 return (mWifiPermissionsUtil.isTargetSdkLessThan(packageName, Build.VERSION_CODES.R, uid) 1530 && !isGuestUser()) 1531 || isPrivileged(pid, uid) 1532 || mWifiPermissionsUtil.isAdmin(uid, packageName) 1533 || mWifiPermissionsUtil.isSystem(packageName, uid); 1534 } 1535 isPlatformOrTargetSdkLessThanT(String packageName, int uid)1536 private boolean isPlatformOrTargetSdkLessThanT(String packageName, int uid) { 1537 if (!SdkLevel.isAtLeastT()) { 1538 return true; 1539 } 1540 return mWifiPermissionsUtil.isTargetSdkLessThan(packageName, Build.VERSION_CODES.TIRAMISU, 1541 uid); 1542 } 1543 isPlatformOrTargetSdkLessThanU(String packageName, int uid)1544 private boolean isPlatformOrTargetSdkLessThanU(String packageName, int uid) { 1545 if (!SdkLevel.isAtLeastU()) { 1546 return true; 1547 } 1548 return mWifiPermissionsUtil.isTargetSdkLessThan(packageName, 1549 Build.VERSION_CODES.UPSIDE_DOWN_CAKE, uid); 1550 } 1551 1552 /** 1553 * Get the current primary ClientModeManager in a thread safe manner, but blocks on the main 1554 * Wifi thread. 1555 */ getPrimaryClientModeManagerBlockingThreadSafe()1556 private ClientModeManager getPrimaryClientModeManagerBlockingThreadSafe() { 1557 return mWifiThreadRunner.call( 1558 () -> mActiveModeWarden.getPrimaryClientModeManager(), 1559 mDefaultClientModeManager, TAG + "#getPrimaryClientModeManagerBlockingThreadSafe"); 1560 } 1561 1562 /** 1563 * see {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)} 1564 * @param enable {@code true} to enable, {@code false} to disable. 1565 * @return {@code true} if the enable/disable operation was 1566 * started or is already in the queue. 1567 */ 1568 @Override setWifiEnabled(String packageName, boolean enable)1569 public synchronized boolean setWifiEnabled(String packageName, boolean enable) { 1570 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 1571 return false; 1572 } 1573 enforceValidCallingUser(); 1574 int callingUid = Binder.getCallingUid(); 1575 int callingPid = Binder.getCallingPid(); 1576 boolean isPrivileged = isPrivileged(callingPid, callingUid); 1577 boolean isThirdParty = !isPrivileged 1578 && !isDeviceOrProfileOwner(callingUid, packageName) 1579 && !mWifiPermissionsUtil.isSystem(packageName, callingUid); 1580 boolean isTargetSdkLessThanQ = mWifiPermissionsUtil.isTargetSdkLessThan(packageName, 1581 Build.VERSION_CODES.Q, callingUid) && !isGuestUser(); 1582 mWifiPermissionsUtil.checkPackage(callingUid, packageName); 1583 if (isThirdParty && !isTargetSdkLessThanQ) { 1584 mLog.info("setWifiEnabled not allowed for uid=%").c(callingUid).flush(); 1585 return false; 1586 } 1587 1588 // If Satellite mode is enabled, Wifi can not be turned on/off 1589 if (mSettingsStore.isSatelliteModeOn()) { 1590 mLog.info("setWifiEnabled not allowed as satellite mode is on.").flush(); 1591 return false; 1592 } 1593 1594 // If Airplane mode is enabled, only privileged apps are allowed to toggle Wifi 1595 if (mSettingsStore.isAirplaneModeOn() && !isPrivileged) { 1596 mLog.err("setWifiEnabled in Airplane mode: only Settings can toggle wifi").flush(); 1597 return false; 1598 } 1599 1600 // Pre-S interface priority is solely based on interface type, which allows STA to delete AP 1601 // for any requester. To prevent non-privileged apps from deleting a tethering AP by 1602 // enabling Wi-Fi, only allow privileged apps to toggle Wi-Fi if tethering AP is up. 1603 if (!SdkLevel.isAtLeastS() && !isPrivileged 1604 && mTetheredSoftApTracker.getState().getState() == WIFI_AP_STATE_ENABLED) { 1605 mLog.err("setWifiEnabled with SoftAp enabled: only Settings can toggle wifi").flush(); 1606 return false; 1607 } 1608 1609 long ident = Binder.clearCallingIdentity(); 1610 try { 1611 // If user restriction is set, only DO/PO is allowed to toggle wifi 1612 if (SdkLevel.isAtLeastT() && mUserManager.hasUserRestrictionForUser( 1613 UserManager.DISALLOW_CHANGE_WIFI_STATE, 1614 UserHandle.getUserHandleForUid(callingUid)) 1615 && !isDeviceOrProfileOwner(callingUid, packageName)) { 1616 mLog.err( 1617 "setWifiEnabled with user restriction: only DO/PO can toggle wifi").flush(); 1618 return false; 1619 } 1620 } finally { 1621 Binder.restoreCallingIdentity(ident); 1622 } 1623 1624 // Show a user-confirmation dialog for legacy third-party apps targeting less than Q. 1625 if (enable && isTargetSdkLessThanQ && isThirdParty 1626 && showDialogWhenThirdPartyAppsEnableWifi()) { 1627 mLog.info("setWifiEnabled must show user confirmation dialog for uid=%").c(callingUid) 1628 .flush(); 1629 mWifiThreadRunner.post(() -> { 1630 if (mActiveModeWarden.getWifiState() 1631 == WIFI_STATE_ENABLED) { 1632 // Wi-Fi already enabled; don't need to show dialog. 1633 return; 1634 } 1635 showWifiEnableRequestDialog(callingUid, callingPid, packageName); 1636 }, TAG + "#setWifiEnabled"); 1637 return true; 1638 } 1639 setWifiEnabledInternal(packageName, enable, callingUid, callingPid, isPrivileged); 1640 return true; 1641 } 1642 1643 @AnyThread setWifiEnabledInternal(String packageName, boolean enable, int callingUid, int callingPid, boolean isPrivileged)1644 private void setWifiEnabledInternal(String packageName, boolean enable, 1645 int callingUid, int callingPid, boolean isPrivileged) { 1646 mLog.info("setWifiEnabled package=% uid=% enable=% isPrivileged=%").c(packageName) 1647 .c(callingUid).c(enable).c(isPrivileged).flush(); 1648 long ident = Binder.clearCallingIdentity(); 1649 try { 1650 if (!mSettingsStore.handleWifiToggled(enable)) { 1651 // Nothing to do if wifi cannot be toggled 1652 return; 1653 } 1654 } finally { 1655 Binder.restoreCallingIdentity(ident); 1656 } 1657 if (enable) { 1658 // Clear out all outstanding wifi enable request dialogs. 1659 mWifiThreadRunner.post(() -> { 1660 for (int i = 0; i < mWifiEnableRequestDialogHandles.size(); i++) { 1661 mWifiEnableRequestDialogHandles.valueAt(i).dismissDialog(); 1662 } 1663 mWifiEnableRequestDialogHandles.clear(); 1664 }, TAG + "#setWifiEnabledInternal$1"); 1665 } 1666 if (mWifiPermissionsUtil.checkNetworkSettingsPermission(callingUid)) { 1667 if (enable) { 1668 mWifiThreadRunner.post( 1669 () -> mWifiConnectivityManager.setAutoJoinEnabledExternal(true, false), 1670 TAG + "#setWifiEnabledInternal$2"); 1671 mWifiMetrics.logUserActionEvent(UserActionEvent.EVENT_TOGGLE_WIFI_ON); 1672 } else { 1673 WifiInfo wifiInfo = mActiveModeWarden.getConnectionInfo(); 1674 mWifiMetrics.logUserActionEvent(UserActionEvent.EVENT_TOGGLE_WIFI_OFF, 1675 wifiInfo == null ? -1 : wifiInfo.getNetworkId()); 1676 } 1677 } 1678 if (!enable) { 1679 mWifiInjector.getInterfaceConflictManager().reset(); 1680 } 1681 mWifiMetrics.incrementNumWifiToggles(isPrivileged, enable); 1682 mWifiMetrics.reportWifiStateChanged(enable, mWifiInjector.getWakeupController().isUsable(), 1683 false); 1684 mActiveModeWarden.wifiToggled(new WorkSource(callingUid, packageName)); 1685 mLastCallerInfoManager.put(WifiManager.API_WIFI_ENABLED, Process.myTid(), 1686 callingUid, callingPid, packageName, enable); 1687 } 1688 showWifiEnableRequestDialog(int uid, int pid, @NonNull String packageName)1689 private void showWifiEnableRequestDialog(int uid, int pid, @NonNull String packageName) { 1690 String appName; 1691 try { 1692 PackageManager pm = mContext.getPackageManager(); 1693 ApplicationInfo appInfo = pm.getApplicationInfo(packageName, 0); 1694 appName = appInfo.loadLabel(pm).toString(); 1695 } catch (PackageManager.NameNotFoundException e) { 1696 appName = packageName; 1697 } 1698 WifiDialogManager.SimpleDialogCallback dialogCallback = 1699 new WifiDialogManager.SimpleDialogCallback() { 1700 @Override 1701 public void onPositiveButtonClicked() { 1702 mLog.info("setWifiEnabled dialog accepted for package=% uid=%") 1703 .c(packageName).c(uid).flush(); 1704 mWifiEnableRequestDialogHandles.delete(uid); 1705 setWifiEnabledInternal(packageName, true, uid, pid, false); 1706 } 1707 1708 @Override 1709 public void onNegativeButtonClicked() { 1710 mLog.info("setWifiEnabled dialog declined for package=% uid=%") 1711 .c(packageName).c(uid).flush(); 1712 mWifiEnableRequestDialogHandles.delete(uid); 1713 } 1714 1715 @Override 1716 public void onNeutralButtonClicked() { 1717 // Not used. 1718 } 1719 1720 @Override 1721 public void onCancelled() { 1722 mLog.info("setWifiEnabled dialog cancelled for package=% uid=%") 1723 .c(packageName).c(uid).flush(); 1724 mWifiEnableRequestDialogHandles.delete(uid); 1725 } 1726 }; 1727 Resources res = mContext.getResources(); 1728 if (mWifiEnableRequestDialogHandles.get(uid) != null) { 1729 mLog.info("setWifiEnabled dialog already launched for package=% uid=%").c(packageName) 1730 .c(uid).flush(); 1731 return; 1732 } 1733 WifiDialogManager.DialogHandle dialogHandle = mWifiDialogManager.createSimpleDialog( 1734 res.getString(R.string.wifi_enable_request_dialog_title, appName), 1735 res.getString(R.string.wifi_enable_request_dialog_message), 1736 res.getString(R.string.wifi_enable_request_dialog_positive_button), 1737 res.getString(R.string.wifi_enable_request_dialog_negative_button), 1738 null /* neutralButtonText */, 1739 dialogCallback, 1740 mWifiThreadRunner); 1741 mWifiEnableRequestDialogHandles.put(uid, dialogHandle); 1742 dialogHandle.launchDialog(); 1743 mLog.info("setWifiEnabled dialog launched for package=% uid=%").c(packageName) 1744 .c(uid).flush(); 1745 } 1746 1747 @RequiresApi(Build.VERSION_CODES.S) 1748 @Override registerSubsystemRestartCallback(ISubsystemRestartCallback callback)1749 public void registerSubsystemRestartCallback(ISubsystemRestartCallback callback) { 1750 if (!SdkLevel.isAtLeastS()) { 1751 throw new UnsupportedOperationException(); 1752 } 1753 if (callback == null) { 1754 throw new IllegalArgumentException("Callback is null"); 1755 } 1756 enforceAccessPermission(); 1757 if (mVerboseLoggingEnabled) { 1758 mLog.info("registerSubsystemRestartCallback uid=%").c(Binder.getCallingUid()).flush(); 1759 } 1760 1761 mWifiThreadRunner.post(() -> { 1762 if (!mActiveModeWarden.registerSubsystemRestartCallback(callback)) { 1763 Log.e(TAG, "registerSubsystemRestartCallback: Failed to register callback"); 1764 } 1765 }, TAG + "#registerSubsystemRestartCallback"); 1766 } 1767 1768 @RequiresApi(Build.VERSION_CODES.S) 1769 @Override unregisterSubsystemRestartCallback(ISubsystemRestartCallback callback)1770 public void unregisterSubsystemRestartCallback(ISubsystemRestartCallback callback) { 1771 if (!SdkLevel.isAtLeastS()) { 1772 throw new UnsupportedOperationException(); 1773 } 1774 if (callback == null) { 1775 throw new IllegalArgumentException("Callback is null"); 1776 } 1777 enforceAccessPermission(); 1778 if (mVerboseLoggingEnabled) { 1779 mLog.info("unregisterSubsystemRestartCallback uid=%").c(Binder.getCallingUid()).flush(); 1780 } 1781 mWifiThreadRunner.post(() -> { 1782 if (!mActiveModeWarden.unregisterSubsystemRestartCallback(callback)) { 1783 Log.e(TAG, "unregisterSubsystemRestartCallback: Failed to register callback"); 1784 } 1785 }, TAG + "#unregisterSubsystemRestartCallback"); 1786 } 1787 1788 /** 1789 * See {@link WifiManager#addWifiNetworkStateChangedListener( 1790 * Executor, WifiManager.WifiNetworkStateChangedListener)} 1791 */ 1792 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 1793 @Override addWifiNetworkStateChangedListener(IWifiNetworkStateChangedListener listener)1794 public void addWifiNetworkStateChangedListener(IWifiNetworkStateChangedListener listener) { 1795 if (listener == null) { 1796 throw new IllegalArgumentException(); 1797 } 1798 enforceNetworkSettingsPermission(); 1799 if (mVerboseLoggingEnabled) { 1800 mLog.info("addWifiNetworkStateChangedListener uid=%").c(Binder.getCallingUid()).flush(); 1801 } 1802 mWifiThreadRunner.post(() -> { 1803 mActiveModeWarden.addWifiNetworkStateChangedListener(listener); 1804 }, TAG + "#addWifiNetworkStateChangedListener"); 1805 } 1806 1807 /** 1808 * See {@link WifiManager#removeWifiNetworkStateChangedListener( 1809 * WifiManager.WifiNetworkStateChangedListener)} 1810 * @param listener 1811 */ 1812 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 1813 @Override removeWifiNetworkStateChangedListener(IWifiNetworkStateChangedListener listener)1814 public void removeWifiNetworkStateChangedListener(IWifiNetworkStateChangedListener listener) { 1815 if (listener == null) { 1816 throw new IllegalArgumentException(); 1817 } 1818 if (mVerboseLoggingEnabled) { 1819 mLog.info("removeWifiNetworkStateChangedListener uid=%") 1820 .c(Binder.getCallingUid()).flush(); 1821 } 1822 mWifiThreadRunner.post(() -> { 1823 mActiveModeWarden.removeWifiNetworkStateChangedListener(listener); 1824 }, TAG + "#removeWifiNetworkStateChangedListener"); 1825 } 1826 1827 @RequiresApi(Build.VERSION_CODES.S) 1828 @Override restartWifiSubsystem()1829 public void restartWifiSubsystem() { 1830 if (!SdkLevel.isAtLeastS()) { 1831 throw new UnsupportedOperationException(); 1832 } 1833 enforceRestartWifiSubsystemPermission(); 1834 if (mVerboseLoggingEnabled) { 1835 mLog.info("restartWifiSubsystem uid=%").c(Binder.getCallingUid()).flush(); 1836 } 1837 mWifiThreadRunner.post(() -> { 1838 WifiInfo wifiInfo = mActiveModeWarden.getConnectionInfo(); 1839 mWifiMetrics.logUserActionEvent(UserActionEvent.EVENT_RESTART_WIFI_SUB_SYSTEM, 1840 wifiInfo == null ? -1 : wifiInfo.getNetworkId()); 1841 mWifiInjector.getSelfRecovery().trigger(REASON_API_CALL); 1842 }, TAG + "#restartWifiSubsystem"); 1843 } 1844 1845 /** 1846 * see {@link WifiManager#getWifiState()} 1847 * @return One of {@link WifiManager#WIFI_STATE_DISABLED}, 1848 * {@link WifiManager#WIFI_STATE_DISABLING}, 1849 * {@link WifiManager#WIFI_STATE_ENABLED}, 1850 * {@link WifiManager#WIFI_STATE_ENABLING}, 1851 * {@link WifiManager#WIFI_STATE_UNKNOWN} 1852 */ 1853 @Override getWifiEnabledState()1854 public int getWifiEnabledState() { 1855 enforceAccessPermission(); 1856 int state = mActiveModeWarden.getWifiState(); 1857 // If the wifi is enabling, call it on the wifi handler to get the state after wifi enabled. 1858 // This is only needed for pre-T. 1859 if (state == WifiManager.WIFI_STATE_ENABLING && !SdkLevel.isAtLeastT()) { 1860 state = mWifiThreadRunner.call(() -> mActiveModeWarden.getWifiState(), 1861 WifiManager.WIFI_STATE_ENABLING, TAG + "#getWifiEnabledState"); 1862 } 1863 if (mVerboseLoggingEnabled) { 1864 mLog.info("getWifiEnabledState uid=% state=%").c(Binder.getCallingUid()).c( 1865 state).flush(); 1866 } 1867 return state; 1868 } 1869 1870 /** 1871 * See {@link WifiManager#addWifiStateChangedListener(Executor, WifiStateChangedListener)} 1872 */ addWifiStateChangedListener(@onNull IWifiStateChangedListener listener)1873 public void addWifiStateChangedListener(@NonNull IWifiStateChangedListener listener) { 1874 enforceAccessPermission(); 1875 if (listener == null) { 1876 throw new IllegalArgumentException("listener must not be null"); 1877 } 1878 if (mVerboseLoggingEnabled) { 1879 mLog.info("addWifiStateChangedListener uid=%").c(Binder.getCallingUid()).flush(); 1880 } 1881 mWifiThreadRunner.post(() -> mActiveModeWarden.addWifiStateChangedListener(listener), 1882 TAG + "#addWifiStateChangedListener"); 1883 } 1884 1885 /** 1886 * See {@link WifiManager#removeWifiStateChangedListener(WifiStateChangedListener)} 1887 */ removeWifiStateChangedListener(@onNull IWifiStateChangedListener listener)1888 public void removeWifiStateChangedListener(@NonNull IWifiStateChangedListener listener) { 1889 enforceAccessPermission(); 1890 if (listener == null) { 1891 throw new IllegalArgumentException("listener must not be null"); 1892 } 1893 if (mVerboseLoggingEnabled) { 1894 mLog.info("removeWifiStateChangedListener uid=%").c(Binder.getCallingUid()).flush(); 1895 } 1896 mWifiThreadRunner.post(() -> mActiveModeWarden.removeWifiStateChangedListener(listener), 1897 TAG + "#removeWifiStateChangedListener"); 1898 } 1899 1900 /** 1901 * see {@link WifiManager#getWifiApState()} 1902 * @return One of {@link WifiManager#WIFI_AP_STATE_DISABLED}, 1903 * {@link WifiManager#WIFI_AP_STATE_DISABLING}, 1904 * {@link WifiManager#WIFI_AP_STATE_ENABLED}, 1905 * {@link WifiManager#WIFI_AP_STATE_ENABLING}, 1906 * {@link WifiManager#WIFI_AP_STATE_FAILED} 1907 */ 1908 @Override getWifiApEnabledState()1909 public int getWifiApEnabledState() { 1910 enforceAccessPermission(); 1911 if (mVerboseLoggingEnabled) { 1912 mLog.info("getWifiApEnabledState uid=%").c(Binder.getCallingUid()).flush(); 1913 } 1914 return mTetheredSoftApTracker.getState().getState(); 1915 } 1916 1917 /** 1918 * see {@link android.net.wifi.WifiManager#updateInterfaceIpState(String, int)} 1919 * 1920 * The possible modes include: {@link WifiManager#IFACE_IP_MODE_TETHERED}, 1921 * {@link WifiManager#IFACE_IP_MODE_LOCAL_ONLY}, 1922 * {@link WifiManager#IFACE_IP_MODE_CONFIGURATION_ERROR} 1923 * 1924 * @param ifaceName String name of the updated interface 1925 * @param mode new operating mode of the interface 1926 * 1927 * @throws SecurityException if the caller does not have permission to call update 1928 */ 1929 @Override updateInterfaceIpState(String ifaceName, int mode)1930 public void updateInterfaceIpState(String ifaceName, int mode) { 1931 // NETWORK_STACK is a signature only permission. 1932 enforceNetworkStackPermission(); 1933 mLog.info("updateInterfaceIpState uid=%").c(Binder.getCallingUid()).flush(); 1934 // hand off the work to our handler thread 1935 mWifiThreadRunner.post(() -> mLohsSoftApTracker.updateInterfaceIpState(ifaceName, mode), 1936 TAG + "#updateInterfaceIpState"); 1937 } 1938 1939 /** 1940 * see {@link WifiManager#isDefaultCoexAlgorithmEnabled()} 1941 * @return {@code true} if the default coex algorithm is enabled. {@code false} otherwise. 1942 */ 1943 @Override isDefaultCoexAlgorithmEnabled()1944 public boolean isDefaultCoexAlgorithmEnabled() { 1945 return mResourceCache.getBoolean(R.bool.config_wifiDefaultCoexAlgorithmEnabled); 1946 } 1947 1948 /** 1949 * see {@link android.net.wifi.WifiManager#setCoexUnsafeChannels(List, int)} 1950 * @param unsafeChannels List of {@link CoexUnsafeChannel} to avoid. 1951 * @param restrictions Bitmap of {@link CoexRestriction} specifying the mandatory 1952 * uses of the specified channels. 1953 */ 1954 @Override 1955 @RequiresApi(Build.VERSION_CODES.S) setCoexUnsafeChannels( @onNull List<CoexUnsafeChannel> unsafeChannels, int restrictions)1956 public void setCoexUnsafeChannels( 1957 @NonNull List<CoexUnsafeChannel> unsafeChannels, int restrictions) { 1958 if (!SdkLevel.isAtLeastS()) { 1959 throw new UnsupportedOperationException(); 1960 } 1961 mContext.enforceCallingOrSelfPermission( 1962 Manifest.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS, "WifiService"); 1963 if (unsafeChannels == null) { 1964 throw new IllegalArgumentException("unsafeChannels cannot be null"); 1965 } 1966 if (mResourceCache.getBoolean(R.bool.config_wifiDefaultCoexAlgorithmEnabled)) { 1967 Log.e(TAG, "setCoexUnsafeChannels called but default coex algorithm is enabled"); 1968 return; 1969 } 1970 mWifiThreadRunner.post(() -> 1971 mCoexManager.setCoexUnsafeChannels(unsafeChannels, restrictions), 1972 TAG + "#setCoexUnsafeChannels"); 1973 } 1974 1975 /** 1976 * See {@link WifiManager#registerCoexCallback(WifiManager.CoexCallback)} 1977 */ 1978 @Override 1979 @RequiresApi(Build.VERSION_CODES.S) registerCoexCallback(@onNull ICoexCallback callback)1980 public void registerCoexCallback(@NonNull ICoexCallback callback) { 1981 if (!SdkLevel.isAtLeastS()) { 1982 throw new UnsupportedOperationException(); 1983 } 1984 mContext.enforceCallingOrSelfPermission( 1985 Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS, "WifiService"); 1986 if (callback == null) { 1987 throw new IllegalArgumentException("callback must not be null"); 1988 } 1989 if (mVerboseLoggingEnabled) { 1990 mLog.info("registerCoexCallback uid=%").c(Binder.getCallingUid()).flush(); 1991 } 1992 mWifiThreadRunner.post(() -> mCoexManager.registerRemoteCoexCallback(callback), 1993 TAG + "#registerCoexCallback"); 1994 } 1995 1996 /** 1997 * Check if input configuration is valid. 1998 * 1999 * Call this before calling {@link startTetheredHotspot(SoftApConfiguration)} or 2000 * {@link #setSoftApConfiguration(softApConfiguration)} to avoid unexpected error duo to 2001 * configuration is invalid. 2002 * 2003 * @param config a configuration would like to be checked. 2004 * @return true if config is valid, otherwise false. 2005 */ 2006 @Override validateSoftApConfiguration(SoftApConfiguration config)2007 public boolean validateSoftApConfiguration(SoftApConfiguration config) { 2008 int uid = Binder.getCallingUid(); 2009 boolean privileged = isSettingsOrSuw(Binder.getCallingPid(), uid); 2010 return WifiApConfigStore.validateApWifiConfiguration( 2011 config, privileged, mContext, mWifiNative); 2012 } 2013 2014 /** 2015 * See {@link WifiManager#unregisterCoexCallback(WifiManager.CoexCallback)} 2016 */ 2017 @Override 2018 @RequiresApi(Build.VERSION_CODES.S) unregisterCoexCallback(@onNull ICoexCallback callback)2019 public void unregisterCoexCallback(@NonNull ICoexCallback callback) { 2020 if (!SdkLevel.isAtLeastS()) { 2021 throw new UnsupportedOperationException(); 2022 } 2023 mContext.enforceCallingOrSelfPermission( 2024 Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS, "WifiService"); 2025 if (callback == null) { 2026 throw new IllegalArgumentException("callback must not be null"); 2027 } 2028 if (mVerboseLoggingEnabled) { 2029 mLog.info("unregisterCoexCallback uid=%").c(Binder.getCallingUid()).flush(); 2030 } 2031 mWifiThreadRunner.post(() -> mCoexManager.unregisterRemoteCoexCallback(callback), 2032 TAG + "#unregisterCoexCallback"); 2033 } 2034 2035 /** 2036 * see {@link android.net.wifi.WifiManager#startSoftAp(WifiConfiguration)} 2037 * @param wifiConfig SSID, security and channel details as part of WifiConfiguration 2038 * @return {@code true} if softap start was triggered 2039 * @throws SecurityException if the caller does not have permission to start softap 2040 */ 2041 @Override startSoftAp(WifiConfiguration wifiConfig, String packageName)2042 public boolean startSoftAp(WifiConfiguration wifiConfig, String packageName) { 2043 // NETWORK_STACK is a signature only permission. 2044 enforceNetworkStackPermission(); 2045 int callingUid = Binder.getCallingUid(); 2046 mWifiPermissionsUtil.checkPackage(callingUid, packageName); 2047 2048 mLog.info("startSoftAp uid=%").c(callingUid).flush(); 2049 2050 SoftApConfiguration softApConfig = null; 2051 if (wifiConfig != null) { 2052 softApConfig = ApConfigUtil.fromWifiConfiguration(wifiConfig); 2053 if (softApConfig == null) { 2054 return false; 2055 } 2056 } 2057 2058 if (!mTetheredSoftApTracker.setEnablingIfAllowed()) { 2059 mLog.err("Tethering is already active or activating.").flush(); 2060 return false; 2061 } 2062 2063 WorkSource requestorWs = new WorkSource(callingUid, packageName); 2064 long id = Binder.clearCallingIdentity(); 2065 try { 2066 if (!mActiveModeWarden.canRequestMoreSoftApManagers(requestorWs)) { 2067 // Take down LOHS if it is up. 2068 mLohsSoftApTracker.stopAll(); 2069 } 2070 } finally { 2071 Binder.restoreCallingIdentity(id); 2072 } 2073 2074 if (!startSoftApInternal(new SoftApModeConfiguration( 2075 WifiManager.IFACE_IP_MODE_TETHERED, softApConfig, 2076 mTetheredSoftApTracker.getSoftApCapability(), 2077 mCountryCode.getCountryCode(), null), requestorWs, null)) { 2078 mTetheredSoftApTracker.setFailedWhileEnabling(); 2079 return false; 2080 } 2081 mLastCallerInfoManager.put(WifiManager.API_SOFT_AP, Process.myTid(), 2082 callingUid, Binder.getCallingPid(), packageName, true); 2083 return true; 2084 } 2085 2086 /** 2087 * see {@link android.net.wifi.WifiManager#startTetheredHotspot(SoftApConfiguration)} 2088 * @param softApConfig SSID, security and channel details as part of SoftApConfiguration 2089 * @return {@code true} if softap start was triggered 2090 * @throws SecurityException if the caller does not have permission to start softap 2091 */ 2092 @Override startTetheredHotspot(@ullable SoftApConfiguration softApConfig, @NonNull String packageName)2093 public boolean startTetheredHotspot(@Nullable SoftApConfiguration softApConfig, 2094 @NonNull String packageName) { 2095 enforceValidCallingUser(); 2096 2097 // NETWORK_STACK is a signature only permission. 2098 enforceNetworkStackPermission(); 2099 int callingUid = Binder.getCallingUid(); 2100 mWifiPermissionsUtil.checkPackage(callingUid, packageName); 2101 2102 // If user restriction is set, cannot start softap 2103 if (mWifiTetheringDisallowed) { 2104 mLog.err("startTetheredHotspot with user restriction: not permitted").flush(); 2105 return false; 2106 } 2107 2108 mLog.info("startTetheredHotspot uid=%").c(callingUid).flush(); 2109 return startTetheredHotspotInternal(new SoftApModeConfiguration( 2110 WifiManager.IFACE_IP_MODE_TETHERED, softApConfig, 2111 mTetheredSoftApTracker.getSoftApCapability(), 2112 mCountryCode.getCountryCode(), null /* request */), callingUid, packageName, null); 2113 } 2114 2115 /** 2116 * see {@link WifiManager#startTetheredHotspot(TetheringManager.TetheringRequest, Executor, WifiManager.SoftApCallback)} 2117 * @param request TetheringRequest details of the Soft AP. 2118 * @return {@code true} if softap start was triggered 2119 * @throws SecurityException if the caller does not have permission to start softap 2120 */ 2121 @Override startTetheredHotspotRequest(@onNull TetheringManager.TetheringRequest request, @NonNull ISoftApCallback callback, @NonNull String packageName)2122 public void startTetheredHotspotRequest(@NonNull TetheringManager.TetheringRequest request, 2123 @NonNull ISoftApCallback callback, 2124 @NonNull String packageName) { 2125 if (request == null) { 2126 throw new IllegalArgumentException("TetheringRequest must not be null"); 2127 } 2128 if (callback == null) { 2129 throw new IllegalArgumentException("callback must not be null"); 2130 } 2131 2132 enforceValidCallingUser(); 2133 // NETWORK_STACK is a signature only permission. 2134 enforceNetworkStackPermission(); 2135 int callingUid = Binder.getCallingUid(); 2136 mWifiPermissionsUtil.checkPackage(callingUid, packageName); 2137 2138 // If user restriction is set, cannot start softap 2139 if (mWifiTetheringDisallowed) { 2140 mLog.err("startTetheredHotspotRequest with user restriction: not permitted").flush(); 2141 try { 2142 callback.onStateChanged(new SoftApState(WIFI_AP_STATE_FAILED, 2143 SAP_START_FAILURE_GENERAL, request, null)); 2144 } catch (RemoteException e) { 2145 Log.e(TAG, "ISoftApCallback.onStateChanged: remote exception -- " + e); 2146 } 2147 return; 2148 } 2149 2150 mLog.info("startTetheredHotspot uid=%").c(callingUid).flush(); 2151 startTetheredHotspotInternal(new SoftApModeConfiguration( 2152 WifiManager.IFACE_IP_MODE_TETHERED, 2153 com.android.net.flags.Flags.tetheringWithSoftApConfig() 2154 ? request.getSoftApConfiguration() : null, 2155 mTetheredSoftApTracker.getSoftApCapability(), 2156 mCountryCode.getCountryCode(), request), callingUid, packageName, callback); 2157 } 2158 2159 /** 2160 * Internal method to start tethered hotspot. Callers of this method should have already checked 2161 * proper permissions beyond the NetworkStack permission. 2162 */ startTetheredHotspotInternal(@onNull SoftApModeConfiguration modeConfig, int callingUid, String packageName, @Nullable ISoftApCallback callback)2163 private boolean startTetheredHotspotInternal(@NonNull SoftApModeConfiguration modeConfig, 2164 int callingUid, String packageName, @Nullable ISoftApCallback callback) { 2165 if (!mTetheredSoftApTracker.setEnablingIfAllowed()) { 2166 mLog.err("Tethering is already active or activating.").flush(); 2167 if (callback != null) { 2168 try { 2169 callback.onStateChanged(new SoftApState(WIFI_AP_STATE_FAILED, 2170 SAP_START_FAILURE_GENERAL, modeConfig.getTetheringRequest(), null)); 2171 } catch (RemoteException e) { 2172 Log.e(TAG, "ISoftApCallback.onStateChanged: remote exception -- " + e); 2173 } 2174 } 2175 return false; 2176 } 2177 2178 WorkSource requestorWs = new WorkSource(callingUid, packageName); 2179 long id = Binder.clearCallingIdentity(); 2180 try { 2181 if (!mActiveModeWarden.canRequestMoreSoftApManagers(requestorWs)) { 2182 // Take down LOHS if it is up. 2183 mLohsSoftApTracker.stopAll(); 2184 } 2185 } finally { 2186 Binder.restoreCallingIdentity(id); 2187 } 2188 2189 if (!startSoftApInternal(modeConfig, requestorWs, callback)) { 2190 mTetheredSoftApTracker.setFailedWhileEnabling(); 2191 return false; 2192 } 2193 mLastCallerInfoManager.put(WifiManager.API_TETHERED_HOTSPOT, Process.myTid(), 2194 callingUid, Binder.getCallingPid(), packageName, true); 2195 return true; 2196 } 2197 2198 /** 2199 * Internal method to start softap mode. Callers of this method should have already checked 2200 * proper permissions beyond the NetworkStack permission. 2201 */ startSoftApInternal(SoftApModeConfiguration apConfig, WorkSource requestorWs, @Nullable ISoftApCallback callback)2202 private boolean startSoftApInternal(SoftApModeConfiguration apConfig, WorkSource requestorWs, 2203 @Nullable ISoftApCallback callback) { 2204 int uid = Binder.getCallingUid(); 2205 boolean privileged = isSettingsOrSuw(Binder.getCallingPid(), uid); 2206 mLog.trace("startSoftApInternal uid=% mode=%") 2207 .c(uid).c(apConfig.getTargetMode()).flush(); 2208 2209 // null wifiConfig is a meaningful input for CMD_SET_AP; it means to use the persistent 2210 // AP config. 2211 SoftApConfiguration softApConfig = apConfig.getSoftApConfiguration(); 2212 if (softApConfig != null 2213 && (!WifiApConfigStore.validateApWifiConfiguration( 2214 softApConfig, privileged, mContext, mWifiNative))) { 2215 Log.e(TAG, "Invalid SoftApConfiguration"); 2216 if (callback != null) { 2217 try { 2218 callback.onStateChanged(new SoftApState(WIFI_AP_STATE_FAILED, 2219 SAP_START_FAILURE_GENERAL, 2220 apConfig.getTetheringRequest(), null)); 2221 } catch (RemoteException e) { 2222 Log.e(TAG, "ISoftApCallback.onStateChanged: remote exception -- " + e); 2223 } 2224 } 2225 return false; 2226 } 2227 if (apConfig.getTargetMode() == IFACE_IP_MODE_TETHERED) { 2228 mTetheredSoftApTracker.setRequestCallback(callback); 2229 } 2230 mActiveModeWarden.startSoftAp(apConfig, requestorWs); 2231 return true; 2232 } 2233 2234 /** 2235 * see {@link android.net.wifi.WifiManager#stopSoftAp()} 2236 * @return {@code true} if softap stop was triggered 2237 * @throws SecurityException if the caller does not have permission to stop softap 2238 */ 2239 @Override stopSoftAp()2240 public boolean stopSoftAp() { 2241 enforceValidCallingUser(); 2242 2243 // NETWORK_STACK is a signature only permission. 2244 enforceNetworkStackPermission(); 2245 2246 // only permitted callers are allowed to this point - they must have gone through 2247 // connectivity service since this method is protected with the NETWORK_STACK PERMISSION 2248 2249 mLog.info("stopSoftAp uid=%").c(Binder.getCallingUid()).flush(); 2250 2251 stopSoftApInternal(WifiManager.IFACE_IP_MODE_TETHERED); 2252 mLastCallerInfoManager.put(WifiManager.API_SOFT_AP, Process.myTid(), 2253 Binder.getCallingUid(), Binder.getCallingPid(), "<unknown>", false); 2254 return true; 2255 } 2256 2257 /** 2258 * Internal method to stop softap mode. 2259 * 2260 * Callers of this method should have already checked 2261 * proper permissions beyond the NetworkStack permission. 2262 * 2263 * @param mode the operating mode of APs to bring down (ex, 2264 * {@link WifiManager.IFACE_IP_MODE_TETHERED} or 2265 * {@link WifiManager.IFACE_IP_MODE_LOCAL_ONLY}). 2266 * Use {@link WifiManager.IFACE_IP_MODE_UNSPECIFIED} to stop all APs. 2267 */ stopSoftApInternal(int mode)2268 private void stopSoftApInternal(int mode) { 2269 mLog.trace("stopSoftApInternal uid=% mode=%").c(Binder.getCallingUid()).c(mode).flush(); 2270 2271 mActiveModeWarden.stopSoftAp(mode); 2272 } 2273 2274 /** 2275 * Internal class for tracking country code changed event. 2276 */ 2277 @VisibleForTesting 2278 public final class CountryCodeTracker implements WifiCountryCode.ChangeListener { 2279 private final RemoteCallbackList<IOnWifiDriverCountryCodeChangedListener> 2280 mRegisteredDriverCountryCodeListeners = new RemoteCallbackList<>(); 2281 2282 /** 2283 * Register Driver Country code changed listener. 2284 * Note: Calling API only in handler thread. 2285 * 2286 * @param listener listener for the driver country code changed events. 2287 */ registerDriverCountryCodeChangedListener( @onNull IOnWifiDriverCountryCodeChangedListener listener, @NonNull WifiPermissionsUtil.CallerIdentity identity)2288 public void registerDriverCountryCodeChangedListener( 2289 @NonNull IOnWifiDriverCountryCodeChangedListener listener, 2290 @NonNull WifiPermissionsUtil.CallerIdentity identity) { 2291 boolean result = mRegisteredDriverCountryCodeListeners.register(listener, identity); 2292 if (mVerboseLoggingEnabled) { 2293 Log.i(TAG, "registerDriverCountryCodeChangedListener, listener:" + listener 2294 + ", CallerIdentity=" + identity.toString() + ", result: " + result); 2295 } 2296 } 2297 2298 2299 /** 2300 * Unregister Driver Country code changed listener. 2301 * Note: Calling API only in handler thread. 2302 * 2303 * @param listener listener to remove. 2304 */ unregisterDriverCountryCodeChangedListener( @onNull IOnWifiDriverCountryCodeChangedListener listener)2305 public void unregisterDriverCountryCodeChangedListener( 2306 @NonNull IOnWifiDriverCountryCodeChangedListener listener) { 2307 boolean result = mRegisteredDriverCountryCodeListeners.unregister(listener); 2308 if (mVerboseLoggingEnabled) { 2309 Log.i(TAG, "unregisterDriverCountryCodeChangedListener, listener:" + listener 2310 + ", result:" + result); 2311 } 2312 } 2313 2314 @Override onCountryCodeChangePending(@onNull String countryCode)2315 public void onCountryCodeChangePending(@NonNull String countryCode) { 2316 // post operation to handler thread 2317 mWifiThreadRunner.post(() -> { 2318 if (mTetheredSoftApTracker != null) { 2319 mTetheredSoftApTracker.notifyNewCountryCodeChangePending(countryCode); 2320 } 2321 if (mLohsSoftApTracker != null) { 2322 mLohsSoftApTracker.notifyNewCountryCodeChangePending(countryCode); 2323 } 2324 }, this.getClass().getSimpleName() + "#onCountryCodeChangePending"); 2325 } 2326 2327 @Override onDriverCountryCodeChanged(@ullable String countryCode)2328 public void onDriverCountryCodeChanged(@Nullable String countryCode) { 2329 // post operation to handler thread 2330 mWifiThreadRunner.post(() -> { 2331 Log.i(TAG, "Receive onDriverCountryCodeChanged to " + countryCode 2332 + ", update available channel list"); 2333 // Update channel capability when country code is not null. 2334 // Because the driver country code will reset to null when driver is non-active. 2335 if (countryCode != null) { 2336 if (!TextUtils.equals(countryCode, 2337 mCountryCode.getCurrentDriverCountryCode())) { 2338 Log.e(TAG, "Country code not consistent! expect " + countryCode + " actual " 2339 + mCountryCode.getCurrentDriverCountryCode()); 2340 } 2341 List<Integer> freqs = new ArrayList<>(); 2342 SparseArray<int[]> channelMap = new SparseArray<>( 2343 SoftApConfiguration.BAND_TYPES.length); 2344 for (int band : SoftApConfiguration.BAND_TYPES) { 2345 if (!ApConfigUtil.isSoftApBandSupported(mContext, band)) { 2346 continue; 2347 } 2348 List<Integer> freqsForBand = ApConfigUtil.getAvailableChannelFreqsForBand( 2349 band, mWifiNative, null, true); 2350 if (freqsForBand != null) { 2351 freqs.addAll(freqsForBand); 2352 int[] channel = new int[freqsForBand.size()]; 2353 for (int i = 0; i < freqsForBand.size(); i++) { 2354 channel[i] = ScanResult.convertFrequencyMhzToChannelIfSupported( 2355 freqsForBand.get(i)); 2356 } 2357 channelMap.put(band, channel); 2358 } 2359 } 2360 if (!mCountryCode.isDriverCountryCodeWorldMode() 2361 || TextUtils.isEmpty(mSettingsConfigStore.get( 2362 WifiSettingsConfigStore.WIFI_SOFT_AP_COUNTRY_CODE))) { 2363 // Store Soft AP channels (non-world mode CC or no save before) for 2364 // reference after a reboot before the driver is up. 2365 mSettingsConfigStore.put(WifiSettingsConfigStore.WIFI_SOFT_AP_COUNTRY_CODE, 2366 countryCode); 2367 mSettingsConfigStore.put( 2368 WifiSettingsConfigStore.WIFI_AVAILABLE_SOFT_AP_FREQS_MHZ, 2369 new JSONArray(freqs).toString()); 2370 } 2371 mTetheredSoftApTracker.updateAvailChannelListInSoftApCapability(countryCode, 2372 channelMap); 2373 mLohsSoftApTracker.updateAvailChannelListInSoftApCapability(countryCode, 2374 channelMap); 2375 mActiveModeWarden.updateSoftApCapability( 2376 mTetheredSoftApTracker.getSoftApCapability(), 2377 WifiManager.IFACE_IP_MODE_TETHERED); 2378 // TODO: b/197529327 trigger Lohs capability callback & update available 2379 // channels 2380 mActiveModeWarden.updateSoftApCapability( 2381 mLohsSoftApTracker.getSoftApCapability(), 2382 WifiManager.IFACE_IP_MODE_LOCAL_ONLY); 2383 } 2384 if (SdkLevel.isAtLeastT()) { 2385 int itemCount = mRegisteredDriverCountryCodeListeners.beginBroadcast(); 2386 for (int i = 0; i < itemCount; i++) { 2387 try { 2388 WifiPermissionsUtil.CallerIdentity identity = 2389 (WifiPermissionsUtil.CallerIdentity) 2390 mRegisteredDriverCountryCodeListeners.getBroadcastCookie(i); 2391 if (!mWifiPermissionsUtil.checkCallersCoarseLocationPermission( 2392 identity.getPackageName(), identity.getFeatureId(), 2393 identity.getUid(), null)) { 2394 Log.i(TAG, "ReceiverIdentity=" + identity.toString() 2395 + " doesn't have ACCESS_COARSE_LOCATION permission now"); 2396 continue; 2397 } 2398 if (mVerboseLoggingEnabled) { 2399 Log.i(TAG, "onDriverCountryCodeChanged, ReceiverIdentity=" 2400 + identity.toString()); 2401 } 2402 mRegisteredDriverCountryCodeListeners.getBroadcastItem(i) 2403 .onDriverCountryCodeChanged(countryCode); 2404 } catch (RemoteException e) { 2405 Log.e(TAG, "onDriverCountryCodeChanged: remote exception -- " + e); 2406 } 2407 } 2408 mRegisteredDriverCountryCodeListeners.finishBroadcast(); 2409 } 2410 mAfcManager.onCountryCodeChange(countryCode); 2411 }, this.getClass().getSimpleName() + "#onCountryCodeChangePending"); 2412 } 2413 } 2414 2415 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 2416 class UwbAdapterStateListener implements UwbManager.AdapterStateCallback { 2417 @Override onStateChanged(int state, int reason)2418 public void onStateChanged(int state, int reason) { 2419 if (mVerboseLoggingEnabled) { 2420 Log.d(TAG, "UwbManager.AdapterState=" + state); 2421 } 2422 mWifiMetrics.setLastUwbState(state); 2423 } 2424 } 2425 2426 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 2427 class ThreadStateListener implements ThreadNetworkController.StateCallback { 2428 @Override onDeviceRoleChanged(int mDeviceRole)2429 public void onDeviceRoleChanged(int mDeviceRole) { 2430 if (mVerboseLoggingEnabled) { 2431 Log.d(TAG, "ThreadNetworkController.DeviceRole=" + mDeviceRole); 2432 } 2433 mWifiMetrics.setLastThreadDeviceRole(mDeviceRole); 2434 } 2435 2436 @Override onPartitionIdChanged(long mPartitionId)2437 public void onPartitionIdChanged(long mPartitionId) {} 2438 } 2439 2440 /** 2441 * SoftAp callback 2442 */ 2443 private class BaseSoftApTracker extends SoftApCallbackInternal { 2444 /** 2445 * State of tethered SoftAP 2446 * One of: {@link WifiManager#WIFI_AP_STATE_DISABLED}, 2447 * {@link WifiManager#WIFI_AP_STATE_DISABLING}, 2448 * {@link WifiManager#WIFI_AP_STATE_ENABLED}, 2449 * {@link WifiManager#WIFI_AP_STATE_ENABLING}, 2450 * {@link WifiManager#WIFI_AP_STATE_FAILED} 2451 */ 2452 private final Object mLock = new Object(); 2453 @NonNull 2454 private SoftApState mSoftApState = 2455 new SoftApState(WIFI_AP_STATE_DISABLED, 0, null, null); 2456 private Map<String, List<WifiClient>> mSoftApConnectedClientsMap = new HashMap(); 2457 private Map<String, SoftApInfo> mSoftApInfoMap = new HashMap(); 2458 private boolean mIsBridgedMode = false; 2459 // TODO: We need to maintain two capability. One for LTE + SAP and one for WIFI + SAP 2460 protected SoftApCapability mSoftApCapability = null; 2461 protected final RemoteCallbackList<ISoftApCallback> mRegisteredSoftApCallbacks = 2462 new RemoteCallbackList<>(); 2463 // Callback tied to the current SoftAp request. 2464 protected ISoftApCallback mRequestCallback = null; 2465 getState()2466 public SoftApState getState() { 2467 synchronized (mLock) { 2468 return mSoftApState; 2469 } 2470 } 2471 setState(SoftApState softApState)2472 public void setState(SoftApState softApState) { 2473 synchronized (mLock) { 2474 mSoftApState = softApState; 2475 } 2476 } 2477 setEnablingIfAllowed()2478 public boolean setEnablingIfAllowed() { 2479 synchronized (mLock) { 2480 int state = mSoftApState.getState(); 2481 if (state != WIFI_AP_STATE_DISABLED 2482 && state != WIFI_AP_STATE_FAILED) { 2483 return false; 2484 } 2485 mSoftApState = new SoftApState( 2486 WIFI_AP_STATE_ENABLING, 0, null, null); 2487 return true; 2488 } 2489 } 2490 setFailedWhileEnabling()2491 public void setFailedWhileEnabling() { 2492 synchronized (mLock) { 2493 int state = mSoftApState.getState(); 2494 if (state == WIFI_AP_STATE_ENABLING) { 2495 mSoftApState = new SoftApState( 2496 WIFI_AP_STATE_FAILED, 0, null, null); 2497 } 2498 } 2499 } 2500 getConnectedClients()2501 public Map<String, List<WifiClient>> getConnectedClients() { 2502 synchronized (mLock) { 2503 return mSoftApConnectedClientsMap; 2504 } 2505 } 2506 getSoftApInfos()2507 public Map<String, SoftApInfo> getSoftApInfos() { 2508 synchronized (mLock) { 2509 return mSoftApInfoMap; 2510 } 2511 } 2512 getIsBridgedMode()2513 public boolean getIsBridgedMode() { 2514 synchronized (mLock) { 2515 return mIsBridgedMode; 2516 } 2517 } 2518 notifyNewCountryCodeChangePending(@onNull String countryCode)2519 public void notifyNewCountryCodeChangePending(@NonNull String countryCode) { 2520 // If country code not changed, no need to update. 2521 if (mSoftApCapability != null && !TextUtils.equals(mSoftApCapability.getCountryCode(), 2522 countryCode)) { 2523 // Country code changed when we can't update channels from HAL, invalidate the soft 2524 // ap capability for supported channels. 2525 SoftApCapability newSoftApCapability = new SoftApCapability( 2526 mSoftApCapability); 2527 for (int b : SoftApConfiguration.BAND_TYPES) { 2528 newSoftApCapability.setSupportedChannelList(b, new int[0]); 2529 } 2530 // Notify the capability change 2531 onCapabilityChanged(newSoftApCapability); 2532 } 2533 } 2534 getSoftApCapability()2535 public SoftApCapability getSoftApCapability() { 2536 synchronized (mLock) { 2537 if (mSoftApCapability == null) { 2538 mSoftApCapability = ApConfigUtil.updateCapabilityFromResource(mContext); 2539 mSoftApCapability = ApConfigUtil.updateCapabilityFromConfigStore( 2540 mSoftApCapability, mWifiInjector.getSettingsConfigStore()); 2541 // Default country code 2542 mSoftApCapability = updateSoftApCapabilityWithAvailableChannelList( 2543 mSoftApCapability, mCountryCode.getCountryCode(), null); 2544 if (mWifiNative.isMLDApSupportMLO()) { 2545 mSoftApCapability.setSupportedFeatures( 2546 true, SoftApCapability.SOFTAP_FEATURE_MLO); 2547 } 2548 } 2549 return mSoftApCapability; 2550 } 2551 } 2552 updateSoftApCapabilityWithAvailableChannelList( @onNull SoftApCapability softApCapability, @Nullable String countryCode, @Nullable SparseArray<int[]> channelMap)2553 private SoftApCapability updateSoftApCapabilityWithAvailableChannelList( 2554 @NonNull SoftApCapability softApCapability, @Nullable String countryCode, 2555 @Nullable SparseArray<int[]> channelMap) { 2556 if (!mIsBootComplete) { 2557 // The available channel list is from wificond or HAL. 2558 // It might be a failure or stuck during wificond or HAL init. 2559 return softApCapability; 2560 } 2561 if (mCountryCode.getCurrentDriverCountryCode() != null) { 2562 mSoftApCapability.setCountryCode(countryCode); 2563 } 2564 return ApConfigUtil.updateSoftApCapabilityWithAvailableChannelList( 2565 softApCapability, mContext, mWifiNative, channelMap); 2566 } 2567 updateAvailChannelListInSoftApCapability(@ullable String countryCode, @Nullable SparseArray<int[]> channelMap)2568 public void updateAvailChannelListInSoftApCapability(@Nullable String countryCode, 2569 @Nullable SparseArray<int[]> channelMap) { 2570 onCapabilityChanged(updateSoftApCapabilityWithAvailableChannelList( 2571 getSoftApCapability(), countryCode, channelMap)); 2572 } 2573 registerSoftApCallback(ISoftApCallback callback, Object cookie)2574 public boolean registerSoftApCallback(ISoftApCallback callback, Object cookie) { 2575 if (!mRegisteredSoftApCallbacks.register(callback, cookie)) { 2576 return false; 2577 } 2578 2579 // Update the client about the current state immediately after registering the callback 2580 try { 2581 callback.onStateChanged(getState()); 2582 callback.onConnectedClientsOrInfoChanged(getSoftApInfos(), 2583 getConnectedClients(), getIsBridgedMode(), true); 2584 callback.onCapabilityChanged(getSoftApCapability()); 2585 } catch (RemoteException e) { 2586 Log.e(TAG, "registerSoftApCallback: remote exception -- " + e); 2587 } 2588 return true; 2589 } 2590 unregisterSoftApCallback(ISoftApCallback callback)2591 public void unregisterSoftApCallback(ISoftApCallback callback) { 2592 mRegisteredSoftApCallbacks.unregister(callback); 2593 } 2594 2595 /** 2596 * Set the callback to track the state of the current SoftAP request. 2597 */ setRequestCallback(@ullable ISoftApCallback callback)2598 public void setRequestCallback(@Nullable ISoftApCallback callback) { 2599 if (mRequestCallback != null) { 2600 mRegisteredSoftApCallbacks.unregister(mRequestCallback); 2601 } 2602 mRequestCallback = callback; 2603 if (callback != null) { 2604 mRegisteredSoftApCallbacks.register(callback); 2605 } 2606 } 2607 2608 /** 2609 * Called when soft AP state changes. 2610 */ 2611 @Override onStateChanged(SoftApState softApState)2612 public void onStateChanged(SoftApState softApState) { 2613 setState(softApState); 2614 notifyRegisterOnStateChanged(mRegisteredSoftApCallbacks, softApState); 2615 } 2616 2617 /** 2618 * Called when the connected clients to soft AP changes. 2619 * 2620 * @param clients connected clients to soft AP 2621 */ 2622 @Override onConnectedClientsOrInfoChanged(Map<String, SoftApInfo> infos, Map<String, List<WifiClient>> clients, boolean isBridged)2623 public void onConnectedClientsOrInfoChanged(Map<String, SoftApInfo> infos, 2624 Map<String, List<WifiClient>> clients, boolean isBridged) { 2625 synchronized (mLock) { 2626 mIsBridgedMode = isBridged; 2627 if (infos.size() == 0 && isBridged) { 2628 Log.d(TAG, "ShutDown bridged mode, clear isBridged cache in Service"); 2629 mIsBridgedMode = false; 2630 } 2631 mSoftApConnectedClientsMap = 2632 ApConfigUtil.deepCopyForWifiClientListMap(clients); 2633 mSoftApInfoMap = ApConfigUtil.deepCopyForSoftApInfoMap(infos); 2634 } 2635 notifyRegisterOnConnectedClientsOrInfoChanged(mRegisteredSoftApCallbacks, 2636 infos, clients, isBridged); 2637 } 2638 2639 /** 2640 * Called when capability of softap changes. 2641 * 2642 * @param capability is the softap capability. {@link SoftApCapability} 2643 */ 2644 @Override onCapabilityChanged(SoftApCapability capability)2645 public void onCapabilityChanged(SoftApCapability capability) { 2646 synchronized (mLock) { 2647 if (Objects.equals(capability, mSoftApCapability)) { 2648 return; 2649 } 2650 mSoftApCapability = new SoftApCapability(capability); 2651 } 2652 notifyRegisterOnCapabilityChanged(mRegisteredSoftApCallbacks, 2653 mSoftApCapability); 2654 } 2655 2656 /** 2657 * Called when client trying to connect but device blocked the client with specific reason. 2658 * 2659 * @param client the currently blocked client. 2660 * @param blockedReason one of blocked reason from 2661 * {@link WifiManager.SapClientBlockedReason} 2662 */ 2663 @Override onBlockedClientConnecting(WifiClient client, int blockedReason)2664 public void onBlockedClientConnecting(WifiClient client, int blockedReason) { 2665 notifyRegisterOnBlockedClientConnecting(mRegisteredSoftApCallbacks, client, 2666 blockedReason); 2667 } 2668 2669 /** 2670 * Called when clients disconnect from a soft AP instance. 2671 * 2672 * @param info The {@link SoftApInfo} of the AP. 2673 * @param clients The clients that have disconnected from the AP instance specified by 2674 * {@code info}. 2675 */ 2676 @Override onClientsDisconnected(@onNull SoftApInfo info, @NonNull List<WifiClient> clients)2677 public void onClientsDisconnected(@NonNull SoftApInfo info, 2678 @NonNull List<WifiClient> clients) { 2679 notifyRegisterOnClientsDisconnected(mRegisteredSoftApCallbacks, info, clients); 2680 } 2681 } 2682 2683 private final class TetheredSoftApTracker extends BaseSoftApTracker { updateSoftApCapabilityWhenCarrierConfigChanged(int subId)2684 public void updateSoftApCapabilityWhenCarrierConfigChanged(int subId) { 2685 CarrierConfigManager carrierConfigManager = 2686 mContext.getSystemService(CarrierConfigManager.class); 2687 if (carrierConfigManager == null) return; 2688 PersistableBundle carrierConfig = carrierConfigManager.getConfigForSubId(subId); 2689 if (carrierConfig == null) return; 2690 int carrierMaxClient = carrierConfig.getInt( 2691 CarrierConfigManager.Wifi.KEY_HOTSPOT_MAX_CLIENT_COUNT); 2692 int finalSupportedClientNumber = mResourceCache.getInteger( 2693 R.integer.config_wifiHardwareSoftapMaxClientCount); 2694 if (carrierMaxClient > 0) { 2695 finalSupportedClientNumber = Math.min(finalSupportedClientNumber, 2696 carrierMaxClient); 2697 } 2698 if (finalSupportedClientNumber == getSoftApCapability().getMaxSupportedClients()) { 2699 return; 2700 } 2701 SoftApCapability newSoftApCapability = new SoftApCapability(mSoftApCapability); 2702 newSoftApCapability.setMaxSupportedClients( 2703 finalSupportedClientNumber); 2704 onCapabilityChanged(newSoftApCapability); 2705 } 2706 2707 } 2708 2709 /** 2710 * Implements LOHS behavior on top of the existing SoftAp API. 2711 */ 2712 private final class LohsSoftApTracker extends BaseSoftApTracker { 2713 private static final int UNSPECIFIED_PID = -1; 2714 2715 @GuardedBy("mLocalOnlyHotspotRequests") 2716 private final HashMap<Integer, LocalOnlyHotspotRequestInfo> 2717 mLocalOnlyHotspotRequests = new HashMap<>(); 2718 2719 /** Currently-active config, to be sent to shared clients registering later. */ 2720 @GuardedBy("mLocalOnlyHotspotRequests") 2721 private SoftApModeConfiguration mActiveConfig = null; 2722 2723 /** 2724 * Whether we are currently operating in exclusive mode (i.e. whether a custom config is 2725 * active). 2726 */ 2727 @GuardedBy("mLocalOnlyHotspotRequests") 2728 private boolean mIsExclusive = false; 2729 2730 @GuardedBy("mLocalOnlyHotspotRequests") 2731 private WorkSource mCurrentWs = null; 2732 2733 @GuardedBy("mLocalOnlyHotspotRequests") 2734 private String mLohsInterfaceName; 2735 2736 @GuardedBy("mLocalOnlyHotspotRequests") 2737 private int mLohsInterfaceMode = WifiManager.IFACE_IP_MODE_UNSPECIFIED; 2738 2739 @GuardedBy("mLocalOnlyHotspotRequests") 2740 private int mPidRestartingLohsFor = UNSPECIFIED_PID; 2741 @Override checkCallbackPermission(@ullable Object broadcastCookie)2742 public boolean checkCallbackPermission(@Nullable Object broadcastCookie) { 2743 if (!SdkLevel.isAtLeastS()) { 2744 // AttributionSource requires at least S. 2745 return false; 2746 } 2747 if (!(broadcastCookie instanceof AttributionSource)) { 2748 return false; 2749 } 2750 return mWifiPermissionsUtil.checkNearbyDevicesPermission( 2751 (AttributionSource) broadcastCookie, 2752 false /* checkForLocation */, 2753 TAG + " " + this.getClass().getSimpleName() + "#checkCallbackPermission"); 2754 } updateInterfaceIpState(String ifaceName, int mode)2755 public void updateInterfaceIpState(String ifaceName, int mode) { 2756 // update interface IP state related to local-only hotspot 2757 synchronized (mLocalOnlyHotspotRequests) { 2758 Log.d(TAG, "updateInterfaceIpState: ifaceName=" + ifaceName + " mode=" + mode 2759 + " previous LOHS mode= " + mLohsInterfaceMode); 2760 2761 switch (mode) { 2762 case WifiManager.IFACE_IP_MODE_LOCAL_ONLY: 2763 // first make sure we have registered requests. 2764 if (mLocalOnlyHotspotRequests.isEmpty()) { 2765 // we don't have requests... stop the hotspot 2766 Log.wtf(TAG, "Starting LOHS without any requests?"); 2767 stopSoftApInternal(WifiManager.IFACE_IP_MODE_LOCAL_ONLY); 2768 return; 2769 } 2770 // LOHS is ready to go! Call our registered requestors! 2771 mLohsInterfaceName = ifaceName; 2772 mLohsInterfaceMode = mode; 2773 sendHotspotStartedMessageToAllLOHSRequestInfoEntriesLocked(); 2774 break; 2775 case WifiManager.IFACE_IP_MODE_TETHERED: 2776 if (TextUtils.equals(mLohsInterfaceName, ifaceName)) { 2777 /* This shouldn't happen except in a race, but if it does, tear down 2778 * the LOHS and let tethering win. 2779 * 2780 * If concurrent SAPs are allowed, the interface names will differ, 2781 * so we don't have to check the config here. 2782 */ 2783 Log.e(TAG, "Unexpected IP mode change on " + ifaceName); 2784 mLohsInterfaceName = null; 2785 mLohsInterfaceMode = WifiManager.IFACE_IP_MODE_UNSPECIFIED; 2786 sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked( 2787 LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE); 2788 } 2789 break; 2790 case WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR: 2791 if (ifaceName == null) { 2792 // All softAps 2793 mLohsInterfaceName = null; 2794 mLohsInterfaceMode = mode; 2795 sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked( 2796 LocalOnlyHotspotCallback.ERROR_GENERIC); 2797 stopSoftApInternal(WifiManager.IFACE_IP_MODE_UNSPECIFIED); 2798 } else if (TextUtils.equals(mLohsInterfaceName, ifaceName)) { 2799 mLohsInterfaceName = null; 2800 mLohsInterfaceMode = mode; 2801 sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked( 2802 LocalOnlyHotspotCallback.ERROR_GENERIC); 2803 stopSoftApInternal(WifiManager.IFACE_IP_MODE_LOCAL_ONLY); 2804 } else { 2805 // Not for LOHS. This is the wrong place to do this, but... 2806 stopSoftApInternal(WifiManager.IFACE_IP_MODE_TETHERED); 2807 } 2808 break; 2809 case WifiManager.IFACE_IP_MODE_UNSPECIFIED: 2810 if (ifaceName == null || ifaceName.equals(mLohsInterfaceName)) { 2811 mLohsInterfaceName = null; 2812 mLohsInterfaceMode = mode; 2813 } 2814 break; 2815 default: 2816 mLog.warn("updateInterfaceIpState: unknown mode %").c(mode).flush(); 2817 } 2818 } 2819 } 2820 2821 /** 2822 * Helper method to send a HOTSPOT_FAILED message to all registered LocalOnlyHotspotRequest 2823 * callers and clear the registrations. 2824 * 2825 * Callers should already hold the mLocalOnlyHotspotRequests lock. 2826 */ 2827 @GuardedBy("mLocalOnlyHotspotRequests") sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked(int reason)2828 private void sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked(int reason) { 2829 for (LocalOnlyHotspotRequestInfo requestor : mLocalOnlyHotspotRequests.values()) { 2830 try { 2831 requestor.sendHotspotFailedMessage(reason); 2832 requestor.unlinkDeathRecipient(); 2833 } catch (RemoteException e) { 2834 // This will be cleaned up by binder death handling 2835 } 2836 } 2837 2838 // Since all callers were notified, now clear the registrations. 2839 mLocalOnlyHotspotRequests.clear(); 2840 mPidRestartingLohsFor = UNSPECIFIED_PID; 2841 } 2842 2843 /** 2844 * Helper method to send a HOTSPOT_STOPPED message to all registered LocalOnlyHotspotRequest 2845 * callers and clear the registrations. 2846 * 2847 * Callers should already hold the mLocalOnlyHotspotRequests lock. 2848 */ 2849 @GuardedBy("mLocalOnlyHotspotRequests") sendHotspotStoppedMessageToAllLOHSRequestInfoEntriesLocked()2850 private void sendHotspotStoppedMessageToAllLOHSRequestInfoEntriesLocked() { 2851 for (LocalOnlyHotspotRequestInfo requestor : mLocalOnlyHotspotRequests.values()) { 2852 try { 2853 requestor.sendHotspotStoppedMessage(); 2854 requestor.unlinkDeathRecipient(); 2855 } catch (RemoteException e) { 2856 // This will be cleaned up by binder death handling 2857 } 2858 } 2859 2860 // Since all callers were notified, now clear the registrations. 2861 mLocalOnlyHotspotRequests.clear(); 2862 } 2863 2864 /** 2865 * Add a new LOHS client 2866 */ start(int pid, LocalOnlyHotspotRequestInfo request)2867 private int start(int pid, LocalOnlyHotspotRequestInfo request) { 2868 synchronized (mLocalOnlyHotspotRequests) { 2869 // does this caller already have a request? 2870 if (mLocalOnlyHotspotRequests.get(pid) != null) { 2871 mLog.trace("caller already has an active request").flush(); 2872 throw new IllegalStateException( 2873 "Caller already has an active LocalOnlyHotspot request"); 2874 } 2875 2876 // Never accept exclusive requests (with custom configuration) at the same time as 2877 // shared requests. 2878 if (!mLocalOnlyHotspotRequests.isEmpty()) { 2879 final boolean requestIsExclusive = request.getCustomConfig() != null; 2880 final int newRequestorWsPriority = mWifiInjector 2881 .makeWsHelper(request.getWorkSource()).getRequestorWsPriority(); 2882 final int currentWsPriority = mWifiInjector 2883 .makeWsHelper(mCurrentWs).getRequestorWsPriority(); 2884 final boolean isCurrentLohsWorksOnNonDefaultBand = mActiveConfig != null 2885 && mActiveConfig.getSoftApConfiguration().getBand() 2886 != SoftApConfiguration.BAND_2GHZ; 2887 Log.d(TAG, "Receive multiple LOHS requestors," 2888 + ", requestIsExclusive: " + requestIsExclusive 2889 + ", mIsExclusive: " + mIsExclusive 2890 + ", currentWsPriority: " + currentWsPriority 2891 + ", newRequestorWsPriority: " + newRequestorWsPriority); 2892 if (requestIsExclusive || mIsExclusive 2893 || (currentWsPriority >= newRequestorWsPriority 2894 && isCurrentLohsWorksOnNonDefaultBand)) { 2895 mLog.trace("Cannot share with existing LOHS request due to custom config") 2896 .flush(); 2897 return LocalOnlyHotspotCallback.ERROR_GENERIC; 2898 } 2899 if (mFeatureFlags.publicBandsForLohs() && isCurrentLohsWorksOnNonDefaultBand) { 2900 // Current LOHS is not using 2.4 band, and new caller priority is higher. 2901 // stop all and logging the new requestor pid. 2902 mLog.trace("Restarting LOHS to default band for new requestor") 2903 .flush(); 2904 mLohsSoftApTracker.stopAll(); 2905 mPidRestartingLohsFor = pid; 2906 } 2907 } 2908 // At this point, the request is accepted. 2909 if (mLocalOnlyHotspotRequests.isEmpty()) { 2910 mWifiThreadRunner.post(() -> { 2911 startForFirstRequestLocked(request); 2912 }, "LohsSoftApTracker#start"); 2913 2914 } else if (mLohsInterfaceMode == WifiManager.IFACE_IP_MODE_LOCAL_ONLY) { 2915 // LOHS has already started up for an earlier request, so we can send the 2916 // current config to the incoming request right away. 2917 try { 2918 mLog.trace("LOHS already up, trigger onStarted callback").flush(); 2919 request.sendHotspotStartedMessage(mActiveConfig.getSoftApConfiguration()); 2920 } catch (RemoteException e) { 2921 return LocalOnlyHotspotCallback.ERROR_GENERIC; 2922 } 2923 } 2924 mLocalOnlyHotspotRequests.put(pid, request); 2925 return LocalOnlyHotspotCallback.REQUEST_REGISTERED; 2926 } 2927 } 2928 2929 @GuardedBy("mLocalOnlyHotspotRequests") startForFirstRequestLocked(LocalOnlyHotspotRequestInfo request)2930 private void startForFirstRequestLocked(LocalOnlyHotspotRequestInfo request) { 2931 mCurrentWs = request.getWorkSource(); 2932 final int currentWsPriority = mWifiInjector.makeWsHelper(mCurrentWs) 2933 .getRequestorWsPriority(); 2934 if (mFeatureFlags.publicBandsForLohs() && Environment.isSdkAtLeastB()) { 2935 mIsExclusive = (request.getCustomConfig() != null) 2936 && currentWsPriority >= WorkSourceHelper.PRIORITY_SYSTEM; 2937 } else { 2938 mIsExclusive = (request.getCustomConfig() != null); 2939 } 2940 final SoftApCapability lohsCapability = mLohsSoftApTracker.getSoftApCapability(); 2941 SoftApConfiguration softApConfig = mWifiApConfigStore.generateLocalOnlyHotspotConfig( 2942 mContext, request.getCustomConfig(), lohsCapability, mIsExclusive); 2943 2944 mActiveConfig = new SoftApModeConfiguration( 2945 WifiManager.IFACE_IP_MODE_LOCAL_ONLY, 2946 softApConfig, lohsCapability, mCountryCode.getCountryCode(), null); 2947 // Report the error if we got failure in startSoftApInternal 2948 if (!startSoftApInternal(mActiveConfig, request.getWorkSource(), null)) { 2949 onStateChanged(new SoftApState( 2950 WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL, 2951 mActiveConfig.getTetheringRequest(), null /* iface */)); 2952 } 2953 } 2954 2955 /** 2956 * Requests that any local-only hotspot be stopped. 2957 */ stopAll()2958 public void stopAll() { 2959 synchronized (mLocalOnlyHotspotRequests) { 2960 if (!mLocalOnlyHotspotRequests.isEmpty()) { 2961 // This is used to take down LOHS when tethering starts, and in that 2962 // case we send failed instead of stopped. 2963 // TODO check if that is right. Calling onFailed instead of onStopped when the 2964 // hotspot is already started does not seem to match the documentation 2965 sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked( 2966 LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE); 2967 stopIfEmptyLocked(); 2968 } 2969 } 2970 } 2971 2972 /** 2973 * Unregisters the LOHS request from the given process and stops LOHS if no other clients. 2974 */ stopByPid(int pid)2975 public void stopByPid(int pid) { 2976 synchronized (mLocalOnlyHotspotRequests) { 2977 LocalOnlyHotspotRequestInfo requestInfo = mLocalOnlyHotspotRequests.remove(pid); 2978 if (requestInfo == null) return; 2979 requestInfo.unlinkDeathRecipient(); 2980 stopIfEmptyLocked(); 2981 } 2982 } 2983 2984 /** 2985 * Unregisters LocalOnlyHotspot request and stops the hotspot if needed. 2986 */ stopByRequest(LocalOnlyHotspotRequestInfo request)2987 public void stopByRequest(LocalOnlyHotspotRequestInfo request) { 2988 synchronized (mLocalOnlyHotspotRequests) { 2989 if (mLocalOnlyHotspotRequests.remove(request.getPid()) == null) { 2990 mLog.trace("LocalOnlyHotspotRequestInfo not found to remove").flush(); 2991 return; 2992 } 2993 stopIfEmptyLocked(); 2994 } 2995 } 2996 2997 @GuardedBy("mLocalOnlyHotspotRequests") stopIfEmptyLocked()2998 private void stopIfEmptyLocked() { 2999 if (mLocalOnlyHotspotRequests.isEmpty()) { 3000 mActiveConfig = null; 3001 mIsExclusive = false; 3002 mCurrentWs = null; 3003 mLohsInterfaceName = null; 3004 mPidRestartingLohsFor = UNSPECIFIED_PID; 3005 mLohsInterfaceMode = WifiManager.IFACE_IP_MODE_UNSPECIFIED; 3006 stopSoftApInternal(WifiManager.IFACE_IP_MODE_LOCAL_ONLY); 3007 } 3008 } 3009 3010 /** 3011 * Helper method to send a HOTSPOT_STARTED message to all registered LocalOnlyHotspotRequest 3012 * callers. 3013 * 3014 * Callers should already hold the mLocalOnlyHotspotRequests lock. 3015 */ 3016 @GuardedBy("mLocalOnlyHotspotRequests") sendHotspotStartedMessageToAllLOHSRequestInfoEntriesLocked()3017 private void sendHotspotStartedMessageToAllLOHSRequestInfoEntriesLocked() { 3018 if (mActiveConfig == null) { 3019 Log.e(TAG, "lohs.sendHotspotStartedMessageToAllLOHSRequestInfoEntriesLocked " 3020 + "mActiveConfig is null"); 3021 return; 3022 } 3023 for (LocalOnlyHotspotRequestInfo requestor : mLocalOnlyHotspotRequests.values()) { 3024 try { 3025 requestor.sendHotspotStartedMessage(mActiveConfig.getSoftApConfiguration()); 3026 } catch (RemoteException e) { 3027 // This will be cleaned up by binder death handling 3028 } 3029 } 3030 } 3031 3032 @Override onStateChanged(SoftApState softApState)3033 public void onStateChanged(SoftApState softApState) { 3034 // The AP state update from ClientModeImpl for softap 3035 synchronized (mLocalOnlyHotspotRequests) { 3036 Log.d(TAG, "lohs.onStateChanged: " + softApState); 3037 int state = softApState.getState(); 3038 int failureReason = softApState.getFailureReasonInternal(); 3039 3040 // check if we have a failure - since it is possible (worst case scenario where 3041 // WifiController and ClientModeImpl are out of sync wrt modes) to get two FAILED 3042 // notifications in a row, we need to handle this first. 3043 if (state == WIFI_AP_STATE_FAILED) { 3044 // update registered LOHS callbacks if we see a failure 3045 int errorToReport = ERROR_GENERIC; 3046 if (failureReason == SAP_START_FAILURE_NO_CHANNEL) { 3047 errorToReport = ERROR_NO_CHANNEL; 3048 } 3049 // holding the required lock: send message to requestors and clear the list 3050 sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked(errorToReport); 3051 // also need to clear interface ip state 3052 updateInterfaceIpState(mLohsInterfaceName, 3053 WifiManager.IFACE_IP_MODE_UNSPECIFIED); 3054 // failed, reset restarting pid info 3055 mPidRestartingLohsFor = UNSPECIFIED_PID; 3056 } else if (state == WIFI_AP_STATE_DISABLING || state == WIFI_AP_STATE_DISABLED) { 3057 // softap is shutting down or is down... let requestors know via the 3058 // onStopped call 3059 // if we are currently in hotspot mode, then trigger onStopped for registered 3060 // requestors, otherwise something odd happened and we should clear state 3061 if (mLohsInterfaceName != null 3062 && mLohsInterfaceMode == WifiManager.IFACE_IP_MODE_LOCAL_ONLY) { 3063 // holding the required lock: send message to requestors and clear the list 3064 sendHotspotStoppedMessageToAllLOHSRequestInfoEntriesLocked(); 3065 } else { 3066 // The LOHS is being restarted since there is a mPidRestartingLohsFor, 3067 // We should expect there will be DISABLING and DISABLED. 3068 // No need to report error. 3069 if (mPidRestartingLohsFor == UNSPECIFIED_PID) { 3070 // LOHS not active: report an error. 3071 sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked( 3072 ERROR_GENERIC); 3073 } 3074 } 3075 // also clear interface ip state 3076 updateInterfaceIpState(mLohsInterfaceName, 3077 WifiManager.IFACE_IP_MODE_UNSPECIFIED); 3078 } else if (state == WIFI_AP_STATE_ENABLING 3079 && mPidRestartingLohsFor != UNSPECIFIED_PID) { 3080 // restarting, reset pid info 3081 mPidRestartingLohsFor = UNSPECIFIED_PID; 3082 } 3083 // For enabling and enabled, just record the new state 3084 setState(softApState); 3085 notifyRegisterOnStateChanged(mRegisteredSoftApCallbacks, softApState); 3086 } 3087 } 3088 } 3089 3090 /** 3091 * see {@link android.net.wifi.WifiManager#registerSoftApCallback(Executor, 3092 * WifiManager.SoftApCallback)} 3093 * 3094 * @param callback Soft AP callback to register 3095 * 3096 * @throws SecurityException if the caller does not have permission to register a callback 3097 * @throws RemoteException if remote exception happens 3098 * @throws IllegalArgumentException if the arguments are null or invalid 3099 */ 3100 @Override registerSoftApCallback(ISoftApCallback callback)3101 public void registerSoftApCallback(ISoftApCallback callback) { 3102 // verify arguments 3103 if (callback == null) { 3104 throw new IllegalArgumentException("Callback must not be null"); 3105 } 3106 3107 int uid = Binder.getCallingUid(); 3108 int pid = Binder.getCallingPid(); 3109 if (!mWifiPermissionsUtil.checkConfigOverridePermission(uid) 3110 && !checkNetworkSettingsPermission(pid, uid) 3111 && !checkMainlineNetworkStackPermission(pid, uid)) { 3112 // random apps should not be allowed to read the user specified config 3113 throw new SecurityException("App not allowed to read WiFi Ap information " 3114 + "(uid/pid = " + uid + "/" + pid + ")"); 3115 } 3116 3117 if (mVerboseLoggingEnabled) { 3118 mLog.info("registerSoftApCallback uid=%").c(Binder.getCallingUid()).flush(); 3119 } 3120 3121 // post operation to handler thread 3122 mWifiThreadRunner.post(() -> { 3123 if (!mTetheredSoftApTracker.registerSoftApCallback(callback, null)) { 3124 Log.e(TAG, "registerSoftApCallback: Failed to add callback"); 3125 return; 3126 } 3127 }, TAG + "#registerSoftApCallback"); 3128 } 3129 3130 /** 3131 * see {@link android.net.wifi.WifiManager#unregisterSoftApCallback(WifiManager.SoftApCallback)} 3132 * 3133 * @param callback Soft AP callback to unregister 3134 * 3135 * @throws SecurityException if the caller does not have permission to register a callback 3136 */ 3137 @Override unregisterSoftApCallback(ISoftApCallback callback)3138 public void unregisterSoftApCallback(ISoftApCallback callback) { 3139 int uid = Binder.getCallingUid(); 3140 int pid = Binder.getCallingPid(); 3141 if (!mWifiPermissionsUtil.checkConfigOverridePermission(uid) 3142 && !checkNetworkSettingsPermission(pid, uid) 3143 && !checkMainlineNetworkStackPermission(pid, uid)) { 3144 // random apps should not be allowed to read the user specified config 3145 throw new SecurityException("App not allowed to read WiFi Ap information " 3146 + "(uid/pid = " + uid + "/" + pid + ")"); 3147 } 3148 3149 if (mVerboseLoggingEnabled) { 3150 mLog.info("unregisterSoftApCallback uid=%").c(Binder.getCallingUid()).flush(); 3151 } 3152 3153 // post operation to handler thread 3154 mWifiThreadRunner.post(() -> 3155 mTetheredSoftApTracker.unregisterSoftApCallback(callback), 3156 TAG + "#unregisterSoftApCallback"); 3157 } 3158 3159 /** 3160 * Temporary method used for testing while start is not fully implemented. This 3161 * method allows unit tests to register callbacks directly for testing mechanisms triggered by 3162 * softap mode changes. 3163 */ 3164 @VisibleForTesting registerLOHSForTest(int pid, LocalOnlyHotspotRequestInfo request)3165 int registerLOHSForTest(int pid, LocalOnlyHotspotRequestInfo request) { 3166 return mLohsSoftApTracker.start(pid, request); 3167 } 3168 3169 /** 3170 * Method to start LocalOnlyHotspot. In this method, permissions, settings and modes are 3171 * checked to verify that we can enter softapmode. This method returns 3172 * {@link LocalOnlyHotspotCallback#REQUEST_REGISTERED} if we will attempt to start, otherwise, 3173 * possible startup erros may include tethering being disallowed failure reason {@link 3174 * LocalOnlyHotspotCallback#ERROR_TETHERING_DISALLOWED} or an incompatible mode failure reason 3175 * {@link LocalOnlyHotspotCallback#ERROR_INCOMPATIBLE_MODE}. 3176 * 3177 * see {@link WifiManager#startLocalOnlyHotspot(LocalOnlyHotspotCallback)} 3178 * 3179 * @param callback Callback to communicate with WifiManager and allow cleanup if the app dies. 3180 * @param packageName String name of the calling package. 3181 * @param featureId The feature in the package 3182 * @param customConfig Custom configuration to be applied to the hotspot, or null for a shared 3183 * hotspot with framework-generated config. 3184 * @param extras Bundle of extra information 3185 * 3186 * @return int return code for attempt to start LocalOnlyHotspot. 3187 * 3188 * @throws SecurityException if the caller does not have permission to start a Local Only 3189 * Hotspot. 3190 * @throws IllegalStateException if the caller attempts to start the LocalOnlyHotspot while they 3191 * have an outstanding request. 3192 */ 3193 @Override startLocalOnlyHotspot(ILocalOnlyHotspotCallback callback, String packageName, String featureId, SoftApConfiguration customConfig, Bundle extras, boolean isCalledFromSystemApi)3194 public int startLocalOnlyHotspot(ILocalOnlyHotspotCallback callback, String packageName, 3195 String featureId, SoftApConfiguration customConfig, Bundle extras, 3196 boolean isCalledFromSystemApi) { 3197 // first check if the caller has permission to start a local only hotspot 3198 // need to check for WIFI_STATE_CHANGE and location permission 3199 final int uid = Binder.getCallingUid(); 3200 final int pid = Binder.getCallingPid(); 3201 mWifiPermissionsUtil.checkPackage(uid, packageName); 3202 3203 mLog.info("start lohs uid=% pid=%").c(uid).c(pid).flush(); 3204 3205 // Permission requirements are different with/without custom config. 3206 // From B, the custom config may from public API, check isCalledFromSystemApi 3207 if (customConfig == null 3208 || (Environment.isSdkAtLeastB() && !isCalledFromSystemApi)) { 3209 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 3210 return LocalOnlyHotspotCallback.ERROR_GENERIC; 3211 } 3212 if (isPlatformOrTargetSdkLessThanT(packageName, uid)) { 3213 enforceLocationPermission(packageName, featureId, uid); 3214 long ident = Binder.clearCallingIdentity(); 3215 try { 3216 // also need to verify that Locations services are enabled. 3217 if (!mWifiPermissionsUtil.isLocationModeEnabled()) { 3218 throw new SecurityException("Location mode is not enabled."); 3219 } 3220 3221 } finally { 3222 Binder.restoreCallingIdentity(ident); 3223 } 3224 } else { 3225 mWifiPermissionsUtil.enforceNearbyDevicesPermission( 3226 extras.getParcelable(WifiManager.EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE), 3227 false, TAG + " startLocalOnlyHotspot"); 3228 } 3229 } else { 3230 if (isPlatformOrTargetSdkLessThanT(packageName, uid)) { 3231 if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { 3232 throw new SecurityException(TAG + ": Permission denied"); 3233 } 3234 } else { 3235 mWifiPermissionsUtil.enforceNearbyDevicesPermission( 3236 extras.getParcelable(WifiManager.EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE), 3237 false, TAG + " startLocalOnlyHotspot"); 3238 } 3239 } 3240 3241 final WorkSource requestorWs = new WorkSource(uid, packageName); 3242 // the app should be in the foreground 3243 long ident = Binder.clearCallingIdentity(); 3244 try { 3245 // verify that tethering is not disabled 3246 if (mUserManager.hasUserRestrictionForUser( 3247 UserManager.DISALLOW_CONFIG_TETHERING, UserHandle.getUserHandleForUid(uid))) { 3248 return LocalOnlyHotspotCallback.ERROR_TETHERING_DISALLOWED; 3249 } 3250 3251 mLastCallerInfoManager.put(WifiManager.API_START_LOCAL_ONLY_HOTSPOT, Process.myTid(), 3252 uid, Binder.getCallingPid(), packageName, true); 3253 // also need to verify that Locations services are enabled. 3254 // bypass shell with root uid 3255 if (uid != Process.ROOT_UID 3256 && !mFrameworkFacade.isAppForeground(mContext, uid)) { 3257 return LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE; 3258 } 3259 // check if we are currently tethering 3260 if (!mActiveModeWarden.canRequestMoreSoftApManagers(requestorWs) 3261 && mTetheredSoftApTracker.getState().getState() == WIFI_AP_STATE_ENABLED) { 3262 // Tethering is enabled, cannot start LocalOnlyHotspot 3263 mLog.info("Cannot start localOnlyHotspot when WiFi Tethering is active.") 3264 .flush(); 3265 return LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE; 3266 } 3267 } finally { 3268 Binder.restoreCallingIdentity(ident); 3269 } 3270 3271 // now create the new LOHS request info object 3272 LocalOnlyHotspotRequestInfo request = new LocalOnlyHotspotRequestInfo( 3273 mWifiHandlerThread.getLooper(), requestorWs, callback, 3274 new LocalOnlyRequestorCallback(), customConfig); 3275 3276 return mLohsSoftApTracker.start(pid, request); 3277 } 3278 3279 /** 3280 * see {@link WifiManager#stopLocalOnlyHotspot()} 3281 * 3282 * @throws SecurityException if the caller does not have permission to stop a Local Only 3283 * Hotspot. 3284 */ 3285 @Override stopLocalOnlyHotspot()3286 public void stopLocalOnlyHotspot() { 3287 // don't do a permission check here. if the app's permission to change the wifi state is 3288 // revoked, we still want them to be able to stop a previously created hotspot (otherwise 3289 // it could cost the user money). When the app created the hotspot, its permission was 3290 // checked. 3291 final int uid = Binder.getCallingUid(); 3292 final int pid = Binder.getCallingPid(); 3293 3294 mLog.info("stopLocalOnlyHotspot uid=% pid=%").c(uid).c(pid).flush(); 3295 // Force to disable lohs when caller is shell with root permission 3296 if (uid == Process.ROOT_UID) { 3297 mLohsSoftApTracker.stopAll(); 3298 } else { 3299 mLohsSoftApTracker.stopByPid(pid); 3300 } 3301 } 3302 3303 @Override registerLocalOnlyHotspotSoftApCallback(ISoftApCallback callback, Bundle extras)3304 public void registerLocalOnlyHotspotSoftApCallback(ISoftApCallback callback, Bundle extras) { 3305 if (!SdkLevel.isAtLeastT()) { 3306 throw new UnsupportedOperationException(); 3307 } 3308 3309 // verify arguments 3310 if (callback == null) { 3311 throw new IllegalArgumentException("Callback must not be null"); 3312 } 3313 3314 AttributionSource attributionSource = 3315 extras.getParcelable(WifiManager.EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE); 3316 mWifiPermissionsUtil.enforceNearbyDevicesPermission(attributionSource, 3317 false, TAG + " registerLocalOnlyHotspotSoftApCallback"); 3318 3319 if (mVerboseLoggingEnabled) { 3320 mLog.info("registerLocalOnlyHotspotSoftApCallback uid=%") 3321 .c(Binder.getCallingUid()).flush(); 3322 } 3323 3324 // post operation to handler thread 3325 mWifiThreadRunner.post(() -> { 3326 if (!mLohsSoftApTracker.registerSoftApCallback(callback, attributionSource)) { 3327 Log.e(TAG, "registerLocalOnlyHotspotSoftApCallback: Failed to add callback"); 3328 } 3329 }, TAG + "#registerLocalOnlyHotspotSoftApCallback"); 3330 } 3331 3332 @Override unregisterLocalOnlyHotspotSoftApCallback(ISoftApCallback callback, Bundle extras)3333 public void unregisterLocalOnlyHotspotSoftApCallback(ISoftApCallback callback, Bundle extras) { 3334 // verify arguments 3335 if (callback == null) { 3336 throw new IllegalArgumentException("Callback must not be null"); 3337 } 3338 3339 mWifiPermissionsUtil.enforceNearbyDevicesPermission( 3340 extras.getParcelable(WifiManager.EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE), 3341 false, TAG + " registerLocalOnlyHotspotSoftApCallback"); 3342 3343 if (mVerboseLoggingEnabled) { 3344 mLog.info("unregisterLocalOnlyHotspotSoftApCallback uid=%") 3345 .c(Binder.getCallingUid()).flush(); 3346 } 3347 3348 // post operation to handler thread 3349 mWifiThreadRunner.post(() -> 3350 mLohsSoftApTracker.unregisterSoftApCallback(callback), 3351 TAG + "#unregisterLocalOnlyHotspotSoftApCallback"); 3352 } 3353 3354 /** 3355 * see {@link WifiManager#watchLocalOnlyHotspot(LocalOnlyHotspotObserver)} 3356 * 3357 * This call requires the android.permission.NETWORK_SETTINGS permission. 3358 * 3359 * @param callback Callback to communicate with WifiManager and allow cleanup if the app dies. 3360 * 3361 * @throws SecurityException if the caller does not have permission to watch Local Only Hotspot 3362 * status updates. 3363 * @throws IllegalStateException if the caller attempts to watch LocalOnlyHotspot updates with 3364 * an existing subscription. 3365 */ 3366 @Override startWatchLocalOnlyHotspot(ILocalOnlyHotspotCallback callback)3367 public void startWatchLocalOnlyHotspot(ILocalOnlyHotspotCallback callback) { 3368 // NETWORK_SETTINGS is a signature only permission. 3369 enforceNetworkSettingsPermission(); 3370 3371 throw new UnsupportedOperationException("LocalOnlyHotspot is still in development"); 3372 } 3373 3374 /** 3375 * see {@link WifiManager#unregisterLocalOnlyHotspotObserver()} 3376 */ 3377 @Override stopWatchLocalOnlyHotspot()3378 public void stopWatchLocalOnlyHotspot() { 3379 // NETWORK_STACK is a signature only permission. 3380 enforceNetworkSettingsPermission(); 3381 throw new UnsupportedOperationException("LocalOnlyHotspot is still in development"); 3382 } 3383 3384 /** 3385 * see {@link WifiManager#getWifiApConfiguration()} 3386 * @return soft access point configuration 3387 * @throws SecurityException if the caller does not have permission to retrieve the softap 3388 * config 3389 */ 3390 @Nullable 3391 @Override getWifiApConfiguration()3392 public WifiConfiguration getWifiApConfiguration() { 3393 enforceAccessPermission(); 3394 int uid = Binder.getCallingUid(); 3395 // only allow Settings UI to get the saved SoftApConfig 3396 if (!mWifiPermissionsUtil.checkConfigOverridePermission(uid)) { 3397 // random apps should not be allowed to read the user specified config 3398 throw new SecurityException("App not allowed to read or update stored WiFi Ap config " 3399 + "(uid = " + uid + ")"); 3400 } 3401 3402 if (mVerboseLoggingEnabled) { 3403 mLog.info("getWifiApConfiguration uid=%").c(uid).flush(); 3404 } 3405 3406 final SoftApConfiguration config = mWifiApConfigStore.getApConfiguration(); 3407 return config == null ? new SoftApConfiguration.Builder().build().toWifiConfiguration() 3408 : config.toWifiConfiguration(); 3409 } 3410 3411 /** 3412 * see {@link WifiManager#getSoftApConfiguration()} 3413 * @return soft access point configuration {@link SoftApConfiguration} 3414 * @throws SecurityException if the caller does not have permission to retrieve the softap 3415 * config 3416 */ 3417 @NonNull 3418 @Override getSoftApConfiguration()3419 public SoftApConfiguration getSoftApConfiguration() { 3420 int uid = Binder.getCallingUid(); 3421 if (!mWifiPermissionsUtil.checkConfigOverridePermission(uid) 3422 && !mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { 3423 // random apps should not be allowed to read the user specified config 3424 throw new SecurityException("App not allowed to read or update stored WiFi Ap config " 3425 + "(uid = " + uid + ")"); 3426 } 3427 if (mVerboseLoggingEnabled) { 3428 mLog.info("getSoftApConfiguration uid=%").c(uid).flush(); 3429 } 3430 3431 final SoftApConfiguration config = mWifiApConfigStore.getApConfiguration(); 3432 return config == null ? new SoftApConfiguration.Builder().build() : config; 3433 } 3434 3435 /** 3436 * See {@code WifiManager#queryLastConfiguredTetheredApPassphraseSinceBoot(Executor, Consumer)} 3437 */ 3438 @Override queryLastConfiguredTetheredApPassphraseSinceBoot(IStringListener listener)3439 public void queryLastConfiguredTetheredApPassphraseSinceBoot(IStringListener listener) { 3440 if (listener == null) { 3441 throw new IllegalArgumentException("listener should not be null"); 3442 } 3443 int uid = Binder.getCallingUid(); 3444 if (!mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { 3445 throw new SecurityException("App not allowed to read last WiFi AP passphrase " 3446 + "(uid = " + uid + ")"); 3447 } 3448 mWifiThreadRunner.post(() -> { 3449 try { 3450 listener.onResult(mWifiApConfigStore 3451 .getLastConfiguredTetheredApPassphraseSinceBoot()); 3452 } catch (RemoteException e) { 3453 Log.e(TAG, e.getMessage(), e); 3454 } 3455 }, TAG + "#queryLastConfiguredTetheredApPassphraseSinceBoot"); 3456 } 3457 3458 /** 3459 * see {@link WifiManager#setWifiApConfiguration(WifiConfiguration)} 3460 * @param wifiConfig WifiConfiguration details for soft access point 3461 * @return boolean indicating success or failure of the operation 3462 * @throws SecurityException if the caller does not have permission to write the softap config 3463 */ 3464 @Override setWifiApConfiguration(WifiConfiguration wifiConfig, String packageName)3465 public boolean setWifiApConfiguration(WifiConfiguration wifiConfig, String packageName) { 3466 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 3467 return false; 3468 } 3469 int uid = Binder.getCallingUid(); 3470 mWifiPermissionsUtil.checkPackage(uid, packageName); 3471 // only allow Settings UI to write the stored SoftApConfig 3472 if (!mWifiPermissionsUtil.checkConfigOverridePermission(uid)) { 3473 // random apps should not be allowed to read the user specified config 3474 throw new SecurityException("App not allowed to read or update stored WiFi AP config " 3475 + "(uid = " + uid + ")"); 3476 } 3477 mLog.info("setWifiApConfiguration uid=%").c(uid).flush(); 3478 if (wifiConfig == null) 3479 return false; 3480 SoftApConfiguration softApConfig = ApConfigUtil.fromWifiConfiguration(wifiConfig); 3481 if (softApConfig == null) return false; 3482 if (!WifiApConfigStore.validateApWifiConfiguration( 3483 softApConfig, false, mContext, mWifiNative)) { 3484 Log.e(TAG, "Invalid WifiConfiguration"); 3485 return false; 3486 } 3487 mWifiApConfigStore.setApConfiguration(softApConfig); 3488 return true; 3489 } 3490 3491 /** 3492 * see {@link WifiManager#setSoftApConfiguration(SoftApConfiguration)} 3493 * @param softApConfig {@link SoftApConfiguration} details for soft access point 3494 * @return boolean indicating success or failure of the operation 3495 * @throws SecurityException if the caller does not have permission to write the softap config 3496 */ 3497 @Override setSoftApConfiguration( @onNull SoftApConfiguration softApConfig, @NonNull String packageName)3498 public boolean setSoftApConfiguration( 3499 @NonNull SoftApConfiguration softApConfig, @NonNull String packageName) { 3500 int uid = Binder.getCallingUid(); 3501 mWifiPermissionsUtil.checkPackage(uid, packageName); 3502 boolean privileged = mWifiPermissionsUtil.checkNetworkSettingsPermission(uid); 3503 if (!mWifiPermissionsUtil.checkConfigOverridePermission(uid) 3504 && !privileged) { 3505 // random apps should not be allowed to read the user specified config 3506 throw new SecurityException("App not allowed to read or update stored WiFi Ap config " 3507 + "(uid = " + uid + ")"); 3508 } 3509 mLog.info("setSoftApConfiguration uid=%").c(uid).flush(); 3510 if (softApConfig == null) return false; 3511 if (WifiApConfigStore.validateApWifiConfiguration(softApConfig, privileged, mContext, 3512 mWifiNative)) { 3513 mWifiApConfigStore.setApConfiguration(softApConfig); 3514 // Send the message for AP config update after the save is done. 3515 mActiveModeWarden.updateSoftApConfiguration(softApConfig); 3516 return true; 3517 } else { 3518 Log.e(TAG, "Invalid SoftAp Configuration"); 3519 return false; 3520 } 3521 } 3522 3523 /** 3524 * see {@link android.net.wifi.WifiManager#setScanAlwaysAvailable(boolean)} 3525 */ 3526 @Override setScanAlwaysAvailable(boolean isAvailable, String packageName)3527 public void setScanAlwaysAvailable(boolean isAvailable, String packageName) { 3528 enforceNetworkSettingsPermission(); 3529 int callingUid = Binder.getCallingUid(); 3530 mWifiPermissionsUtil.checkPackage(callingUid, packageName); 3531 mLog.info("setScanAlwaysAvailable uid=% package=% isAvailable=%") 3532 .c(callingUid) 3533 .c(packageName) 3534 .c(isAvailable) 3535 .flush(); 3536 mSettingsStore.handleWifiScanAlwaysAvailableToggled(isAvailable); 3537 long ident = Binder.clearCallingIdentity(); 3538 try { 3539 mWifiInjector.getWifiScanAlwaysAvailableSettingsCompatibility() 3540 .handleWifiScanAlwaysAvailableToggled(isAvailable); 3541 } finally { 3542 Binder.restoreCallingIdentity(ident); 3543 } 3544 mActiveModeWarden.scanAlwaysModeChanged(); 3545 } 3546 3547 /** 3548 * see {@link android.net.wifi.WifiManager#isScanAlwaysAvailable()} 3549 */ 3550 @Override isScanAlwaysAvailable()3551 public boolean isScanAlwaysAvailable() { 3552 enforceAccessPermission(); 3553 if (mVerboseLoggingEnabled) { 3554 mLog.info("isScanAlwaysAvailable uid=%").c(Binder.getCallingUid()).flush(); 3555 } 3556 return mSettingsStore.isScanAlwaysAvailableToggleEnabled(); 3557 } 3558 3559 /** 3560 * see {@link android.net.wifi.WifiManager#disconnect()} 3561 */ 3562 @Override disconnect(String packageName)3563 public boolean disconnect(String packageName) { 3564 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 3565 return false; 3566 } 3567 int callingUid = Binder.getCallingUid(); 3568 mWifiPermissionsUtil.checkPackage(callingUid, packageName); 3569 if (!isTargetSdkLessThanQOrPrivileged( 3570 packageName, Binder.getCallingPid(), callingUid)) { 3571 mLog.info("disconnect not allowed for uid=%").c(callingUid).flush(); 3572 return false; 3573 } 3574 mLog.info("disconnect uid=%").c(callingUid).flush(); 3575 mWifiThreadRunner.post(() -> mActiveModeWarden.getPrimaryClientModeManager().disconnect(), 3576 TAG + "#disconnect"); 3577 return true; 3578 } 3579 3580 /** 3581 * see {@link android.net.wifi.WifiManager#reconnect()} 3582 */ 3583 @Override reconnect(String packageName)3584 public boolean reconnect(String packageName) { 3585 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 3586 return false; 3587 } 3588 int callingUid = Binder.getCallingUid(); 3589 mWifiPermissionsUtil.checkPackage(callingUid, packageName); 3590 if (!isTargetSdkLessThanQOrPrivileged(packageName, Binder.getCallingPid(), callingUid)) { 3591 mLog.info("reconnect not allowed for uid=%").c(callingUid).flush(); 3592 return false; 3593 } 3594 mLog.info("reconnect uid=%").c(callingUid).flush(); 3595 3596 mWifiThreadRunner.post(() -> { 3597 mActiveModeWarden.getPrimaryClientModeManager().reconnect(new WorkSource(callingUid)); 3598 }, TAG + "#reconnect"); 3599 return true; 3600 } 3601 3602 /** 3603 * see {@link android.net.wifi.WifiManager#reassociate()} 3604 */ 3605 @Override reassociate(String packageName)3606 public boolean reassociate(String packageName) { 3607 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 3608 return false; 3609 } 3610 int callingUid = Binder.getCallingUid(); 3611 mWifiPermissionsUtil.checkPackage(callingUid, packageName); 3612 if (!isTargetSdkLessThanQOrPrivileged( 3613 packageName, Binder.getCallingPid(), callingUid)) { 3614 mLog.info("reassociate not allowed for uid=%").c(callingUid).flush(); 3615 return false; 3616 } 3617 mLog.info("reassociate uid=%").c(callingUid).flush(); 3618 mWifiThreadRunner.post(() -> mActiveModeWarden.getPrimaryClientModeManager().reassociate(), 3619 TAG + "#reassociate"); 3620 return true; 3621 } 3622 3623 /** 3624 * Returns true if we should log the call to isFeatureSupported. 3625 * 3626 * Because of the way isFeatureSupported is used in WifiManager, there are 3627 * often clusters of several back-to-back calls; avoid repeated logging if 3628 * the feature set has not changed and the time interval is short. 3629 */ needToLogSupportedFeatures(BitSet features)3630 private boolean needToLogSupportedFeatures(BitSet features) { 3631 if (mVerboseLoggingEnabled) { 3632 long now = mClock.getElapsedSinceBootMillis(); 3633 synchronized (this) { 3634 if (now > mLastLoggedSupportedFeaturesTimestamp + A_FEW_MILLISECONDS 3635 || !features.equals(mLastLoggedSupportedFeatures)) { 3636 mLastLoggedSupportedFeaturesTimestamp = now; 3637 mLastLoggedSupportedFeatures = features; 3638 return true; 3639 } 3640 } 3641 } 3642 return false; 3643 } 3644 private static final int A_FEW_MILLISECONDS = 250; 3645 private BitSet mLastLoggedSupportedFeatures = new BitSet(); 3646 private long mLastLoggedSupportedFeaturesTimestamp = 0; 3647 3648 @Override isFeatureSupported(int feature)3649 public boolean isFeatureSupported(int feature) { 3650 enforceAccessPermission(); 3651 BitSet supportedFeatures = getSupportedFeaturesInternal(); 3652 if (needToLogSupportedFeatures(supportedFeatures)) { 3653 mLog.info("isFeatureSupported uid=% returns %") 3654 .c(Binder.getCallingUid()) 3655 .c(FeatureBitsetUtils.formatSupportedFeatures(supportedFeatures)) 3656 .flush(); 3657 } 3658 return supportedFeatures.get(feature); 3659 } 3660 3661 @Override getWifiActivityEnergyInfoAsync(@onNull IOnWifiActivityEnergyInfoListener listener)3662 public void getWifiActivityEnergyInfoAsync(@NonNull IOnWifiActivityEnergyInfoListener 3663 listener) { 3664 if (listener == null) { 3665 throw new IllegalArgumentException("listener should not be null"); 3666 } 3667 enforceAccessPermission(); 3668 if (mVerboseLoggingEnabled) { 3669 mLog.info("getWifiActivityEnergyInfoAsync uid=%") 3670 .c(Binder.getCallingUid()) 3671 .flush(); 3672 } 3673 if (!isFeatureSupported(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)) { 3674 try { 3675 listener.onWifiActivityEnergyInfo(null); 3676 } catch (RemoteException e) { 3677 Log.e(TAG, "onWifiActivityEnergyInfo: RemoteException -- ", e); 3678 } 3679 return; 3680 } 3681 mWifiThreadRunner.post(() -> { 3682 try { 3683 listener.onWifiActivityEnergyInfo(getWifiActivityEnergyInfo()); 3684 } catch (RemoteException e) { 3685 Log.e(TAG, "onWifiActivityEnergyInfo: RemoteException -- ", e); 3686 } 3687 }, TAG + "#getWifiActivityEnergyInfoAsync"); 3688 } 3689 getWifiActivityEnergyInfo()3690 private WifiActivityEnergyInfo getWifiActivityEnergyInfo() { 3691 WifiLinkLayerStats stats = mActiveModeWarden 3692 .getPrimaryClientModeManager().getWifiLinkLayerStats(); 3693 if (stats == null) { 3694 return null; 3695 } 3696 final long rxIdleTimeMillis = stats.on_time - stats.tx_time - stats.rx_time; 3697 if (VDBG || rxIdleTimeMillis < 0 || stats.on_time < 0 || stats.tx_time < 0 3698 || stats.rx_time < 0 || stats.on_time_scan < 0) { 3699 Log.d(TAG, " getWifiActivityEnergyInfo: " 3700 + " on_time_millis=" + stats.on_time 3701 + " tx_time_millis=" + stats.tx_time 3702 + " rx_time_millis=" + stats.rx_time 3703 + " rxIdleTimeMillis=" + rxIdleTimeMillis 3704 + " scan_time_millis=" + stats.on_time_scan); 3705 } 3706 // Convert the LinkLayerStats into WifiActivityEnergyInfo 3707 return new WifiActivityEnergyInfo( 3708 mClock.getElapsedSinceBootMillis(), 3709 WifiActivityEnergyInfo.STACK_STATE_STATE_IDLE, 3710 stats.tx_time, 3711 stats.rx_time, 3712 stats.on_time_scan, 3713 rxIdleTimeMillis); 3714 } 3715 3716 /** 3717 * see {@link android.net.wifi.WifiManager#getConfiguredNetworks()} 3718 * 3719 * @param packageName String name of the calling package 3720 * @param featureId The feature in the package 3721 * @param callerNetworksOnly Whether to only return networks created by the caller 3722 * @return the list of configured networks 3723 */ 3724 @Override getConfiguredNetworks(String packageName, String featureId, boolean callerNetworksOnly)3725 public ParceledListSlice<WifiConfiguration> getConfiguredNetworks(String packageName, 3726 String featureId, boolean callerNetworksOnly) { 3727 enforceAccessPermission(); 3728 int callingUid = Binder.getCallingUid(); 3729 // bypass shell: can get various pkg name 3730 // also bypass if caller is only retrieving networks added by itself 3731 if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID) { 3732 mWifiPermissionsUtil.checkPackage(callingUid, packageName); 3733 if (!callerNetworksOnly) { 3734 long ident = Binder.clearCallingIdentity(); 3735 try { 3736 mWifiPermissionsUtil.enforceCanAccessScanResults(packageName, featureId, 3737 callingUid, null); 3738 } catch (SecurityException e) { 3739 Log.w(TAG, "Permission violation - getConfiguredNetworks not allowed for uid=" 3740 + callingUid + ", packageName=" + packageName + ", reason=" + e); 3741 return new ParceledListSlice<>(new ArrayList<>()); 3742 } finally { 3743 Binder.restoreCallingIdentity(ident); 3744 } 3745 } 3746 } 3747 boolean isDeviceOrProfileOwner = isDeviceOrProfileOwner(callingUid, packageName); 3748 boolean isCarrierApp = mWifiInjector.makeTelephonyManager() 3749 .checkCarrierPrivilegesForPackageAnyPhone(packageName) 3750 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; 3751 boolean isPrivileged = isPrivileged(getCallingPid(), callingUid); 3752 // Only DO, PO, carrier app or system app can use callerNetworksOnly argument 3753 if (callerNetworksOnly) { 3754 if (!isDeviceOrProfileOwner && !isCarrierApp && !isPrivileged) { 3755 throw new SecurityException( 3756 "Not a DO, PO, carrier or privileged app"); 3757 } 3758 } 3759 boolean isTargetSdkLessThanQOrPrivileged = isTargetSdkLessThanQOrPrivileged( 3760 packageName, Binder.getCallingPid(), callingUid); 3761 if (!isTargetSdkLessThanQOrPrivileged && !isCarrierApp) { 3762 mLog.info("getConfiguredNetworks not allowed for uid=%") 3763 .c(callingUid).flush(); 3764 return new ParceledListSlice<>(new ArrayList<>()); 3765 } 3766 if (mVerboseLoggingEnabled) { 3767 mLog.info("getConfiguredNetworks uid=%").c(callingUid).flush(); 3768 } 3769 3770 int targetConfigUid = Process.INVALID_UID; // don't expose any MAC addresses 3771 if (isPrivileged) { 3772 targetConfigUid = WIFI_UID; // expose all MAC addresses 3773 } else if (isCarrierApp || isDeviceOrProfileOwner) { 3774 targetConfigUid = callingUid; // expose only those configs created by the calling App 3775 } 3776 int finalTargetConfigUid = targetConfigUid; 3777 List<WifiConfiguration> configs = mWifiThreadRunner.call( 3778 () -> mWifiConfigManager.getSavedNetworks(finalTargetConfigUid), 3779 Collections.emptyList(), TAG + "#getConfiguredNetworks"); 3780 if (isTargetSdkLessThanQOrPrivileged && !callerNetworksOnly) { 3781 return new ParceledListSlice<>( 3782 WifiConfigurationUtil.convertMultiTypeConfigsToLegacyConfigs(configs, false)); 3783 } 3784 // Should only get its own configs 3785 List<WifiConfiguration> creatorConfigs = new ArrayList<>(); 3786 for (WifiConfiguration config : configs) { 3787 if (config.creatorUid == callingUid) { 3788 creatorConfigs.add(config); 3789 } 3790 } 3791 return new ParceledListSlice<>( 3792 WifiConfigurationUtil.convertMultiTypeConfigsToLegacyConfigs( 3793 creatorConfigs, true)); 3794 } 3795 3796 /** 3797 * see {@link android.net.wifi.WifiManager#getPrivilegedConfiguredNetworks()} 3798 * 3799 * @param packageName String name of the calling package 3800 * @param featureId The feature in the package 3801 * @param extras - Bundle of extra information 3802 * @return the list of configured networks with real preSharedKey 3803 */ 3804 @Override getPrivilegedConfiguredNetworks( String packageName, String featureId, Bundle extras)3805 public ParceledListSlice<WifiConfiguration> getPrivilegedConfiguredNetworks( 3806 String packageName, String featureId, Bundle extras) { 3807 enforceReadCredentialPermission(); 3808 enforceAccessPermission(); 3809 int callingUid = Binder.getCallingUid(); 3810 mWifiPermissionsUtil.checkPackage(callingUid, packageName); 3811 if (isPlatformOrTargetSdkLessThanT(packageName, callingUid)) { 3812 // For backward compatibility, do not check for nearby devices permission on pre-T 3813 // SDK version or if the app targets pre-T. 3814 long ident = Binder.clearCallingIdentity(); 3815 try { 3816 mWifiPermissionsUtil.enforceCanAccessScanResults(packageName, featureId, callingUid, 3817 null); 3818 } catch (SecurityException e) { 3819 Log.w(TAG, "Permission violation - getPrivilegedConfiguredNetworks not allowed" 3820 + " for uid=" + callingUid + ", packageName=" + packageName + ", reason=" 3821 + e); 3822 return null; 3823 } finally { 3824 Binder.restoreCallingIdentity(ident); 3825 } 3826 } else { 3827 try { 3828 mWifiPermissionsUtil.enforceNearbyDevicesPermission( 3829 extras.getParcelable(WifiManager.EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE), 3830 false, TAG + " getPrivilegedConfiguredNetworks"); 3831 } catch (SecurityException e) { 3832 Log.w(TAG, "Permission violation - getPrivilegedConfiguredNetworks not allowed" 3833 + " for uid=" + callingUid + ", packageName=" + packageName + ", reason=" 3834 + e); 3835 return null; 3836 } 3837 } 3838 if (mVerboseLoggingEnabled) { 3839 mLog.info("getPrivilegedConfiguredNetworks uid=%").c(callingUid).flush(); 3840 } 3841 List<WifiConfiguration> configs = mWifiThreadRunner.call( 3842 () -> mWifiConfigManager.getConfiguredNetworksWithPasswords(), 3843 Collections.emptyList(), TAG + "#getPrivilegedConfiguredNetworks"); 3844 return new ParceledListSlice<>( 3845 WifiConfigurationUtil.convertMultiTypeConfigsToLegacyConfigs(configs, false)); 3846 } 3847 3848 /** 3849 * See {@link WifiManager#getPrivilegedConnectedNetwork()} 3850 */ 3851 @Override getPrivilegedConnectedNetwork(String packageName, String featureId, Bundle extras)3852 public WifiConfiguration getPrivilegedConnectedNetwork(String packageName, String featureId, 3853 Bundle extras) { 3854 enforceReadCredentialPermission(); 3855 enforceAccessPermission(); 3856 int callingUid = Binder.getCallingUid(); 3857 mWifiPermissionsUtil.checkPackage(callingUid, packageName); 3858 if (isPlatformOrTargetSdkLessThanT(packageName, callingUid)) { 3859 mWifiPermissionsUtil.enforceCanAccessScanResults(packageName, featureId, callingUid, 3860 null); 3861 } else { 3862 mWifiPermissionsUtil.enforceNearbyDevicesPermission( 3863 extras.getParcelable(WifiManager.EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE), 3864 true, TAG + " getPrivilegedConnectedNetwork"); 3865 } 3866 if (mVerboseLoggingEnabled) { 3867 mLog.info("getPrivilegedConnectedNetwork uid=%").c(callingUid).flush(); 3868 } 3869 3870 WifiInfo wifiInfo = mActiveModeWarden.getConnectionInfo(); 3871 int networkId = wifiInfo.getNetworkId(); 3872 if (networkId < 0) { 3873 if (mVerboseLoggingEnabled) { 3874 mLog.info("getPrivilegedConnectedNetwork primary wifi not connected") 3875 .flush(); 3876 } 3877 return null; 3878 } 3879 WifiConfiguration config = mWifiThreadRunner.call( 3880 () -> mWifiConfigManager.getConfiguredNetworkWithPassword(networkId), null, 3881 TAG + "#getPrivilegedConnectedNetwork"); 3882 if (config == null) { 3883 if (mVerboseLoggingEnabled) { 3884 mLog.info("getPrivilegedConnectedNetwork failed to get config").flush(); 3885 } 3886 return null; 3887 } 3888 // mask out the randomized MAC address 3889 config.setRandomizedMacAddress(MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS)); 3890 return config; 3891 } 3892 3893 /** 3894 * See {@link WifiManager#setNetworkSelectionConfig(WifiNetworkSelectionConfig)} 3895 */ 3896 @Override 3897 @RequiresApi(Build.VERSION_CODES.TIRAMISU) setNetworkSelectionConfig(@onNull WifiNetworkSelectionConfig nsConfig)3898 public void setNetworkSelectionConfig(@NonNull WifiNetworkSelectionConfig nsConfig) { 3899 if (!SdkLevel.isAtLeastT()) { 3900 throw new UnsupportedOperationException(); 3901 } 3902 if (nsConfig == null) { 3903 throw new IllegalArgumentException("Config can not be null"); 3904 } 3905 if (!nsConfig.isValid()) { 3906 throw new IllegalArgumentException("Config is invalid."); 3907 } 3908 int uid = Binder.getCallingUid(); 3909 if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid) 3910 && !mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { 3911 throw new SecurityException("Uid=" + uid + ", is not allowed to set network selection " 3912 + "config"); 3913 } 3914 mLog.info("uid=% WifiNetworkSelectionConfig=%") 3915 .c(uid).c(nsConfig.toString()).flush(); 3916 3917 mWifiThreadRunner.post(() -> { 3918 mNetworkSelectionConfig = nsConfig; 3919 mWifiConnectivityManager.setNetworkSelectionConfig(nsConfig); 3920 }, TAG + "#setNetworkSelectionConfig"); 3921 mLastCallerInfoManager.put( 3922 WifiManager.API_SET_NETWORK_SELECTION_CONFIG, 3923 Process.myTid(), 3924 uid, Binder.getCallingPid(), "<unknown>", true); 3925 } 3926 3927 /** 3928 * See {@link WifiManager#getNetworkSelectionConfig(Executor, Consumer)} 3929 */ 3930 @Override 3931 @RequiresApi(Build.VERSION_CODES.TIRAMISU) getNetworkSelectionConfig(@onNull IWifiNetworkSelectionConfigListener listener)3932 public void getNetworkSelectionConfig(@NonNull IWifiNetworkSelectionConfigListener listener) { 3933 if (listener == null) { 3934 throw new IllegalArgumentException("listener should not be null"); 3935 } 3936 if (!SdkLevel.isAtLeastT()) { 3937 throw new UnsupportedOperationException(); 3938 } 3939 int uid = Binder.getCallingUid(); 3940 if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid) 3941 && !mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { 3942 throw new SecurityException("Uid=" + uid + ", is not allowed to get network selection " 3943 + "config"); 3944 } 3945 mWifiThreadRunner.post(() -> { 3946 try { 3947 if (mNetworkSelectionConfig == null) { 3948 mNetworkSelectionConfig = new WifiNetworkSelectionConfig.Builder().build(); 3949 } 3950 WifiNetworkSelectionConfig.Builder builder = 3951 new WifiNetworkSelectionConfig.Builder(mNetworkSelectionConfig); 3952 ScoringParams scoringParams = mWifiInjector.getScoringParams(); 3953 if (WifiNetworkSelectionConfig.isRssiThresholdResetArray( 3954 mNetworkSelectionConfig.getRssiThresholds(WIFI_BAND_24_GHZ))) { 3955 builder = builder.setRssiThresholds(WIFI_BAND_24_GHZ, 3956 scoringParams.getRssiArray(ScanResult.BAND_24_GHZ_START_FREQ_MHZ)); 3957 } 3958 if (WifiNetworkSelectionConfig.isRssiThresholdResetArray( 3959 mNetworkSelectionConfig.getRssiThresholds(WIFI_BAND_5_GHZ))) { 3960 builder = builder.setRssiThresholds(WIFI_BAND_5_GHZ, 3961 scoringParams.getRssiArray(ScanResult.BAND_5_GHZ_START_FREQ_MHZ)); 3962 } 3963 if (WifiNetworkSelectionConfig.isRssiThresholdResetArray( 3964 mNetworkSelectionConfig.getRssiThresholds(WIFI_BAND_6_GHZ))) { 3965 builder = builder.setRssiThresholds(WIFI_BAND_6_GHZ, 3966 scoringParams.getRssiArray(ScanResult.BAND_6_GHZ_START_FREQ_MHZ)); 3967 } 3968 mNetworkSelectionConfig = builder.build(); 3969 listener.onResult(mNetworkSelectionConfig); 3970 } catch (RemoteException e) { 3971 Log.e(TAG, e.getMessage(), e); 3972 } 3973 }, TAG + "#getNetworkSelectionConfig"); 3974 } 3975 3976 /** 3977 * See {@link WifiManager#setThirdPartyAppEnablingWifiConfirmationDialogEnabled(boolean)} 3978 */ 3979 @Override setThirdPartyAppEnablingWifiConfirmationDialogEnabled(boolean enable)3980 public void setThirdPartyAppEnablingWifiConfirmationDialogEnabled(boolean enable) { 3981 int uid = Binder.getCallingUid(); 3982 if (!mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) 3983 && !mWifiPermissionsUtil.checkNetworkSetupWizardPermission(uid)) { 3984 throw new SecurityException("Uid=" + uid + ", is not allowed to enable warning dialog " 3985 + "to display when third party apps start wifi"); 3986 } 3987 mLog.info("uid=% enableWarningDialog=%").c(uid).c(enable).flush(); 3988 mSettingsConfigStore.put(SHOW_DIALOG_WHEN_THIRD_PARTY_APPS_ENABLE_WIFI, enable); 3989 mSettingsConfigStore.put(SHOW_DIALOG_WHEN_THIRD_PARTY_APPS_ENABLE_WIFI_SET_BY_API, true); 3990 mLastCallerInfoManager.put( 3991 WifiManager.API_SET_THIRD_PARTY_APPS_ENABLING_WIFI_CONFIRMATION_DIALOG, 3992 Process.myTid(), 3993 uid, Binder.getCallingPid(), "<unknown>", enable); 3994 } 3995 showDialogWhenThirdPartyAppsEnableWifi()3996 private boolean showDialogWhenThirdPartyAppsEnableWifi() { 3997 if (mSettingsConfigStore.get(SHOW_DIALOG_WHEN_THIRD_PARTY_APPS_ENABLE_WIFI_SET_BY_API)) { 3998 // API was called to override the overlay value. 3999 return mSettingsConfigStore.get(SHOW_DIALOG_WHEN_THIRD_PARTY_APPS_ENABLE_WIFI); 4000 } else { 4001 return mResourceCache.getBoolean( 4002 R.bool.config_showConfirmationDialogForThirdPartyAppsEnablingWifi); 4003 } 4004 } 4005 4006 /** 4007 * See {@link WifiManager#isThirdPartyAppEnablingWifiConfirmationDialogEnabled()} 4008 */ 4009 @Override isThirdPartyAppEnablingWifiConfirmationDialogEnabled()4010 public boolean isThirdPartyAppEnablingWifiConfirmationDialogEnabled() { 4011 int uid = Binder.getCallingUid(); 4012 if (!mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) 4013 && !mWifiPermissionsUtil.checkNetworkSetupWizardPermission(uid)) { 4014 throw new SecurityException("Uid=" + uid + ", is not allowed to check if warning " 4015 + "dialog is enabled when third party apps start wifi"); 4016 } 4017 return showDialogWhenThirdPartyAppsEnableWifi(); 4018 } 4019 4020 /** 4021 * See {@link WifiManager#setScreenOnScanSchedule(List)} 4022 */ 4023 @Override 4024 @RequiresApi(Build.VERSION_CODES.TIRAMISU) setScreenOnScanSchedule(int[] scanScheduleSeconds, int[] scanType)4025 public void setScreenOnScanSchedule(int[] scanScheduleSeconds, int[] scanType) { 4026 if (!SdkLevel.isAtLeastT()) { 4027 throw new UnsupportedOperationException(); 4028 } 4029 if ((scanScheduleSeconds == null && scanType != null) 4030 || (scanScheduleSeconds != null && scanType == null)) { 4031 throw new IllegalArgumentException("scanSchedule and scanType should be either both" 4032 + " non-null or both null"); 4033 } 4034 if (scanScheduleSeconds != null && scanScheduleSeconds.length < 1) { 4035 throw new IllegalArgumentException("scanSchedule should have length > 0, or be null"); 4036 } 4037 if (scanType != null) { 4038 if (scanType.length < 1) { 4039 throw new IllegalArgumentException("scanType should have length > 0, or be null"); 4040 } 4041 for (int type : scanType) { 4042 if (type < 0 || type > WifiScanner.SCAN_TYPE_MAX) { 4043 throw new IllegalArgumentException("scanType=" + type 4044 + " is not a valid value"); 4045 } 4046 } 4047 } 4048 int uid = Binder.getCallingUid(); 4049 if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid) 4050 && !mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { 4051 throw new SecurityException("Uid=" + uid + ", is not allowed to set scan schedule"); 4052 } 4053 mLog.info("scanSchedule=% scanType=% uid=%").c(Arrays.toString(scanScheduleSeconds)) 4054 .c(Arrays.toString(scanType)).c(uid).flush(); 4055 mWifiThreadRunner.post(() -> mWifiConnectivityManager.setExternalScreenOnScanSchedule( 4056 scanScheduleSeconds, scanType), TAG + "#setScreenOnScanSchedule"); 4057 mLastCallerInfoManager.put(WifiManager.API_SET_SCAN_SCHEDULE, Process.myTid(), 4058 uid, Binder.getCallingPid(), "<unknown>", 4059 scanScheduleSeconds != null); 4060 } 4061 4062 @Override 4063 @RequiresApi(Build.VERSION_CODES.TIRAMISU) setOneShotScreenOnConnectivityScanDelayMillis(int delayMs)4064 public void setOneShotScreenOnConnectivityScanDelayMillis(int delayMs) { 4065 if (!SdkLevel.isAtLeastT()) { 4066 throw new UnsupportedOperationException(); 4067 } 4068 if (delayMs < 0) { 4069 throw new IllegalArgumentException("delayMs should not be negative"); 4070 } 4071 int uid = Binder.getCallingUid(); 4072 if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid) 4073 && !mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { 4074 throw new SecurityException("Uid=" + uid + ", is not allowed to set screen-on scan " 4075 + "delay"); 4076 } 4077 mLog.info("delayMs=% uid=%").c(delayMs).c(uid).flush(); 4078 mWifiThreadRunner.post(() -> 4079 mWifiConnectivityManager.setOneShotScreenOnConnectivityScanDelayMillis(delayMs), 4080 TAG + "#setOneShotScreenOnConnectivityScanDelayMillis"); 4081 mLastCallerInfoManager.put(WifiManager.API_SET_ONE_SHOT_SCREEN_ON_CONNECTIVITY_SCAN_DELAY, 4082 Process.myTid(), uid, Binder.getCallingPid(), "<unknown>", 4083 delayMs > 0); 4084 } 4085 4086 /** 4087 * Return a map of all matching configurations keys with corresponding scanResults (or an empty 4088 * map if none). 4089 * 4090 * @param scanResults The list of scan results 4091 * @return Map that consists of FQDN (Fully Qualified Domain Name) and corresponding 4092 * scanResults per network type({@link WifiManager#PASSPOINT_HOME_NETWORK} and {@link 4093 * WifiManager#PASSPOINT_ROAMING_NETWORK}). 4094 */ 4095 @Override 4096 public Map<String, Map<Integer, List<ScanResult>>> getAllMatchingPasspointProfilesForScanResults( ParceledListSlice<ScanResult> scanResults)4097 getAllMatchingPasspointProfilesForScanResults( 4098 ParceledListSlice<ScanResult> scanResults) { 4099 if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { 4100 throw new SecurityException(TAG + ": Permission denied"); 4101 } 4102 if (mVerboseLoggingEnabled) { 4103 mLog.info("getMatchingPasspointConfigurations uid=%").c(Binder.getCallingUid()).flush(); 4104 } 4105 if (scanResults == null || !ScanResultUtil.validateScanResultList(scanResults.getList())) { 4106 Log.e(TAG, "Attempt to retrieve passpoint with invalid scanResult List"); 4107 return Collections.emptyMap(); 4108 } 4109 return mWifiThreadRunner.call( 4110 () -> mPasspointManager.getAllMatchingPasspointProfilesForScanResults( 4111 scanResults.getList()), Collections.emptyMap(), 4112 TAG + "#getAllMatchingPasspointProfilesForScanResults"); 4113 } 4114 4115 /** 4116 * See {@link WifiManager#setSsidsAllowlist(Set)} 4117 */ 4118 @Override setSsidsAllowlist(@onNull String packageName, @NonNull ParceledListSlice<WifiSsid> ssids)4119 public void setSsidsAllowlist(@NonNull String packageName, 4120 @NonNull ParceledListSlice<WifiSsid> ssids) { 4121 int uid = Binder.getCallingUid(); 4122 mWifiPermissionsUtil.checkPackage(uid, packageName); 4123 boolean hasPermission = mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) 4124 || isDeviceOrProfileOwner(uid, packageName); 4125 if (!hasPermission && SdkLevel.isAtLeastT()) { 4126 // MANAGE_WIFI_NETWORK_SELECTION is a new permission added in T. 4127 hasPermission = mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid); 4128 } 4129 if (!hasPermission) { 4130 throw new SecurityException(TAG + "Uid " + uid + ": Permission denied"); 4131 } 4132 if (mVerboseLoggingEnabled) { 4133 mLog.info("setSsidsAllowlist uid=%").c(uid).flush(); 4134 } 4135 List<WifiSsid> ssidList = ssids == null ? null : ssids.getList(); 4136 mWifiThreadRunner.post(() -> mWifiBlocklistMonitor.setSsidsAllowlist(ssidList), 4137 TAG + "#setSsidsAllowlist"); 4138 } 4139 4140 /** 4141 * See {@link WifiManager#getSsidsAllowlist()} 4142 */ 4143 @Override getSsidsAllowlist(String packageName)4144 public @NonNull ParceledListSlice<WifiSsid> getSsidsAllowlist(String packageName) { 4145 int uid = Binder.getCallingUid(); 4146 mWifiPermissionsUtil.checkPackage(uid, packageName); 4147 boolean hasPermission = mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) 4148 || isDeviceOrProfileOwner(uid, packageName); 4149 if (!hasPermission && SdkLevel.isAtLeastT()) { 4150 // MANAGE_WIFI_NETWORK_SELECTION is a new permission added in T. 4151 hasPermission = mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid); 4152 } 4153 if (!hasPermission) { 4154 throw new SecurityException(TAG + " Uid " + uid + ": Permission denied"); 4155 } 4156 if (mVerboseLoggingEnabled) { 4157 mLog.info("getSsidsAllowlist uid=%").c(uid).flush(); 4158 } 4159 return new ParceledListSlice<>(mWifiThreadRunner.call( 4160 () -> mWifiBlocklistMonitor.getSsidsAllowlist(), Collections.EMPTY_LIST, 4161 TAG + "#getSsidsAllowlist")); 4162 } 4163 4164 /** 4165 * Returns list of OSU (Online Sign-Up) providers associated with the given list of ScanResult. 4166 * 4167 * @param scanResults a list of ScanResult that has Passpoint APs. 4168 * @return Map that consists of {@link OsuProvider} and a matching list of {@link ScanResult}. 4169 */ 4170 @Override getMatchingOsuProviders( ParceledListSlice<ScanResult> scanResults)4171 public Map<OsuProvider, List<ScanResult>> getMatchingOsuProviders( 4172 ParceledListSlice<ScanResult> scanResults) { 4173 if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { 4174 throw new SecurityException(TAG + ": Permission denied"); 4175 } 4176 if (mVerboseLoggingEnabled) { 4177 mLog.info("getMatchingOsuProviders uid=%").c(Binder.getCallingUid()).flush(); 4178 } 4179 if (scanResults == null || !ScanResultUtil.validateScanResultList(scanResults.getList())) { 4180 Log.w(TAG, "Attempt to retrieve OsuProviders with invalid scanResult List"); 4181 return Collections.emptyMap(); 4182 } 4183 return mWifiThreadRunner.call( 4184 () -> mPasspointManager.getMatchingOsuProviders(scanResults.getList()), 4185 Collections.emptyMap(), TAG + "#getMatchingOsuProviders"); 4186 } 4187 4188 /** 4189 * Returns the matching Passpoint configurations for given OSU(Online Sign-Up) providers. 4190 * 4191 * @param osuProviders a list of {@link OsuProvider} 4192 * @return Map that consists of {@link OsuProvider} and matching {@link PasspointConfiguration}. 4193 */ 4194 @Override getMatchingPasspointConfigsForOsuProviders( ParceledListSlice<OsuProvider> osuProviders)4195 public Map<OsuProvider, PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders( 4196 ParceledListSlice<OsuProvider> osuProviders) { 4197 if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { 4198 throw new SecurityException(TAG + ": Permission denied"); 4199 } 4200 if (mVerboseLoggingEnabled) { 4201 mLog.info("getMatchingPasspointConfigsForOsuProviders uid=%").c( 4202 Binder.getCallingUid()).flush(); 4203 } 4204 if (osuProviders == null || osuProviders.getList() == null) { 4205 Log.e(TAG, "Attempt to retrieve Passpoint configuration with null osuProviders"); 4206 return new HashMap<>(); 4207 } 4208 return mWifiThreadRunner.call( 4209 () -> mPasspointManager.getMatchingPasspointConfigsForOsuProviders( 4210 osuProviders.getList()), Collections.emptyMap(), 4211 TAG + "#getMatchingPasspointConfigsForOsuProviders"); 4212 } 4213 4214 /** 4215 * Returns the corresponding wifi configurations for given FQDN (Fully Qualified Domain Name) 4216 * list. 4217 * 4218 * An empty list will be returned when no match is found. 4219 * 4220 * @param fqdnList a list of FQDN 4221 * @return List of {@link WifiConfiguration} converted from {@link PasspointProvider} 4222 */ 4223 @Override getWifiConfigsForPasspointProfiles( StringParceledListSlice fqdnList)4224 public ParceledListSlice<WifiConfiguration> getWifiConfigsForPasspointProfiles( 4225 StringParceledListSlice fqdnList) { 4226 if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { 4227 throw new SecurityException(TAG + ": Permission denied"); 4228 } 4229 if (mVerboseLoggingEnabled) { 4230 mLog.info("getWifiConfigsForPasspointProfiles uid=%").c( 4231 Binder.getCallingUid()).flush(); 4232 } 4233 if (fqdnList == null || fqdnList.getList() == null || fqdnList.getList().isEmpty()) { 4234 Log.e(TAG, "Attempt to retrieve WifiConfiguration with null fqdn List"); 4235 return new ParceledListSlice<>(Collections.emptyList()); 4236 } 4237 return new ParceledListSlice<>(mWifiThreadRunner.call( 4238 () -> mPasspointManager.getWifiConfigsForPasspointProfiles(fqdnList.getList()), 4239 Collections.emptyList(), TAG + "#getWifiConfigsForPasspointProfiles")); 4240 } 4241 4242 /** 4243 * Returns a list of Wifi configurations for matched available WifiNetworkSuggestion 4244 * corresponding to the given scan results. 4245 * 4246 * An empty list will be returned when no match is found or all matched suggestions is not 4247 * available(not allow user manually connect, user not approved or open network). 4248 * 4249 * @param scanResults a list of {@link ScanResult}. 4250 * @return a list of {@link WifiConfiguration} from matched {@link WifiNetworkSuggestion}. 4251 */ 4252 @Override 4253 public ParceledListSlice<WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( ParceledListSlice<ScanResult> scanResults)4254 getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( 4255 ParceledListSlice<ScanResult> scanResults) { 4256 if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { 4257 throw new SecurityException(TAG + ": Permission denied"); 4258 } 4259 if (mVerboseLoggingEnabled) { 4260 mLog.info("getWifiConfigsForMatchedNetworkSuggestions uid=%").c( 4261 Binder.getCallingUid()).flush(); 4262 } 4263 if (scanResults == null || !ScanResultUtil.validateScanResultList(scanResults.getList())) { 4264 Log.w(TAG, "Attempt to retrieve WifiConfiguration with invalid scanResult List"); 4265 return new ParceledListSlice<>(Collections.emptyList()); 4266 } 4267 return new ParceledListSlice<>(WifiConfigurationUtil.convertMultiTypeConfigsToLegacyConfigs( 4268 mWifiThreadRunner.call( 4269 () -> mWifiNetworkSuggestionsManager 4270 .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( 4271 scanResults.getList()), Collections.emptyList(), 4272 TAG + "#getWifiConfigForMatchedNetworkSuggestionsSharedWithUser"), true)); 4273 } 4274 4275 /** 4276 * see {@link WifiManager#addNetworkPrivileged(WifiConfiguration)} 4277 * @return WifiManager.AddNetworkResult Object. 4278 */ 4279 @Override addOrUpdateNetworkPrivileged( WifiConfiguration config, String packageName)4280 public @NonNull WifiManager.AddNetworkResult addOrUpdateNetworkPrivileged( 4281 WifiConfiguration config, String packageName) { 4282 int pid = Binder.getCallingPid(); 4283 int uid = Binder.getCallingUid(); 4284 mWifiPermissionsUtil.checkPackage(uid, packageName); 4285 boolean hasPermission = isPrivileged(pid, uid) 4286 || mWifiPermissionsUtil.isAdmin(uid, packageName) 4287 || mWifiPermissionsUtil.isSystem(packageName, uid); 4288 if (!hasPermission) { 4289 throw new SecurityException("Caller is not a device owner, profile owner, system app," 4290 + " or privileged app"); 4291 } 4292 return addOrUpdateNetworkInternal(config, packageName, uid, packageName, false); 4293 } 4294 4295 /** 4296 * see {@link android.net.wifi.WifiManager#addOrUpdateNetwork(WifiConfiguration)} 4297 * @return the supplicant-assigned identifier for the new or updated 4298 * network if the operation succeeds, or {@code -1} if it fails 4299 */ 4300 @Override addOrUpdateNetwork(WifiConfiguration config, String packageName, Bundle extras)4301 public int addOrUpdateNetwork(WifiConfiguration config, String packageName, Bundle extras) { 4302 int uidToUse = getMockableCallingUid(); 4303 String packageNameToUse = packageName; 4304 boolean overrideCreator = false; 4305 4306 // if we're being called from the SYSTEM_UID then allow usage of the AttributionSource to 4307 // reassign the WifiConfiguration to another app (reassignment == creatorUid) 4308 if (SdkLevel.isAtLeastS() && UserHandle.getAppId(uidToUse) == Process.SYSTEM_UID) { 4309 if (extras == null) { 4310 throw new SecurityException("extras bundle is null"); 4311 } 4312 AttributionSource as = extras.getParcelable( 4313 WifiManager.EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE); 4314 if (as == null) { 4315 throw new SecurityException("addOrUpdateNetwork attributionSource is null"); 4316 } 4317 4318 if (!as.checkCallingUid()) { 4319 throw new SecurityException( 4320 "addOrUpdateNetwork invalid (checkCallingUid fails) attribution source=" 4321 + as); 4322 } 4323 4324 // an attribution chain is either of size 1: unregistered (valid by definition) or 4325 // size >1: in which case all are validated. 4326 if (as.getNext() != null) { 4327 AttributionSource asIt = as; 4328 AttributionSource asLast = as; 4329 do { 4330 if (!asIt.isTrusted(mContext)) { 4331 throw new SecurityException( 4332 "addOrUpdateNetwork invalid (isTrusted fails) attribution source=" 4333 + asIt); 4334 } 4335 asIt = asIt.getNext(); 4336 if (asIt != null) asLast = asIt; 4337 } while (asIt != null); 4338 4339 // use the last AttributionSource in the chain - i.e. the original caller 4340 uidToUse = asLast.getUid(); 4341 packageNameToUse = asLast.getPackageName(); 4342 if (config.networkId >= 0) { 4343 /** 4344 * only allow to override the creator by calling the 4345 * {@link WifiManager#updateNetwork(WifiConfiguration)} 4346 */ 4347 overrideCreator = true; 4348 } 4349 } 4350 } 4351 4352 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 4353 return -1; 4354 } 4355 4356 int callingUid = Binder.getCallingUid(); 4357 int callingPid = Binder.getCallingPid(); 4358 mWifiPermissionsUtil.checkPackage(callingUid, packageName); 4359 boolean isAdmin = mWifiPermissionsUtil.isAdmin(callingUid, packageName); 4360 boolean isCamera = mWifiPermissionsUtil.checkCameraPermission(callingUid); 4361 boolean isSystem = mWifiPermissionsUtil.isSystem(packageName, callingUid); 4362 boolean isPrivileged = isPrivileged(callingPid, callingUid); 4363 if (!isPrivileged && !isSystem && !isAdmin && config.getBssidAllowlistInternal() != null) { 4364 mLog.info("addOrUpdateNetwork with allow bssid list is not allowed for uid=%") 4365 .c(callingUid).flush(); 4366 return -1; 4367 } 4368 4369 if (!isTargetSdkLessThanQOrPrivileged(packageName, callingPid, callingUid)) { 4370 mLog.info("addOrUpdateNetwork not allowed for uid=%").c(callingUid).flush(); 4371 return -1; 4372 } 4373 long ident = Binder.clearCallingIdentity(); 4374 try { 4375 if (mUserManager.hasUserRestrictionForUser(UserManager.DISALLOW_CONFIG_WIFI, 4376 UserHandle.of(mWifiPermissionsUtil.getCurrentUser())) 4377 && isCamera && !isAdmin) { 4378 mLog.info( 4379 "addOrUpdateNetwork not allowed for the camera apps and therefore the " 4380 + "user when DISALLOW_CONFIG_WIFI user restriction is set").flush(); 4381 return -1; 4382 } 4383 if (SdkLevel.isAtLeastT() && mUserManager.hasUserRestrictionForUser( 4384 UserManager.DISALLOW_ADD_WIFI_CONFIG, 4385 UserHandle.getUserHandleForUid(callingUid))) { 4386 if (mWifiPermissionsUtil.isTargetSdkLessThan( 4387 packageName, Build.VERSION_CODES.Q, callingUid) 4388 && !(isPrivileged || isAdmin || isSystem)) { 4389 mLog.info( 4390 "addOrUpdateNetwork not allowed for normal apps targeting " 4391 + "SDK less than Q when the DISALLOW_ADD_WIFI_CONFIG " 4392 + "user restriction is set").flush(); 4393 return -1; 4394 } 4395 if (isCamera && !isAdmin) { 4396 mLog.info( 4397 "addOrUpdateNetwork not allowed for camera apps and therefore the " 4398 + "user when the DISALLOW_ADD_WIFI_CONFIG " 4399 + "user restriction is set").flush(); 4400 return -1; 4401 } 4402 } 4403 } finally { 4404 Binder.restoreCallingIdentity(ident); 4405 } 4406 4407 mLog.info("addOrUpdateNetwork uid=%").c(callingUid).flush(); 4408 return addOrUpdateNetworkInternal(config, packageName, uidToUse, 4409 packageNameToUse, overrideCreator).networkId; 4410 } 4411 addOrUpdateNetworkInternal(WifiConfiguration config, String packageName, int attributedCreatorUid, String attributedCreatorPackage, boolean overrideCreator)4412 private @NonNull AddNetworkResult addOrUpdateNetworkInternal(WifiConfiguration config, 4413 String packageName, int attributedCreatorUid, String attributedCreatorPackage, 4414 boolean overrideCreator) { 4415 if (config == null) { 4416 Log.e(TAG, "bad network configuration"); 4417 return new AddNetworkResult( 4418 AddNetworkResult.STATUS_INVALID_CONFIGURATION, -1); 4419 } 4420 mWifiMetrics.incrementNumAddOrUpdateNetworkCalls(); 4421 4422 // Previously, this API is overloaded for installing Passpoint profiles. Now 4423 // that we have a dedicated API for doing it, redirect the call to the dedicated API. 4424 if (config.isPasspoint()) { 4425 PasspointConfiguration passpointConfig = 4426 PasspointProvider.convertFromWifiConfig(config); 4427 if (passpointConfig == null || passpointConfig.getCredential() == null) { 4428 Log.e(TAG, "Missing credential for Passpoint profile"); 4429 return new AddNetworkResult( 4430 AddNetworkResult.STATUS_ADD_PASSPOINT_FAILURE, -1); 4431 } 4432 4433 // Copy over certificates and keys. 4434 X509Certificate[] x509Certificates = null; 4435 if (config.enterpriseConfig.getCaCertificate() != null) { 4436 x509Certificates = 4437 new X509Certificate[]{config.enterpriseConfig.getCaCertificate()}; 4438 } 4439 passpointConfig.getCredential().setCaCertificates(x509Certificates); 4440 passpointConfig.getCredential().setClientCertificateChain( 4441 config.enterpriseConfig.getClientCertificateChain()); 4442 passpointConfig.getCredential().setClientPrivateKey( 4443 config.enterpriseConfig.getClientPrivateKey()); 4444 if (!addOrUpdatePasspointConfiguration(passpointConfig, packageName)) { 4445 Log.e(TAG, "Failed to add Passpoint profile"); 4446 return new AddNetworkResult( 4447 AddNetworkResult.STATUS_ADD_PASSPOINT_FAILURE, -1); 4448 } 4449 // There is no network ID associated with a Passpoint profile. 4450 return new AddNetworkResult(AddNetworkResult.STATUS_SUCCESS, 0); 4451 } 4452 4453 mLastCallerInfoManager.put(config.networkId < 0 4454 ? WifiManager.API_ADD_NETWORK : WifiManager.API_UPDATE_NETWORK, 4455 Process.myTid(), Binder.getCallingUid(), 4456 Binder.getCallingPid(), packageName, true); 4457 Log.i("addOrUpdateNetworkInternal", " uid = " + Binder.getCallingUid() 4458 + " SSID " + config.SSID 4459 + " nid=" + config.networkId); 4460 NetworkUpdateResult result = mWifiThreadRunner.call( 4461 () -> mWifiConfigManager.addOrUpdateNetwork(config, attributedCreatorUid, 4462 attributedCreatorPackage, overrideCreator), 4463 new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID), 4464 TAG + "#addOrUpdateNetworkInternal"); 4465 return new AddNetworkResult(result.getStatusCode(), result.getNetworkId()); 4466 } 4467 verifyCert(X509Certificate caCert)4468 public static void verifyCert(X509Certificate caCert) 4469 throws GeneralSecurityException, IOException { 4470 CertificateFactory factory = CertificateFactory.getInstance("X.509"); 4471 CertPathValidator validator = 4472 CertPathValidator.getInstance(CertPathValidator.getDefaultType()); 4473 CertPath path = factory.generateCertPath( 4474 Arrays.asList(caCert)); 4475 KeyStore ks = KeyStore.getInstance("AndroidCAStore"); 4476 ks.load(null, null); 4477 PKIXParameters params = new PKIXParameters(ks); 4478 params.setRevocationEnabled(false); 4479 validator.validate(path, params); 4480 } 4481 4482 /** 4483 * See {@link android.net.wifi.WifiManager#removeNetwork(int)} 4484 * @param netId the integer that identifies the network configuration 4485 * to the supplicant 4486 * @return {@code true} if the operation succeeded 4487 */ 4488 @Override removeNetwork(int netId, String packageName)4489 public boolean removeNetwork(int netId, String packageName) { 4490 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 4491 return false; 4492 } 4493 int callingUid = Binder.getCallingUid(); 4494 mWifiPermissionsUtil.checkPackage(callingUid, packageName); 4495 if (!isTargetSdkLessThanQOrPrivileged( 4496 packageName, Binder.getCallingPid(), callingUid)) { 4497 mLog.info("removeNetwork not allowed for uid=%").c(callingUid).flush(); 4498 return false; 4499 } 4500 mLog.info("removeNetwork uid=%").c(callingUid).flush(); 4501 return mWifiThreadRunner.call( 4502 () -> mWifiConfigManager.removeNetwork(netId, callingUid, packageName), false, 4503 TAG + "#removeNetwork"); 4504 } 4505 4506 @Override removeNonCallerConfiguredNetworks(String packageName)4507 public boolean removeNonCallerConfiguredNetworks(String packageName) { 4508 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 4509 throw new SecurityException("Caller does not hold CHANGE_WIFI_STATE permission"); 4510 } 4511 final int callingUid = Binder.getCallingUid(); 4512 mWifiPermissionsUtil.checkPackage(callingUid, packageName); 4513 if (!mWifiPermissionsUtil.isOrganizationOwnedDeviceAdmin(callingUid, packageName)) { 4514 throw new SecurityException("Caller is not device owner or profile owner " 4515 + "of an organization owned device"); 4516 } 4517 return mWifiThreadRunner.call( 4518 () -> mWifiConfigManager.removeNonCallerConfiguredNetwork(callingUid), false, 4519 TAG + "#removeNonCallerConfiguredNetworks"); 4520 } 4521 4522 /** 4523 * Trigger a connect request and wait for the callback to return status. 4524 * This preserves the legacy connect API behavior, i.e. {@link WifiManager#enableNetwork( 4525 * int, true)} 4526 * @return 4527 */ triggerConnectAndReturnStatus(int netId, int callingUid, @NonNull String packageName)4528 private boolean triggerConnectAndReturnStatus(int netId, int callingUid, 4529 @NonNull String packageName) { 4530 final CountDownLatch countDownLatch = new CountDownLatch(1); 4531 final Mutable<Boolean> success = new Mutable<>(false); 4532 IActionListener.Stub connectListener = new IActionListener.Stub() { 4533 @Override 4534 public void onSuccess() { 4535 success.value = true; 4536 countDownLatch.countDown(); 4537 } 4538 @Override 4539 public void onFailure(int reason) { 4540 success.value = false; 4541 countDownLatch.countDown(); 4542 } 4543 }; 4544 mWifiThreadRunner.post(() -> 4545 mMakeBeforeBreakManager.stopAllSecondaryTransientClientModeManagers(() -> 4546 mConnectHelper.connectToNetwork( 4547 new NetworkUpdateResult(netId), 4548 new ActionListenerWrapper(connectListener), 4549 callingUid, packageName, null) 4550 ), TAG + "#triggerConnectAndReturnStatus" 4551 ); 4552 // now wait for response. 4553 try { 4554 countDownLatch.await(RUN_WITH_SCISSORS_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); 4555 } catch (InterruptedException e) { 4556 Log.e(TAG, "Failed to retrieve connect status"); 4557 } 4558 return success.value; 4559 } 4560 4561 /** 4562 * See {@link android.net.wifi.WifiManager#enableNetwork(int, boolean)} 4563 * @param netId the integer that identifies the network configuration 4564 * to the supplicant 4565 * @param disableOthers if true, disable all other networks. 4566 * @return {@code true} if the operation succeeded 4567 */ 4568 @Override enableNetwork(int netId, boolean disableOthers, @NonNull String packageName)4569 public boolean enableNetwork(int netId, boolean disableOthers, @NonNull String packageName) { 4570 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 4571 return false; 4572 } 4573 if (packageName == null) { 4574 throw new IllegalArgumentException("packageName must not be null"); 4575 } 4576 int callingUid = Binder.getCallingUid(); 4577 mWifiPermissionsUtil.checkPackage(callingUid, packageName); 4578 if (!isTargetSdkLessThanQOrPrivileged( 4579 packageName, Binder.getCallingPid(), callingUid)) { 4580 mLog.info("enableNetwork not allowed for uid=%").c(callingUid).flush(); 4581 return false; 4582 } 4583 WifiConfiguration configuration = mWifiConfigManager.getConfiguredNetwork(netId); 4584 if (mWifiPermissionsUtil.isAdminRestrictedNetwork(configuration)) { 4585 mLog.info("enableNetwork not allowed for admin restricted network Id=%") 4586 .c(netId).flush(); 4587 return false; 4588 } 4589 if (mWifiGlobals.isDeprecatedSecurityTypeNetwork(configuration)) { 4590 mLog.info("enableNetwork not allowed for deprecated security type network Id=%") 4591 .c(netId).flush(); 4592 return false; 4593 } 4594 4595 mLastCallerInfoManager.put(WifiManager.API_ENABLE_NETWORK, Process.myTid(), 4596 callingUid, Binder.getCallingPid(), packageName, disableOthers); 4597 // TODO b/33807876 Log netId 4598 mLog.info("enableNetwork uid=% disableOthers=%") 4599 .c(callingUid) 4600 .c(disableOthers).flush(); 4601 4602 mWifiMetrics.incrementNumEnableNetworkCalls(); 4603 if (disableOthers) { 4604 return triggerConnectAndReturnStatus(netId, callingUid, packageName); 4605 } else { 4606 return mWifiThreadRunner.call( 4607 () -> mWifiConfigManager.enableNetwork(netId, false, callingUid, packageName), 4608 false, 4609 TAG + "#enableNetwork"); 4610 } 4611 } 4612 4613 /** 4614 * See {@link android.net.wifi.WifiManager#disableNetwork(int)} 4615 * @param netId the integer that identifies the network configuration 4616 * to the supplicant 4617 * @return {@code true} if the operation succeeded 4618 */ 4619 @Override disableNetwork(int netId, String packageName)4620 public boolean disableNetwork(int netId, String packageName) { 4621 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 4622 return false; 4623 } 4624 int callingUid = Binder.getCallingUid(); 4625 mWifiPermissionsUtil.checkPackage(callingUid, packageName); 4626 if (!isTargetSdkLessThanQOrPrivileged( 4627 packageName, Binder.getCallingPid(), callingUid)) { 4628 mLog.info("disableNetwork not allowed for uid=%").c(callingUid).flush(); 4629 return false; 4630 } 4631 mLastCallerInfoManager.put(WifiManager.API_DISABLE_NETWORK, Process.myTid(), 4632 callingUid, Binder.getCallingPid(), packageName, true); 4633 mLog.info("disableNetwork uid=%").c(callingUid).flush(); 4634 return mWifiThreadRunner.call( 4635 () -> mWifiConfigManager.disableNetwork(netId, callingUid, packageName), false, 4636 TAG + "#disableNetwork"); 4637 } 4638 4639 /** 4640 * See 4641 * {@link android.net.wifi.WifiManager#startRestrictingAutoJoinToSubscriptionId(int)} 4642 * @param subscriptionId the subscription ID of the carrier whose merged wifi networks won't be 4643 * disabled. 4644 */ 4645 @Override 4646 @RequiresApi(Build.VERSION_CODES.S) startRestrictingAutoJoinToSubscriptionId(int subscriptionId)4647 public void startRestrictingAutoJoinToSubscriptionId(int subscriptionId) { 4648 if (!SdkLevel.isAtLeastS()) { 4649 throw new UnsupportedOperationException(); 4650 } 4651 if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { 4652 throw new SecurityException(TAG + ": Permission denied"); 4653 } 4654 4655 mLog.info("startRestrictingAutoJoinToSubscriptionId=% uid=%").c(subscriptionId) 4656 .c(Binder.getCallingUid()).flush(); 4657 mWifiThreadRunner.post(() -> { 4658 mWifiConfigManager 4659 .startRestrictingAutoJoinToSubscriptionId(subscriptionId); 4660 // Clear all cached candidates to avoid the imminent disconnect connecting back to a 4661 // cached candidate that's likely no longer valid after 4662 // startRestrictingAutoJoinToSubscriptionId is called. Let the disconnection trigger 4663 // a new scan to ensure proper network selection is done. 4664 mWifiConnectivityManager.clearCachedCandidates(); 4665 // always disconnect here and rely on auto-join to find the appropriate carrier network 4666 // to join. Even if we are currently connected to the carrier-merged wifi, it's still 4667 // better to disconnect here because it's possible that carrier wifi offload is 4668 // disabled. 4669 for (ClientModeManager clientModeManager : mActiveModeWarden.getClientModeManagers()) { 4670 if (!(clientModeManager instanceof ConcreteClientModeManager)) { 4671 continue; 4672 } 4673 ConcreteClientModeManager cmm = (ConcreteClientModeManager) clientModeManager; 4674 if ((cmm.getRole() == ROLE_CLIENT_SECONDARY_LONG_LIVED && cmm.isSecondaryInternet()) 4675 || cmm.getRole() == ROLE_CLIENT_SECONDARY_TRANSIENT) { 4676 clientModeManager.disconnect(); 4677 } 4678 } 4679 // Disconnect the primary CMM last to avoid STA+STA features handling the 4680 // primary STA disconnecting (such as promoting the secondary to primary), potentially 4681 // resulting in messy and unexpected state transitions. 4682 mActiveModeWarden.getPrimaryClientModeManager().disconnect(); 4683 }, TAG + "#startRestrictingAutoJoinToSubscriptionId"); 4684 } 4685 4686 /** 4687 * See {@link android.net.wifi.WifiManager#stopRestrictingAutoJoinToSubscriptionId()} 4688 */ 4689 @Override 4690 @RequiresApi(Build.VERSION_CODES.S) stopRestrictingAutoJoinToSubscriptionId()4691 public void stopRestrictingAutoJoinToSubscriptionId() { 4692 if (!SdkLevel.isAtLeastS()) { 4693 throw new UnsupportedOperationException(); 4694 } 4695 if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { 4696 throw new SecurityException(TAG + ": Permission denied"); 4697 } 4698 4699 mLog.info("stopRestrictingAutoJoinToSubscriptionId uid=%") 4700 .c(Binder.getCallingUid()).flush(); 4701 mWifiThreadRunner.post(() -> 4702 mWifiConfigManager.stopRestrictingAutoJoinToSubscriptionId(), 4703 TAG + "#stopRestrictingAutoJoinToSubscriptionId"); 4704 } 4705 4706 /** 4707 * See {@link android.net.wifi.WifiManager#allowAutojoinGlobal(boolean)} 4708 * @param choice the OEM's choice to allow auto-join 4709 */ 4710 @Override allowAutojoinGlobal(boolean choice, String packageName, Bundle extras)4711 public void allowAutojoinGlobal(boolean choice, String packageName, Bundle extras) { 4712 int callingUid = Binder.getCallingUid(); 4713 boolean isDeviceAdmin = mWifiPermissionsUtil.isAdmin(callingUid, packageName); 4714 if (!mWifiPermissionsUtil.checkNetworkSettingsPermission(callingUid) 4715 && !mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(callingUid) 4716 && !isDeviceAdmin) { 4717 throw new SecurityException("Uid " + callingUid 4718 + " is not allowed to set wifi global autojoin"); 4719 } 4720 mLog.info("allowAutojoinGlobal=% uid=%").c(choice).c(callingUid).flush(); 4721 if (!isDeviceAdmin && SdkLevel.isAtLeastS()) { 4722 // direct caller is not device admin but there exists and attribution chain. Check 4723 // if the original caller is device admin. 4724 AttributionSource as = extras.getParcelable( 4725 WifiManager.EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE); 4726 if (as != null) { 4727 AttributionSource asLast = as; 4728 while (asLast.getNext() != null) { 4729 asLast = asLast.getNext(); 4730 } 4731 isDeviceAdmin = mWifiPermissionsUtil.isAdmin(asLast.getUid(), 4732 asLast.getPackageName()) || mWifiPermissionsUtil.isLegacyDeviceAdmin( 4733 asLast.getUid(), asLast.getPackageName()); 4734 } 4735 } 4736 boolean finalIsDeviceAdmin = isDeviceAdmin; 4737 mWifiThreadRunner.post(() -> mWifiConnectivityManager.setAutoJoinEnabledExternal(choice, 4738 finalIsDeviceAdmin), TAG + "#allowAutojoinGlobal"); 4739 mLastCallerInfoManager.put(WifiManager.API_AUTOJOIN_GLOBAL, Process.myTid(), 4740 callingUid, Binder.getCallingPid(), "<unknown>", choice); 4741 } 4742 4743 /** 4744 * See {@link WifiManager#queryAutojoinGlobal(Executor, Consumer)} 4745 */ 4746 @Override queryAutojoinGlobal(@onNull IBooleanListener listener)4747 public void queryAutojoinGlobal(@NonNull IBooleanListener listener) { 4748 if (listener == null) { 4749 throw new IllegalArgumentException("listener should not be null"); 4750 } 4751 int callingUid = Binder.getCallingUid(); 4752 if (!mWifiPermissionsUtil.checkNetworkSettingsPermission(callingUid) 4753 && !mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(callingUid) 4754 && !isDeviceOrProfileOwner(callingUid, mContext.getOpPackageName())) { 4755 throw new SecurityException("Uid " + callingUid 4756 + " is not allowed to get wifi global autojoin"); 4757 } 4758 mWifiThreadRunner.post(() -> { 4759 try { 4760 listener.onResult(mWifiConnectivityManager.getAutoJoinEnabledExternal()); 4761 } catch (RemoteException e) { 4762 Log.e(TAG, e.getMessage(), e); 4763 } 4764 }, TAG + "#queryAutojoinGlobal"); 4765 } 4766 4767 /** 4768 * See {@link android.net.wifi.WifiManager#allowAutojoin(int, boolean)} 4769 * @param netId the integer that identifies the network configuration 4770 * @param choice the user's choice to allow auto-join 4771 */ 4772 @Override allowAutojoin(int netId, boolean choice)4773 public void allowAutojoin(int netId, boolean choice) { 4774 enforceNetworkSettingsPermission(); 4775 4776 int callingUid = Binder.getCallingUid(); 4777 mLog.info("allowAutojoin=% uid=%").c(choice).c(callingUid).flush(); 4778 mLastCallerInfoManager.put(WifiManager.API_ALLOW_AUTOJOIN, Process.myTid(), 4779 callingUid, Binder.getCallingPid(), "<unknown>", choice); 4780 mWifiThreadRunner.post(() -> { 4781 WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(netId); 4782 if (config == null) { 4783 return; 4784 } 4785 if (config.fromWifiNetworkSpecifier) { 4786 Log.e(TAG, "Auto-join configuration is not permitted for NetworkSpecifier " 4787 + "connections: " + config); 4788 return; 4789 } 4790 if (config.isPasspoint() && !config.isEphemeral()) { 4791 Log.e(TAG, 4792 "Auto-join configuration for a non-ephemeral Passpoint network should be " 4793 + "configured using FQDN: " 4794 + config); 4795 return; 4796 } 4797 // If the network is a suggestion, store the auto-join configure to the 4798 // WifiNetWorkSuggestionsManager. 4799 if (config.fromWifiNetworkSuggestion) { 4800 if (!mWifiNetworkSuggestionsManager 4801 .allowNetworkSuggestionAutojoin(config, choice)) { 4802 return; 4803 } 4804 } 4805 // even for Suggestion, modify the current ephemeral configuration so that 4806 // existing configuration auto-connection is updated correctly 4807 if (choice != config.allowAutojoin) { 4808 mWifiConfigManager.allowAutojoin(netId, choice); 4809 // do not log this metrics for passpoint networks again here since it's already 4810 // logged in PasspointManager. 4811 if (!config.isPasspoint()) { 4812 mWifiMetrics.logUserActionEvent(choice 4813 ? UserActionEvent.EVENT_CONFIGURE_AUTO_CONNECT_ON 4814 : UserActionEvent.EVENT_CONFIGURE_AUTO_CONNECT_OFF, netId); 4815 } 4816 } 4817 }, TAG + "#allowAutojoin"); 4818 } 4819 4820 /** 4821 * See {@link android.net.wifi.WifiManager#allowAutojoinPasspoint(String, boolean)} 4822 * @param fqdn the FQDN that identifies the passpoint configuration 4823 * @param enableAutojoin true to enable auto-join, false to disable 4824 */ 4825 @Override allowAutojoinPasspoint(String fqdn, boolean enableAutojoin)4826 public void allowAutojoinPasspoint(String fqdn, boolean enableAutojoin) { 4827 enforceNetworkSettingsPermission(); 4828 if (fqdn == null) { 4829 throw new IllegalArgumentException("FQDN cannot be null"); 4830 } 4831 4832 int callingUid = Binder.getCallingUid(); 4833 mLog.info("allowAutojoinPasspoint=% uid=%").c(enableAutojoin).c(callingUid).flush(); 4834 mWifiThreadRunner.post( 4835 () -> mPasspointManager.enableAutojoin(null, fqdn, enableAutojoin), 4836 TAG + "#allowAutojoinPasspoint"); 4837 } 4838 4839 /** 4840 * See {@link WifiManager#getBssidBlocklist(List, Executor, Consumer)} 4841 * @param ssids the list of ssids to get BSSID blocklist for. 4842 * @param listener returns the results 4843 */ 4844 @Override getBssidBlocklist(@onNull ParceledListSlice<WifiSsid> ssids, @NonNull IMacAddressListListener listener)4845 public void getBssidBlocklist(@NonNull ParceledListSlice<WifiSsid> ssids, 4846 @NonNull IMacAddressListListener listener) { 4847 if (ssids == null || ssids.getList() == null) { 4848 throw new IllegalArgumentException("Null ssids"); 4849 } 4850 if (listener == null) { 4851 throw new IllegalArgumentException("Null listener"); 4852 } 4853 int uid = Binder.getCallingUid(); 4854 if (!mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) 4855 && !mWifiPermissionsUtil.checkNetworkSetupWizardPermission(uid)) { 4856 throw new SecurityException("No permission to call getBssidBlocklist"); 4857 } 4858 Set<String> ssidSet; 4859 if (!ssids.getList().isEmpty()) { 4860 ssidSet = new ArraySet<>(); 4861 for (WifiSsid ssid : ssids.getList()) { 4862 ssidSet.add(ssid.toString()); 4863 } 4864 } else { 4865 ssidSet = null; 4866 } 4867 mWifiThreadRunner.post(() -> { 4868 try { 4869 List<String> bssids = mWifiBlocklistMonitor.getBssidBlocklistForSsids(ssidSet); 4870 List<MacAddress> macAddresses = new ArrayList<>(); 4871 for (String bssid : bssids) { 4872 try { 4873 macAddresses.add(MacAddress.fromString(bssid)); 4874 } catch (Exception e) { 4875 Log.e(TAG, "getBssidBlocklist failed to convert MAC address: " + bssid); 4876 } 4877 } 4878 listener.onResult(new ParceledListSlice(macAddresses)); 4879 } catch (RemoteException e) { 4880 Log.e(TAG, e.getMessage(), e); 4881 } 4882 }, TAG + "#getBssidBlocklist"); 4883 } 4884 4885 /** 4886 * See {@link android.net.wifi.WifiManager 4887 * #setMacRandomizationSettingPasspointEnabled(String, boolean)} 4888 * @param fqdn the FQDN that identifies the passpoint configuration 4889 * @param enable true to enable mac randomization, false to disable 4890 */ 4891 @Override setMacRandomizationSettingPasspointEnabled(String fqdn, boolean enable)4892 public void setMacRandomizationSettingPasspointEnabled(String fqdn, boolean enable) { 4893 enforceNetworkSettingsPermission(); 4894 if (fqdn == null) { 4895 throw new IllegalArgumentException("FQDN cannot be null"); 4896 } 4897 4898 int callingUid = Binder.getCallingUid(); 4899 mLog.info("setMacRandomizationSettingPasspointEnabled=% uid=%") 4900 .c(enable).c(callingUid).flush(); 4901 mWifiThreadRunner.post( 4902 () -> mPasspointManager.enableMacRandomization(fqdn, enable), 4903 TAG + "#setMacRandomizationSettingPasspointEnabled"); 4904 } 4905 4906 /** 4907 * See {@link android.net.wifi.WifiManager#setPasspointMeteredOverride(String, boolean)} 4908 * @param fqdn the FQDN that identifies the passpoint configuration 4909 * @param meteredOverride One of the values in {@link MeteredOverride} 4910 */ 4911 @Override setPasspointMeteredOverride(String fqdn, int meteredOverride)4912 public void setPasspointMeteredOverride(String fqdn, int meteredOverride) { 4913 enforceNetworkSettingsPermission(); 4914 if (fqdn == null) { 4915 throw new IllegalArgumentException("FQDN cannot be null"); 4916 } 4917 4918 int callingUid = Binder.getCallingUid(); 4919 mLog.info("setPasspointMeteredOverride=% uid=%") 4920 .c(meteredOverride).c(callingUid).flush(); 4921 mWifiThreadRunner.post( 4922 () -> mPasspointManager.setMeteredOverride(fqdn, meteredOverride), 4923 TAG + "#setPasspointMeteredOverride"); 4924 } 4925 4926 /** 4927 * Provides backward compatibility for apps using 4928 * {@link WifiManager#getConnectionInfo()}, {@link WifiManager#getDhcpInfo()} when a 4929 * secondary STA is created as a result of a request from their app (peer to peer 4930 * WifiNetworkSpecifier request or oem paid/private suggestion). 4931 */ getClientModeManagerIfSecondaryCmmRequestedByCallerPresent( int callingUid, @NonNull String callingPackageName)4932 private ClientModeManager getClientModeManagerIfSecondaryCmmRequestedByCallerPresent( 4933 int callingUid, @NonNull String callingPackageName) { 4934 List<ConcreteClientModeManager> secondaryCmms = null; 4935 ActiveModeManager.ClientConnectivityRole roleSecondaryLocalOnly = 4936 ROLE_CLIENT_LOCAL_ONLY; 4937 ActiveModeManager.ClientInternetConnectivityRole roleSecondaryLongLived = 4938 ROLE_CLIENT_SECONDARY_LONG_LIVED; 4939 try { 4940 secondaryCmms = mActiveModeWarden.getClientModeManagersInRoles( 4941 roleSecondaryLocalOnly, roleSecondaryLongLived); 4942 } catch (Exception e) { 4943 // print debug info and then rethrow the exception 4944 Log.e(TAG, "Failed to call getClientModeManagersInRoles on " 4945 + roleSecondaryLocalOnly + ", and " + roleSecondaryLongLived); 4946 throw e; 4947 } 4948 4949 for (ConcreteClientModeManager cmm : secondaryCmms) { 4950 WorkSource reqWs = new WorkSource(cmm.getRequestorWs()); 4951 if (reqWs.size() > 1 && cmm.getRole() == roleSecondaryLocalOnly) { 4952 // Remove promoted settings WorkSource if present 4953 reqWs.remove(mFrameworkFacade.getSettingsWorkSource(mContext)); 4954 } 4955 WorkSource withCaller = new WorkSource(reqWs); 4956 withCaller.add(new WorkSource(callingUid, callingPackageName)); 4957 // If there are more than 1 secondary CMM for same app, return any one (should not 4958 // happen currently since we don't support 3 STA's concurrently). 4959 if (reqWs.equals(withCaller)) { 4960 mLog.info("getConnectionInfo providing secondary CMM info").flush(); 4961 return cmm; 4962 } 4963 } 4964 // No secondary CMM's created for the app, return primary CMM. 4965 return mActiveModeWarden.getPrimaryClientModeManager(); 4966 } 4967 4968 /** 4969 * See {@link android.net.wifi.WifiManager#getConnectionInfo()} 4970 * @return the Wi-Fi information, contained in {@link WifiInfo}. 4971 */ 4972 @Override getConnectionInfo(@onNull String callingPackage, @Nullable String callingFeatureId)4973 public WifiInfo getConnectionInfo(@NonNull String callingPackage, 4974 @Nullable String callingFeatureId) { 4975 enforceAccessPermission(); 4976 int uid = Binder.getCallingUid(); 4977 if (mVerboseLoggingEnabled) { 4978 mLog.info("getConnectionInfo uid=%").c(uid).flush(); 4979 } 4980 mWifiPermissionsUtil.checkPackage(uid, callingPackage); 4981 if (mActiveModeWarden.getWifiState() != WIFI_STATE_ENABLED) { 4982 return new WifiInfo(); 4983 } 4984 WifiInfo wifiInfo; 4985 if (isCurrentRequestWsContainsCaller(uid, callingPackage)) { 4986 wifiInfo = 4987 mWifiThreadRunner.call( 4988 () -> 4989 getClientModeManagerIfSecondaryCmmRequestedByCallerPresent( 4990 uid, callingPackage) 4991 .getConnectionInfo(), 4992 new WifiInfo(), TAG + "#getConnectionInfo"); 4993 } else { 4994 // If no caller 4995 wifiInfo = mActiveModeWarden.getConnectionInfo(); 4996 } 4997 long ident = Binder.clearCallingIdentity(); 4998 try { 4999 long redactions = wifiInfo.getApplicableRedactions(); 5000 if (mWifiPermissionsUtil.checkLocalMacAddressPermission(uid)) { 5001 if (mVerboseLoggingEnabled) { 5002 Log.v(TAG, "Clearing REDACT_FOR_LOCAL_MAC_ADDRESS for " + callingPackage 5003 + "(uid=" + uid + ")"); 5004 } 5005 redactions &= ~NetworkCapabilities.REDACT_FOR_LOCAL_MAC_ADDRESS; 5006 } 5007 if (mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) 5008 || mWifiPermissionsUtil.checkNetworkSetupWizardPermission(uid)) { 5009 if (mVerboseLoggingEnabled) { 5010 Log.v(TAG, "Clearing REDACT_FOR_NETWORK_SETTINGS for " + callingPackage 5011 + "(uid=" + uid + ")"); 5012 } 5013 redactions &= ~NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS; 5014 } 5015 try { 5016 mWifiPermissionsUtil.enforceCanAccessScanResults(callingPackage, callingFeatureId, 5017 uid, null); 5018 if (mVerboseLoggingEnabled) { 5019 Log.v(TAG, "Clearing REDACT_FOR_ACCESS_FINE_LOCATION for " + callingPackage 5020 + "(uid=" + uid + ")"); 5021 } 5022 redactions &= ~NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION; 5023 } catch (SecurityException ignored) { 5024 if (mVerboseLoggingEnabled) { 5025 Log.v(TAG, "Keeping REDACT_FOR_ACCESS_FINE_LOCATION:" + ignored); 5026 } 5027 } 5028 return wifiInfo.makeCopy(redactions); 5029 } finally { 5030 Binder.restoreCallingIdentity(ident); 5031 } 5032 } 5033 isCurrentRequestWsContainsCaller(int uid, String callingPackage)5034 private boolean isCurrentRequestWsContainsCaller(int uid, String callingPackage) { 5035 Set<WorkSource> requestWs = mActiveModeWarden.getSecondaryRequestWs(); 5036 for (WorkSource ws : requestWs) { 5037 WorkSource reqWs = new WorkSource(ws); 5038 if (reqWs.size() > 1) { 5039 // Remove promoted settings WorkSource if present 5040 reqWs.remove(mFrameworkFacade.getSettingsWorkSource(mContext)); 5041 } 5042 WorkSource withCaller = new WorkSource(reqWs); 5043 withCaller.add(new WorkSource(uid, callingPackage)); 5044 if (reqWs.equals(withCaller)) { 5045 return true; 5046 } 5047 } 5048 return false; 5049 } 5050 5051 /** 5052 * Return the results of the most recent access point scan, in the form of 5053 * a list of {@link ScanResult} objects. 5054 * @return the list of results 5055 */ 5056 @Override getScanResults(String callingPackage, String callingFeatureId)5057 @Nullable public ParceledListSlice<ScanResult> getScanResults(String callingPackage, 5058 String callingFeatureId) { 5059 enforceAccessPermission(); 5060 int uid = Binder.getCallingUid(); 5061 long ident = Binder.clearCallingIdentity(); 5062 if (mVerboseLoggingEnabled) { 5063 mLog.info("getScanResults uid=%").c(uid).flush(); 5064 } 5065 try { 5066 mWifiPermissionsUtil.enforceCanAccessScanResults(callingPackage, callingFeatureId, 5067 uid, null); 5068 List<ScanResult> scanResults = mWifiThreadRunner.call( 5069 mScanRequestProxy::getScanResults, Collections.emptyList(), 5070 TAG + "#getScanResults"); 5071 if (scanResults.size() > 200) { 5072 Log.i(TAG, "too many scan results, may break binder transaction"); 5073 } 5074 return new ParceledListSlice<>(scanResults); 5075 } catch (SecurityException e) { 5076 Log.w(TAG, "Permission violation - getScanResults not allowed for uid=" 5077 + uid + ", packageName=" + callingPackage + ", reason=" + e); 5078 return null; 5079 } finally { 5080 Binder.restoreCallingIdentity(ident); 5081 } 5082 } 5083 5084 /** 5085 * See {@link WifiManager#getChannelData(Executor, Consumer)} 5086 */ 5087 @Override 5088 @RequiresApi(Build.VERSION_CODES.TIRAMISU) getChannelData(@onNull IListListener listener, String packageName, Bundle extras)5089 public void getChannelData(@NonNull IListListener listener, String packageName, 5090 Bundle extras) { 5091 if (!SdkLevel.isAtLeastT()) { 5092 throw new UnsupportedOperationException(); 5093 } 5094 if (listener == null) { 5095 throw new IllegalArgumentException("listener should not be null"); 5096 } 5097 mWifiPermissionsUtil.enforceNearbyDevicesPermission( 5098 extras.getParcelable(WifiManager.EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE), false, 5099 TAG + " getChannelData"); 5100 mWifiThreadRunner.post(() -> { 5101 try { 5102 listener.onResult(getChannelDataInternal()); 5103 } catch (RemoteException e) { 5104 Log.e(TAG, e.getMessage(), e); 5105 } 5106 }, TAG + "#getChannelData"); 5107 } 5108 getChannelDataInternal()5109 private List<Bundle> getChannelDataInternal() { 5110 SparseIntArray dataSparseIntArray = new SparseIntArray(); 5111 List<ScanResult> scanResults = mScanRequestProxy.getScanResults(); 5112 if (scanResults != null) { 5113 for (ScanResult scanResultItem : scanResults) { 5114 if (scanResultItem.level >= CHANNEL_USAGE_WEAK_SCAN_RSSI_DBM) { 5115 dataSparseIntArray.put(scanResultItem.frequency, 5116 dataSparseIntArray.get(scanResultItem.frequency, 0) + 1); 5117 } 5118 } 5119 } 5120 5121 List<Bundle> dataArray = new ArrayList<>(); 5122 for (int i = 0; i < dataSparseIntArray.size(); i++) { 5123 Bundle dataBundle = new Bundle(); 5124 dataBundle.putInt(CHANNEL_DATA_KEY_FREQUENCY_MHZ, dataSparseIntArray.keyAt(i)); 5125 dataBundle.putInt(CHANNEL_DATA_KEY_NUM_AP, dataSparseIntArray.valueAt(i)); 5126 dataArray.add(dataBundle); 5127 } 5128 return dataArray; 5129 } 5130 5131 /** 5132 * Return the filtered ScanResults which may be authenticated by the suggested network 5133 * configurations. 5134 * @return The map of {@link WifiNetworkSuggestion} and the list of {@link ScanResult} which 5135 * may be authenticated by the corresponding network configuration. 5136 */ 5137 @Override 5138 @NonNull getMatchingScanResults( @onNull ParceledListSlice<WifiNetworkSuggestion> networkSuggestions, @Nullable ParceledListSlice<ScanResult> scanResults, String callingPackage, String callingFeatureId)5139 public Map<WifiNetworkSuggestion, List<ScanResult>> getMatchingScanResults( 5140 @NonNull ParceledListSlice<WifiNetworkSuggestion> networkSuggestions, 5141 @Nullable ParceledListSlice<ScanResult> scanResults, 5142 String callingPackage, String callingFeatureId) { 5143 enforceAccessPermission(); 5144 int uid = Binder.getCallingUid(); 5145 long ident = Binder.clearCallingIdentity(); 5146 if (networkSuggestions == null || networkSuggestions.getList() == null) { 5147 throw new IllegalArgumentException("networkSuggestions must not be null."); 5148 } 5149 try { 5150 mWifiPermissionsUtil.enforceCanAccessScanResults(callingPackage, callingFeatureId, 5151 uid, null); 5152 5153 return mWifiThreadRunner.call( 5154 () -> { 5155 if (scanResults == null 5156 || !ScanResultUtil.validateScanResultList(scanResults.getList())) { 5157 return mWifiNetworkSuggestionsManager.getMatchingScanResults( 5158 networkSuggestions.getList(), 5159 mScanRequestProxy.getScanResults()); 5160 } else { 5161 return mWifiNetworkSuggestionsManager.getMatchingScanResults( 5162 networkSuggestions.getList(), scanResults.getList()); 5163 } 5164 }, 5165 Collections.emptyMap(), TAG + "#getMatchingScanResults"); 5166 } catch (SecurityException e) { 5167 Log.w(TAG, "Permission violation - getMatchingScanResults not allowed for uid=" 5168 + uid + ", packageName=" + callingPackage + ", reason + e"); 5169 } finally { 5170 Binder.restoreCallingIdentity(ident); 5171 } 5172 5173 return Collections.emptyMap(); 5174 } 5175 5176 /** 5177 * Add or update a Passpoint configuration. 5178 * 5179 * @param config The Passpoint configuration to be added 5180 * @return true on success or false on failure 5181 */ 5182 @Override 5183 public boolean addOrUpdatePasspointConfiguration( 5184 PasspointConfiguration config, String packageName) { 5185 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 5186 return false; 5187 } 5188 int callingUid = Binder.getCallingUid(); 5189 mWifiPermissionsUtil.checkPackage(callingUid, packageName); 5190 if (!isTargetSdkLessThanROrPrivileged( 5191 packageName, Binder.getCallingPid(), callingUid)) { 5192 mLog.info("addOrUpdatePasspointConfiguration not allowed for uid=%") 5193 .c(callingUid).flush(); 5194 return false; 5195 } 5196 long ident = Binder.clearCallingIdentity(); 5197 try { 5198 if (SdkLevel.isAtLeastT() && mUserManager.hasUserRestrictionForUser( 5199 UserManager.DISALLOW_ADD_WIFI_CONFIG, 5200 UserHandle.getUserHandleForUid(callingUid)) 5201 && !mWifiPermissionsUtil.isAdmin(callingUid, packageName)) { 5202 mLog.info("addOrUpdatePasspointConfiguration only allowed for admin" 5203 + "when the DISALLOW_ADD_WIFI_CONFIG user restriction is set").flush(); 5204 return false; 5205 } 5206 } finally { 5207 Binder.restoreCallingIdentity(ident); 5208 } 5209 mLog.info("addorUpdatePasspointConfiguration uid=%").c(callingUid).flush(); 5210 return mWifiThreadRunner.call( 5211 () -> { 5212 boolean success = mPasspointManager.addOrUpdateProvider(config, callingUid, 5213 packageName, false, true, false); 5214 if (success && TextUtils.equals(CERT_INSTALLER_PKG, packageName)) { 5215 int networkId = mActiveModeWarden.getConnectionInfo().getNetworkId(); 5216 WifiConfiguration currentConfig = 5217 mWifiConfigManager.getConfiguredNetworkWithPassword(networkId); 5218 if (currentConfig != null 5219 && !currentConfig.getNetworkSelectionStatus() 5220 .hasNeverDetectedCaptivePortal()) { 5221 mActiveModeWarden.getPrimaryClientModeManager().disconnect(); 5222 } 5223 } 5224 return success; 5225 }, false, TAG + "#addOrUpdatePasspointConfiguration"); 5226 } 5227 5228 /** 5229 * Remove the Passpoint configuration identified by its FQDN (Fully Qualified Domain Name). 5230 * 5231 * @param fqdn The FQDN of the Passpoint configuration to be removed 5232 * @return true on success or false on failure 5233 */ 5234 @Override 5235 public boolean removePasspointConfiguration(String fqdn, String packageName) { 5236 mWifiPermissionsUtil.checkPackage(Binder.getCallingUid(), packageName); 5237 return removePasspointConfigurationInternal(fqdn, null); 5238 } 5239 5240 /** 5241 * Remove a Passpoint profile based on either FQDN (multiple matching profiles) or a unique 5242 * identifier (one matching profile). 5243 * 5244 * @param fqdn The FQDN of the Passpoint configuration to be removed 5245 * @param uniqueId The unique identifier of the Passpoint configuration to be removed 5246 * @return true on success or false on failure 5247 */ 5248 private boolean removePasspointConfigurationInternal(String fqdn, String uniqueId) { 5249 final int uid = Binder.getCallingUid(); 5250 boolean privileged = false; 5251 if (mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) 5252 || mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(uid)) { 5253 privileged = true; 5254 } 5255 mLog.info("removePasspointConfigurationInternal uid=%").c(Binder.getCallingUid()).flush(); 5256 final boolean privilegedFinal = privileged; 5257 return mWifiThreadRunner.call( 5258 () -> mPasspointManager.removeProvider(uid, privilegedFinal, uniqueId, fqdn), 5259 false, TAG + "#removePasspointConfigurationInternal"); 5260 } 5261 5262 /** 5263 * Return the list of the installed Passpoint configurations. 5264 * 5265 * An empty list will be returned when no configuration is installed. 5266 * @param packageName String name of the calling package 5267 * @return A list of {@link PasspointConfiguration}. 5268 */ 5269 @Override 5270 public ParceledListSlice<PasspointConfiguration> getPasspointConfigurations( 5271 String packageName) { 5272 final int uid = Binder.getCallingUid(); 5273 mWifiPermissionsUtil.checkPackage(uid, packageName); 5274 boolean privileged = false; 5275 if (mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) 5276 || mWifiPermissionsUtil.checkNetworkSetupWizardPermission(uid)) { 5277 privileged = true; 5278 } 5279 if (mVerboseLoggingEnabled) { 5280 mLog.info("getPasspointConfigurations uid=%").c(Binder.getCallingUid()).flush(); 5281 } 5282 final boolean privilegedFinal = privileged; 5283 return new ParceledListSlice<>(mWifiThreadRunner.call( 5284 () -> mPasspointManager.getProviderConfigs(uid, privilegedFinal), 5285 Collections.emptyList(), TAG + "#getPasspointConfigurations")); 5286 } 5287 5288 /** 5289 * Query for a Hotspot 2.0 release 2 OSU icon 5290 * @param bssid The BSSID of the AP 5291 * @param fileName Icon file name 5292 */ 5293 @Override 5294 public void queryPasspointIcon(long bssid, String fileName) { 5295 enforceAccessPermission(); 5296 mLog.info("queryPasspointIcon uid=%").c(Binder.getCallingUid()).flush(); 5297 mWifiThreadRunner.post(() -> { 5298 mActiveModeWarden.getPrimaryClientModeManager().syncQueryPasspointIcon(bssid, fileName); 5299 }, TAG + "#queryPasspointIcon"); 5300 } 5301 5302 /** 5303 * Match the currently associated network against the SP matching the given FQDN 5304 * @param fqdn FQDN of the SP 5305 * @return ordinal [HomeProvider, RoamingProvider, Incomplete, None, Declined] 5306 */ 5307 @Override 5308 public int matchProviderWithCurrentNetwork(String fqdn) { 5309 mLog.info("matchProviderWithCurrentNetwork uid=%").c(Binder.getCallingUid()).flush(); 5310 return 0; 5311 } 5312 5313 /** 5314 * see {@link android.net.wifi.WifiManager#addDriverCountryCodeChangedListener( 5315 * WifiManager.OnDriverCountryCodeChangedListener)} 5316 * 5317 * @param listener country code listener to register 5318 * @param packageName Package name of the calling app 5319 * @param featureId The feature in the package 5320 * 5321 * @throws SecurityException if the caller does not have permission to register a callback 5322 * @throws RemoteException if remote exception happens 5323 * @throws IllegalArgumentException if the arguments are null or invalid 5324 */ 5325 @Override 5326 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 5327 public void registerDriverCountryCodeChangedListener(@NonNull 5328 IOnWifiDriverCountryCodeChangedListener listener, @Nullable String packageName, 5329 @Nullable String featureId) { 5330 if (!SdkLevel.isAtLeastT()) { 5331 throw new UnsupportedOperationException(); 5332 } 5333 // verify arguments 5334 if (listener == null) { 5335 throw new IllegalArgumentException("listener must not be null"); 5336 } 5337 int uid = Binder.getCallingUid(); 5338 int pid = Binder.getCallingPid(); 5339 mWifiPermissionsUtil.checkPackage(uid, packageName); 5340 // Allow to register if caller owns location permission in the manifest. 5341 enforceLocationPermissionInManifest(uid, true /* isCoarseOnly */); 5342 if (mVerboseLoggingEnabled) { 5343 mLog.info("registerDriverCountryCodeChangedListener uid=%") 5344 .c(Binder.getCallingUid()).flush(); 5345 } 5346 5347 // post operation to handler thread 5348 mWifiThreadRunner.post(() -> { 5349 mCountryCodeTracker.registerDriverCountryCodeChangedListener(listener, 5350 new WifiPermissionsUtil.CallerIdentity(uid, pid, packageName, featureId)); 5351 // Update the client about the current driver country code immediately 5352 // after registering if the client owns location permission and global location setting 5353 // is on. 5354 try { 5355 if (mWifiPermissionsUtil.checkCallersCoarseLocationPermission( 5356 packageName, featureId, uid, null)) { 5357 listener.onDriverCountryCodeChanged(mCountryCode.getCurrentDriverCountryCode()); 5358 } else { 5359 Log.i(TAG, "drop to notify to listener (maybe location off?) for" 5360 + " DriverCountryCodeChangedListener, uid=" + uid); 5361 } 5362 } catch (RemoteException e) { 5363 Log.e(TAG, "registerDriverCountryCodeChangedListener: remote exception -- " + e); 5364 } 5365 }, TAG + "#registerDriverCountryCodeChangedListener"); 5366 } 5367 5368 /** 5369 * see {@link android.net.wifi.WifiManager#removeDriverCountryCodeChangedListener(Executor, 5370 * WifiManager.OnDriverCountryCodeChangedListener)} 5371 * 5372 * @param listener country code listener to register 5373 * 5374 * @throws RemoteException if remote exception happens 5375 * @throws IllegalArgumentException if the arguments are null or invalid 5376 */ 5377 @Override 5378 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 5379 public void unregisterDriverCountryCodeChangedListener(@NonNull 5380 IOnWifiDriverCountryCodeChangedListener listener) { 5381 if (!SdkLevel.isAtLeastT()) { 5382 throw new UnsupportedOperationException(); 5383 } 5384 // verify arguments 5385 if (listener == null) { 5386 throw new IllegalArgumentException("listener must not be null"); 5387 } 5388 int uid = Binder.getCallingUid(); 5389 if (mVerboseLoggingEnabled) { 5390 mLog.info("unregisterDriverCountryCodeChangedListener uid=%") 5391 .c(Binder.getCallingUid()).flush(); 5392 } 5393 5394 // post operation to handler thread 5395 mWifiThreadRunner.post(() -> 5396 mCountryCodeTracker.unregisterDriverCountryCodeChangedListener(listener), 5397 TAG + "#unregisterDriverCountryCodeChangedListener"); 5398 } 5399 5400 /** 5401 * Get the country code 5402 * @return Get the best choice country code for wifi, regardless of if it was set or 5403 * not. 5404 * Returns null when there is no country code available. 5405 */ 5406 @Override 5407 public String getCountryCode(String packageName, String featureId) { 5408 int uid = Binder.getCallingUid(); 5409 mWifiPermissionsUtil.checkPackage(uid, packageName); 5410 if (!mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) 5411 && !mWifiPermissionsUtil.checkCallersCoarseLocationPermission( 5412 packageName, featureId, uid, "getCountryCode")) { 5413 throw new SecurityException("Caller has no permission to get country code."); 5414 } 5415 if (mVerboseLoggingEnabled) { 5416 mLog.info("getCountryCode uid=%").c(Binder.getCallingUid()).flush(); 5417 } 5418 return mCountryCode.getCountryCode(); 5419 } 5420 5421 /** 5422 * Set the Wifi country code. This call will override the country code set by telephony. 5423 * @param countryCode A 2-Character alphanumeric country code. 5424 * 5425 */ 5426 @RequiresApi(Build.VERSION_CODES.S) 5427 @Override 5428 public void setOverrideCountryCode(@NonNull String countryCode) { 5429 if (!SdkLevel.isAtLeastS()) { 5430 throw new UnsupportedOperationException(); 5431 } 5432 mContext.enforceCallingOrSelfPermission( 5433 Manifest.permission.MANAGE_WIFI_COUNTRY_CODE, "WifiService"); 5434 if (!WifiCountryCode.isValid(countryCode)) { 5435 throw new IllegalArgumentException("Country code must be a 2-Character alphanumeric" 5436 + " code. But got countryCode " + countryCode 5437 + " instead"); 5438 } 5439 if (mVerboseLoggingEnabled) { 5440 mLog.info("setOverrideCountryCode uid=% countryCode=%") 5441 .c(Binder.getCallingUid()).c(countryCode).flush(); 5442 } 5443 // Post operation to handler thread 5444 mWifiThreadRunner.post(() -> mCountryCode.setOverrideCountryCode(countryCode), 5445 TAG + "#setOverrideCountryCode"); 5446 } 5447 5448 /** 5449 * Clear the country code previously set through setOverrideCountryCode method. 5450 * 5451 */ 5452 @RequiresApi(Build.VERSION_CODES.S) 5453 @Override 5454 public void clearOverrideCountryCode() { 5455 if (!SdkLevel.isAtLeastS()) { 5456 throw new UnsupportedOperationException(); 5457 } 5458 mContext.enforceCallingOrSelfPermission( 5459 Manifest.permission.MANAGE_WIFI_COUNTRY_CODE, "WifiService"); 5460 if (mVerboseLoggingEnabled) { 5461 mLog.info("clearCountryCode uid=%").c(Binder.getCallingUid()).flush(); 5462 } 5463 // Post operation to handler thread 5464 mWifiThreadRunner.post(() -> mCountryCode.clearOverrideCountryCode(), 5465 TAG + "#clearOverrideCountryCode"); 5466 } 5467 5468 /** 5469 * Change the default country code previously set from ro.boot.wificountrycode. 5470 * @param countryCode A 2-Character alphanumeric country code. 5471 * 5472 */ 5473 @RequiresApi(Build.VERSION_CODES.S) 5474 @Override 5475 public void setDefaultCountryCode(@NonNull String countryCode) { 5476 if (!SdkLevel.isAtLeastS()) { 5477 throw new UnsupportedOperationException(); 5478 } 5479 mContext.enforceCallingOrSelfPermission( 5480 Manifest.permission.MANAGE_WIFI_COUNTRY_CODE, "WifiService"); 5481 if (!WifiCountryCode.isValid(countryCode)) { 5482 throw new IllegalArgumentException("Country code must be a 2-Character alphanumeric" 5483 + " code. But got countryCode " + countryCode 5484 + " instead"); 5485 } 5486 if (mVerboseLoggingEnabled) { 5487 mLog.info("setDefaultCountryCode uid=% countryCode=%") 5488 .c(Binder.getCallingUid()).c(countryCode).flush(); 5489 } 5490 // Post operation to handler thread 5491 mWifiThreadRunner.post(() -> mCountryCode.setDefaultCountryCode(countryCode), 5492 TAG + "#setDefaultCountryCode"); 5493 } 5494 5495 @Override 5496 public boolean is24GHzBandSupported() { 5497 if (mVerboseLoggingEnabled) { 5498 mLog.info("is24GHzBandSupported uid=%").c(Binder.getCallingUid()).flush(); 5499 } 5500 5501 return is24GhzBandSupportedInternal(); 5502 } 5503 5504 private boolean is24GhzBandSupportedInternal() { 5505 if (mResourceCache.getBoolean(R.bool.config_wifi24ghzSupport)) { 5506 return true; 5507 } 5508 return mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_24_GHZ); 5509 } 5510 5511 5512 @Override 5513 public boolean is5GHzBandSupported() { 5514 if (mVerboseLoggingEnabled) { 5515 mLog.info("is5GHzBandSupported uid=%").c(Binder.getCallingUid()).flush(); 5516 } 5517 5518 return is5GhzBandSupportedInternal(); 5519 } 5520 5521 private boolean is5GhzBandSupportedInternal() { 5522 if (mResourceCache.getBoolean(R.bool.config_wifi5ghzSupport)) { 5523 return true; 5524 } 5525 return mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_5_GHZ); 5526 } 5527 5528 @Override 5529 public boolean is6GHzBandSupported() { 5530 if (mVerboseLoggingEnabled) { 5531 mLog.info("is6GHzBandSupported uid=%").c(Binder.getCallingUid()).flush(); 5532 } 5533 5534 return is6GhzBandSupportedInternal(); 5535 } 5536 5537 private boolean is6GhzBandSupportedInternal() { 5538 if (mResourceCache.getBoolean(R.bool.config_wifi6ghzSupport)) { 5539 return true; 5540 } 5541 return mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_6_GHZ); 5542 } 5543 5544 @Override 5545 public boolean is60GHzBandSupported() { 5546 if (!SdkLevel.isAtLeastS()) { 5547 throw new UnsupportedOperationException(); 5548 } 5549 5550 if (mVerboseLoggingEnabled) { 5551 mLog.info("is60GHzBandSupported uid=%").c(Binder.getCallingUid()).flush(); 5552 } 5553 5554 return is60GhzBandSupportedInternal(); 5555 } 5556 5557 private boolean is60GhzBandSupportedInternal() { 5558 if (mResourceCache.getBoolean(R.bool.config_wifi60ghzSupport)) { 5559 return true; 5560 } 5561 return mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_60_GHZ); 5562 } 5563 5564 @Override 5565 public boolean isWifiStandardSupported(@WifiStandard int standard) { 5566 return mWifiThreadRunner.call( 5567 () -> mActiveModeWarden.getPrimaryClientModeManager().isWifiStandardSupported( 5568 standard), false, TAG + "#isWifiStandardSupported"); 5569 } 5570 5571 /** 5572 * Return the DHCP-assigned addresses from the last successful DHCP request, 5573 * if any. 5574 * @return the DHCP information 5575 * @deprecated 5576 */ 5577 @Override 5578 public DhcpInfo getDhcpInfo(@NonNull String packageName) { 5579 enforceAccessPermission(); 5580 int callingUid = Binder.getCallingUid(); 5581 mWifiPermissionsUtil.checkPackage(callingUid, packageName); 5582 if (mVerboseLoggingEnabled) { 5583 mLog.info("getDhcpInfo uid=%").c(callingUid).flush(); 5584 } 5585 DhcpResultsParcelable dhcpResults = mWifiThreadRunner.call( 5586 () -> getClientModeManagerIfSecondaryCmmRequestedByCallerPresent( 5587 callingUid, packageName) 5588 .syncGetDhcpResultsParcelable(), new DhcpResultsParcelable(), 5589 TAG + "#getDhcpInfo"); 5590 5591 DhcpInfo info = new DhcpInfo(); 5592 5593 if (dhcpResults.baseConfiguration != null) { 5594 if (dhcpResults.baseConfiguration.getIpAddress() != null 5595 && dhcpResults.baseConfiguration.getIpAddress().getAddress() 5596 instanceof Inet4Address) { 5597 info.ipAddress = Inet4AddressUtils.inet4AddressToIntHTL( 5598 (Inet4Address) dhcpResults.baseConfiguration.getIpAddress().getAddress()); 5599 } 5600 5601 if (dhcpResults.baseConfiguration.getGateway() != null) { 5602 info.gateway = Inet4AddressUtils.inet4AddressToIntHTL( 5603 (Inet4Address) dhcpResults.baseConfiguration.getGateway()); 5604 } 5605 5606 int dnsFound = 0; 5607 for (InetAddress dns : dhcpResults.baseConfiguration.getDnsServers()) { 5608 if (dns instanceof Inet4Address) { 5609 if (dnsFound == 0) { 5610 info.dns1 = Inet4AddressUtils.inet4AddressToIntHTL((Inet4Address) dns); 5611 } else { 5612 info.dns2 = Inet4AddressUtils.inet4AddressToIntHTL((Inet4Address) dns); 5613 } 5614 if (++dnsFound > 1) break; 5615 } 5616 } 5617 } 5618 String serverAddress = dhcpResults.serverAddress; 5619 if (serverAddress != null) { 5620 InetAddress serverInetAddress = InetAddresses.parseNumericAddress(serverAddress); 5621 info.serverAddress = 5622 Inet4AddressUtils.inet4AddressToIntHTL((Inet4Address) serverInetAddress); 5623 } 5624 info.leaseDuration = dhcpResults.leaseDuration; 5625 5626 return info; 5627 } 5628 5629 /** 5630 * enable TDLS for the local NIC to remote NIC 5631 * The APPs don't know the remote MAC address to identify NIC though, 5632 * so we need to do additional work to find it from remote IP address 5633 */ 5634 5635 private static class TdlsTaskParams { 5636 String mRemoteIpAddress; 5637 boolean mEnable; 5638 } 5639 5640 private class TdlsTask extends AsyncTask<TdlsTaskParams, Integer, Integer> { 5641 @Override 5642 protected Integer doInBackground(TdlsTaskParams... params) { 5643 5644 // Retrieve parameters for the call 5645 TdlsTaskParams param = params[0]; 5646 String remoteIpAddress = param.mRemoteIpAddress.trim(); 5647 boolean enable = param.mEnable; 5648 5649 // Get MAC address of Remote IP 5650 String macAddress = null; 5651 5652 try (BufferedReader reader = new BufferedReader(new FileReader("/proc/net/arp"))) { 5653 // Skip over the line bearing column titles 5654 reader.readLine(); 5655 5656 String line; 5657 while ((line = reader.readLine()) != null) { 5658 String[] tokens = line.split("[ ]+"); 5659 if (tokens.length < 6) { 5660 continue; 5661 } 5662 5663 // ARP column format is 5664 // Address HWType HWAddress Flags Mask IFace 5665 String ip = tokens[0]; 5666 String mac = tokens[3]; 5667 5668 if (TextUtils.equals(remoteIpAddress, ip)) { 5669 macAddress = mac; 5670 break; 5671 } 5672 } 5673 5674 if (macAddress == null) { 5675 Log.w(TAG, "Did not find remoteAddress {" + remoteIpAddress + "} in " 5676 + "/proc/net/arp"); 5677 } else { 5678 enableTdlsWithMacAddress(macAddress, enable); 5679 } 5680 5681 } catch (FileNotFoundException e) { 5682 Log.e(TAG, "Could not open /proc/net/arp to lookup mac address"); 5683 } catch (IOException e) { 5684 Log.e(TAG, "Could not read /proc/net/arp to lookup mac address"); 5685 } 5686 return 0; 5687 } 5688 } 5689 5690 @Override 5691 public void enableTdls(String remoteAddress, boolean enable) { 5692 if (remoteAddress == null) { 5693 throw new IllegalArgumentException("remoteAddress cannot be null"); 5694 } 5695 mLog.info("enableTdls uid=% enable=%").c(Binder.getCallingUid()).c(enable).flush(); 5696 TdlsTaskParams params = new TdlsTaskParams(); 5697 params.mRemoteIpAddress = remoteAddress; 5698 params.mEnable = enable; 5699 mLastCallerInfoManager.put(WifiManager.API_SET_TDLS_ENABLED, Process.myTid(), 5700 Binder.getCallingUid(), Binder.getCallingPid(), "<unknown>", enable); 5701 new TdlsTask().execute(params); 5702 } 5703 5704 /** 5705 * See {@link WifiManager#setTdlsEnabled(InetAddress, boolean, Executor, Consumer)} 5706 */ 5707 @Override 5708 public void enableTdlsWithRemoteIpAddress(String remoteAddress, boolean enable, 5709 @NonNull IBooleanListener listener) { 5710 if (remoteAddress == null) { 5711 throw new NullPointerException("remoteAddress cannot be null"); 5712 } 5713 if (listener == null) { 5714 throw new NullPointerException("listener should not be null"); 5715 } 5716 5717 mLog.info("enableTdlsWithRemoteIpAddress uid=% enable=%") 5718 .c(Binder.getCallingUid()).c(enable).flush(); 5719 mLastCallerInfoManager.put(WifiManager.API_SET_TDLS_ENABLED, 5720 Process.myTid(), Binder.getCallingUid(), Binder.getCallingPid(), "<unknown>", 5721 enable); 5722 5723 mWifiThreadRunner.post(() -> { 5724 try { 5725 listener.onResult( 5726 mActiveModeWarden.getPrimaryClientModeManager() 5727 .enableTdlsWithRemoteIpAddress(remoteAddress, enable)); 5728 } catch (RemoteException e) { 5729 Log.e(TAG, e.getMessage(), e); 5730 } 5731 }, TAG + "#enableTdlsWithRemoteIpAddress"); 5732 } 5733 5734 @Override 5735 public void enableTdlsWithMacAddress(String remoteMacAddress, boolean enable) { 5736 mLog.info("enableTdlsWithMacAddress uid=% enable=%") 5737 .c(Binder.getCallingUid()) 5738 .c(enable) 5739 .flush(); 5740 if (remoteMacAddress == null) { 5741 throw new IllegalArgumentException("remoteMacAddress cannot be null"); 5742 } 5743 mLastCallerInfoManager.put(WifiManager.API_SET_TDLS_ENABLED_WITH_MAC_ADDRESS, 5744 Process.myTid(), Binder.getCallingUid(), Binder.getCallingPid(), "<unknown>", 5745 enable); 5746 mWifiThreadRunner.post(() -> 5747 mActiveModeWarden.getPrimaryClientModeManager().enableTdls( 5748 remoteMacAddress, enable), TAG + "#enableTdlsWithMacAddress"); 5749 } 5750 5751 /** 5752 * See {@link WifiManager#setTdlsEnabledWithMacAddress(String, boolean, Executor, Consumer)} 5753 */ 5754 @Override 5755 public void enableTdlsWithRemoteMacAddress(String remoteMacAddress, boolean enable, 5756 @NonNull IBooleanListener listener) { 5757 if (remoteMacAddress == null) { 5758 throw new NullPointerException("remoteAddress cannot be null"); 5759 } 5760 if (listener == null) { 5761 throw new NullPointerException("listener should not be null"); 5762 } 5763 5764 mLog.info("enableTdlsWithRemoteMacAddress uid=% enable=%") 5765 .c(Binder.getCallingUid()).c(enable).flush(); 5766 mLastCallerInfoManager.put( 5767 WifiManager.API_SET_TDLS_ENABLED_WITH_MAC_ADDRESS, 5768 Process.myTid(), Binder.getCallingUid(), Binder.getCallingPid(), "<unknown>", 5769 enable); 5770 5771 mWifiThreadRunner.post(() -> { 5772 try { 5773 listener.onResult( 5774 mActiveModeWarden.getPrimaryClientModeManager() 5775 .enableTdls(remoteMacAddress, enable)); 5776 } catch (RemoteException e) { 5777 Log.e(TAG, e.getMessage(), e); 5778 } 5779 }, TAG + "#enableTdlsWithRemoteMacAddress"); 5780 } 5781 5782 /** 5783 * See {@link WifiManager#isTdlsOperationCurrentlyAvailable(Executor, Consumer)} 5784 */ 5785 @Override 5786 public void isTdlsOperationCurrentlyAvailable(@NonNull IBooleanListener listener) { 5787 if (listener == null) { 5788 throw new NullPointerException("listener should not be null"); 5789 } 5790 mWifiThreadRunner.post(() -> { 5791 try { 5792 listener.onResult( 5793 mActiveModeWarden.getPrimaryClientModeManager() 5794 .isTdlsOperationCurrentlyAvailable()); 5795 } catch (RemoteException e) { 5796 Log.e(TAG, e.getMessage(), e); 5797 } 5798 }, TAG + "#isTdlsOperationCurrentlyAvailable"); 5799 } 5800 5801 /** 5802 * See {@link WifiManager#getMaxSupportedConcurrentTdlsSessions(Executor, Consumer)} 5803 */ 5804 @Override 5805 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 5806 public void getMaxSupportedConcurrentTdlsSessions(@NonNull IIntegerListener listener) { 5807 if (!SdkLevel.isAtLeastU()) { 5808 throw new UnsupportedOperationException("SDK level too old"); 5809 } 5810 if (listener == null) { 5811 throw new NullPointerException("listener should not be null"); 5812 } 5813 mWifiThreadRunner.post(() -> { 5814 try { 5815 listener.onResult( 5816 mActiveModeWarden.getPrimaryClientModeManager() 5817 .getMaxSupportedConcurrentTdlsSessions()); 5818 } catch (RemoteException e) { 5819 Log.e(TAG, e.getMessage(), e); 5820 } 5821 }, TAG + "#getMaxSupportedConcurrentTdlsSessions"); 5822 } 5823 5824 /** 5825 * See {@link WifiManager#getNumberOfEnabledTdlsSessions(Executor, Consumer)} 5826 */ 5827 @Override 5828 public void getNumberOfEnabledTdlsSessions(@NonNull IIntegerListener listener) { 5829 if (listener == null) { 5830 throw new NullPointerException("listener should not be null"); 5831 } 5832 mWifiThreadRunner.post(() -> { 5833 try { 5834 listener.onResult( 5835 mActiveModeWarden.getPrimaryClientModeManager() 5836 .getNumberOfEnabledTdlsSessions()); 5837 } catch (RemoteException e) { 5838 Log.e(TAG, e.getMessage(), e); 5839 } 5840 }, TAG + "#getNumberOfEnabledTdlsSessions"); 5841 } 5842 5843 /** 5844 * Temporarily disable a network, should be trigger when user disconnect a network 5845 */ 5846 @Override 5847 public void disableEphemeralNetwork(String network, String packageName) { 5848 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE, 5849 "WifiService"); 5850 int callingUid = Binder.getCallingUid(); 5851 mWifiPermissionsUtil.checkPackage(callingUid, packageName); 5852 if (!isPrivileged(Binder.getCallingPid(), callingUid)) { 5853 mLog.info("disableEphemeralNetwork not allowed for uid=%").c(callingUid).flush(); 5854 return; 5855 } 5856 mLog.info("disableEphemeralNetwork uid=%").c(callingUid).flush(); 5857 mWifiThreadRunner.post(() -> mWifiConfigManager.userTemporarilyDisabledNetwork(network, 5858 callingUid), TAG + "#disableEphemeralNetwork"); 5859 } 5860 5861 private void removeAppStateInternal(int uid, @NonNull String pkgName) { 5862 ApplicationInfo ai = new ApplicationInfo(); 5863 ai.packageName = pkgName; 5864 ai.uid = uid; 5865 mWifiConfigManager.removeNetworksForApp(ai); 5866 mScanRequestProxy.clearScanRequestTimestampsForApp(pkgName, uid); 5867 5868 // Remove all suggestions from the package. 5869 mWifiNetworkSuggestionsManager.removeApp(pkgName); 5870 mWifiInjector.getWifiNetworkFactory().removeApp(pkgName); 5871 5872 // Remove all Passpoint profiles from package. 5873 mWifiInjector.getPasspointManager().removePasspointProviderWithPackage( 5874 pkgName); 5875 } 5876 5877 private void registerForBroadcasts() { 5878 IntentFilter intentFilter = new IntentFilter(); 5879 intentFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED); 5880 intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); 5881 intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 5882 intentFilter.addDataScheme("package"); 5883 mContext.registerReceiver( 5884 new BroadcastReceiver() { 5885 @Override 5886 public void onReceive(Context context, Intent intent) { 5887 final String action = intent.getAction(); 5888 if (action == null) { 5889 return; 5890 } 5891 int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); 5892 Uri uri = intent.getData(); 5893 if (uid == -1 || uri == null) { 5894 Log.e(TAG, "Uid or Uri is missing for action:" + action); 5895 return; 5896 } 5897 String pkgName = uri.getSchemeSpecificPart(); 5898 PackageManager pm = context.getPackageManager(); 5899 PackageInfo packageInfo = null; 5900 try { 5901 packageInfo = pm.getPackageInfo(pkgName, 0); 5902 } catch (PackageManager.NameNotFoundException e) { 5903 Log.w(TAG, "Couldn't get PackageInfo for package:" + pkgName); 5904 } 5905 // If app is updating or replacing, just ignore 5906 if (Intent.ACTION_PACKAGE_REMOVED.equals(action) 5907 && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { 5908 return; 5909 } 5910 // If package is not removed or disabled, just ignore. 5911 if (packageInfo != null 5912 && packageInfo.applicationInfo != null 5913 && packageInfo.applicationInfo.enabled) { 5914 return; 5915 } 5916 Log.d(TAG, "Remove settings for package:" + pkgName); 5917 removeAppStateInternal(uid, pkgName); 5918 } 5919 }, 5920 intentFilter, 5921 null, 5922 new Handler(mWifiHandlerThread.getLooper())); 5923 } 5924 5925 private void registerForCarrierConfigChange() { 5926 IntentFilter filter = new IntentFilter(); 5927 filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); 5928 mContext.registerReceiver( 5929 new BroadcastReceiver() { 5930 @Override 5931 public void onReceive(Context context, Intent intent) { 5932 final int subId = SubscriptionManager.getActiveDataSubscriptionId(); 5933 Log.d(TAG, "ACTION_CARRIER_CONFIG_CHANGED, active subId: " + subId); 5934 // Tether mode only since carrier requirement only for tethered SoftAp. 5935 mTetheredSoftApTracker 5936 .updateSoftApCapabilityWhenCarrierConfigChanged(subId); 5937 mActiveModeWarden.updateSoftApCapability( 5938 mTetheredSoftApTracker.getSoftApCapability(), 5939 WifiManager.IFACE_IP_MODE_TETHERED); 5940 } 5941 }, 5942 filter, 5943 null, 5944 new Handler(mWifiHandlerThread.getLooper())); 5945 5946 WifiPhoneStateListener phoneStateListener = new WifiPhoneStateListener( 5947 mWifiHandlerThread.getLooper()); 5948 5949 mContext.getSystemService(TelephonyManager.class).listen( 5950 phoneStateListener, PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE); 5951 } 5952 5953 @Override 5954 public int handleShellCommand(@NonNull ParcelFileDescriptor in, 5955 @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err, 5956 @NonNull String[] args) { 5957 if (!mIsBootComplete) { 5958 Log.w(TAG, "Received shell command when boot is not complete!"); 5959 return -1; 5960 } 5961 5962 WifiShellCommand shellCommand = mWifiInjector.makeWifiShellCommand(this); 5963 return shellCommand.exec(this, in.getFileDescriptor(), out.getFileDescriptor(), 5964 err.getFileDescriptor(), args); 5965 } 5966 5967 5968 private void updateWifiMetrics() { 5969 mWifiMetrics.updateSavedNetworks(mWifiConfigManager.getSavedNetworks(WIFI_UID)); 5970 mActiveModeWarden.updateMetrics(); 5971 mPasspointManager.updateMetrics(); 5972 boolean isNonPersistentMacRandEnabled = mFrameworkFacade.getIntegerSetting(mContext, 5973 WifiConfigManager.NON_PERSISTENT_MAC_RANDOMIZATION_FEATURE_FORCE_ENABLE_FLAG, 0) 5974 == 1 ? true : false; 5975 mWifiMetrics.setNonPersistentMacRandomizationForceEnabled(isNonPersistentMacRandEnabled); 5976 mWifiMetrics.setIsScanningAlwaysEnabled( 5977 mSettingsStore.isScanAlwaysAvailableToggleEnabled()); 5978 mWifiMetrics.setVerboseLoggingEnabled(mVerboseLoggingEnabled); 5979 mWifiMetrics.setWifiWakeEnabled(mWifiInjector.getWakeupController().isEnabled()); 5980 } 5981 5982 @Override 5983 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 5984 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 5985 != PERMISSION_GRANTED) { 5986 pw.println("Permission Denial: can't dump WifiService from from pid=" 5987 + Binder.getCallingPid() 5988 + ", uid=" + Binder.getCallingUid()); 5989 return; 5990 } 5991 if (!mIsWifiServiceStarted) { 5992 pw.println("Wifi Service is not started. no dump available"); 5993 return; 5994 } 5995 mWifiThreadRunner.run(() -> { 5996 String arg0 = args != null && args.length > 0 ? args[0] : null; 5997 if (WifiMetrics.PROTO_DUMP_ARG.equals(arg0)) { 5998 // WifiMetrics proto bytes were requested. Dump only these. 5999 updateWifiMetrics(); 6000 mWifiMetrics.dump(fd, pw, args); 6001 } else if (IpClientUtil.DUMP_ARG.equals(arg0)) { 6002 // IpClient dump was requested. Pass it along and take no further action. 6003 String[] ipClientArgs = new String[args.length - 1]; 6004 System.arraycopy(args, 1, ipClientArgs, 0, ipClientArgs.length); 6005 mActiveModeWarden.getPrimaryClientModeManager().dumpIpClient(fd, pw, ipClientArgs); 6006 } else if (WifiScoreReport.DUMP_ARG.equals(arg0)) { 6007 mActiveModeWarden.getPrimaryClientModeManager().dumpWifiScoreReport(fd, pw, args); 6008 } else if (WifiScoreCard.DUMP_ARG.equals(arg0)) { 6009 WifiScoreCard wifiScoreCard = mWifiInjector.getWifiScoreCard(); 6010 String networkListBase64 = wifiScoreCard.getNetworkListBase64(true); 6011 pw.println(networkListBase64); 6012 } else { 6013 pw.println("Verbose logging is " + (mVerboseLoggingEnabled ? "on" : "off")); 6014 pw.println("mVerboseLoggingLevel " + mVerboseLoggingLevel); 6015 pw.println("Stay-awake conditions: " + mFacade.getIntegerSetting( 6016 mContext, Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0)); 6017 pw.println("mInIdleMode " + mInIdleMode); 6018 pw.println("mScanPending " + mScanPending); 6019 pw.println("SupportedFeatures: " + getSupportedFeaturesString()); 6020 pw.println("SettingsStore:"); 6021 mSettingsStore.dump(fd, pw, args); 6022 mActiveModeWarden.dump(fd, pw, args); 6023 mMakeBeforeBreakManager.dump(fd, pw, args); 6024 pw.println(); 6025 mWifiInjector.getInterfaceConflictManager().dump(fd, pw, args); 6026 pw.println(); 6027 mWifiTrafficPoller.dump(fd, pw, args); 6028 pw.println(); 6029 pw.println("Locks held:"); 6030 mWifiLockManager.dump(pw); 6031 pw.println(); 6032 mWifiMulticastLockManager.dump(pw); 6033 pw.println(); 6034 WifiScoreCard wifiScoreCard = mWifiInjector.getWifiScoreCard(); 6035 String networkListBase64 = wifiScoreCard.getNetworkListBase64(true); 6036 pw.println("WifiScoreCard:"); 6037 pw.println(networkListBase64); 6038 6039 updateWifiMetrics(); 6040 mWifiMetrics.dump(fd, pw, args); 6041 6042 pw.println(); 6043 mWifiNetworkSuggestionsManager.dump(fd, pw, args); 6044 pw.println(); 6045 mWifiBackupRestore.dump(fd, pw, args); 6046 pw.println(); 6047 mBackupRestoreController.dump(fd, pw, args); 6048 pw.println(); 6049 pw.println("ScoringParams: " + mWifiInjector.getScoringParams()); 6050 pw.println(); 6051 mSettingsConfigStore.dump(fd, pw, args); 6052 pw.println(); 6053 mCountryCode.dump(fd, pw, args); 6054 mWifiInjector.getWifiNetworkFactory().dump(fd, pw, args); 6055 mWifiInjector.getUntrustedWifiNetworkFactory().dump(fd, pw, args); 6056 mWifiInjector.getOemWifiNetworkFactory().dump(fd, pw, args); 6057 mWifiInjector.getRestrictedWifiNetworkFactory().dump(fd, pw, args); 6058 mWifiInjector.getMultiInternetWifiNetworkFactory().dump(fd, pw, args); 6059 mWifiInjector.getSsidTranslator().dump(pw); 6060 pw.println("Wlan Wake Reasons:" + mWifiNative.getWlanWakeReasonCount()); 6061 pw.println(); 6062 mWifiConfigManager.dump(fd, pw, args); 6063 pw.println(); 6064 pw.println("WifiApConfigStore config: " + mWifiApConfigStore.getApConfiguration()); 6065 pw.println(); 6066 mPasspointManager.dump(pw); 6067 mWifiInjector.getPasspointNetworkNominateHelper().dump(pw); 6068 pw.println(); 6069 mWifiInjector.getWifiDiagnostics().captureBugReportData( 6070 WifiDiagnostics.REPORT_REASON_USER_ACTION); 6071 mWifiInjector.getWifiDiagnostics().dump(fd, pw, args); 6072 mWifiConnectivityManager.dump(fd, pw, args); 6073 mWifiHealthMonitor.dump(fd, pw, args); 6074 mWifiScoreCard.dump(fd, pw, args); 6075 mWifiInjector.getWakeupController().dump(fd, pw, args); 6076 mWifiInjector.getWifiLastResortWatchdog().dump(fd, pw, args); 6077 mWifiInjector.getAdaptiveConnectivityEnabledSettingObserver().dump(fd, pw, args); 6078 mWifiInjector.getWifiGlobals().dump(fd, pw, args); 6079 mWifiInjector.getSarManager().dump(fd, pw, args); 6080 pw.println(); 6081 mLastCallerInfoManager.dump(pw); 6082 pw.println(); 6083 mWifiNative.dump(pw); 6084 pw.println(); 6085 mWifiInjector.getWifiRoamingModeManager().dump(fd, pw, args); 6086 if (SdkLevel.isAtLeastV() && mWifiInjector.getWifiVoipDetector() != null) { 6087 pw.println(); 6088 mWifiInjector.getWifiVoipDetector().dump(fd, pw, args); 6089 } 6090 pw.println(); 6091 mResourceCache.dump(pw); 6092 if (mFeatureFlags.wepDisabledInApm() 6093 && mWepNetworkUsageController != null) { 6094 pw.println(); 6095 mWepNetworkUsageController.dump(fd, pw, args); 6096 } 6097 if (mScorerServiceConnection != null) { 6098 pw.println("boundToExternalScorer successfully"); 6099 } else { 6100 pw.println("boundToExternalScorer=failure, lastScorerBindingState=" 6101 + mLastScorerBindingState); 6102 } 6103 } 6104 }, TAG + "#dump"); 6105 } 6106 6107 @Override 6108 public boolean acquireWifiLock(IBinder binder, int lockMode, String tag, WorkSource ws, 6109 @NonNull String packageName, Bundle extras) { 6110 mLog.info("acquireWifiLock uid=% lockMode=% packageName=%") 6111 .c(Binder.getCallingUid()) 6112 .c(lockMode).c(getPackageName(extras)).flush(); 6113 6114 if (packageName == null) { 6115 throw new NullPointerException("Package name should not be null"); 6116 } 6117 6118 // Check on permission to make this call 6119 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null); 6120 6121 // If no UID is provided in worksource, use the calling UID 6122 WorkSource updatedWs = (ws == null || ws.isEmpty()) 6123 ? new WorkSource(Binder.getCallingUid(), packageName) : ws; 6124 6125 if (!WifiLockManager.isValidLockMode(lockMode)) { 6126 throw new IllegalArgumentException("lockMode =" + lockMode); 6127 } 6128 6129 return mWifiThreadRunner.call(() -> 6130 mWifiLockManager.acquireWifiLock(lockMode, tag, binder, updatedWs), false, 6131 TAG + "#acquireWifiLock"); 6132 } 6133 6134 @Override 6135 public void updateWifiLockWorkSource(IBinder binder, WorkSource ws, String packageName, 6136 Bundle extras) { 6137 mLog.info("updateWifiLockWorkSource uid=% package name=%") 6138 .c(Binder.getCallingUid()) 6139 .c(getPackageName(extras)).flush(); 6140 6141 // Check on permission to make this call 6142 mContext.enforceCallingOrSelfPermission( 6143 android.Manifest.permission.UPDATE_DEVICE_STATS, null); 6144 6145 // If no UID is provided in worksource, use the calling UID 6146 WorkSource updatedWs = (ws == null || ws.isEmpty()) 6147 ? new WorkSource(Binder.getCallingUid(), packageName) : ws; 6148 6149 mWifiThreadRunner.run(() -> 6150 mWifiLockManager.updateWifiLockWorkSource(binder, updatedWs), 6151 TAG + "#updateWifiLockWorkSource"); 6152 } 6153 6154 @Override 6155 public boolean releaseWifiLock(IBinder binder) { 6156 mLog.info("releaseWifiLock uid=%").c(Binder.getCallingUid()).flush(); 6157 6158 // Check on permission to make this call 6159 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null); 6160 6161 return mWifiThreadRunner.call(() -> 6162 mWifiLockManager.releaseWifiLock(binder), false, 6163 TAG + "#releaseWifiLock"); 6164 } 6165 6166 @Override 6167 public void initializeMulticastFiltering() { 6168 enforceMulticastChangePermission(); 6169 mLog.info("initializeMulticastFiltering uid=%").c(Binder.getCallingUid()).flush(); 6170 mWifiMulticastLockManager.startFilteringMulticastPackets(); 6171 } 6172 6173 @Override 6174 public void acquireMulticastLock(IBinder binder, String lockTag, String attributionTag, 6175 String packageName) { 6176 enforceMulticastChangePermission(); 6177 int uid = Binder.getCallingUid(); 6178 mLog.info("acquireMulticastLock uid=% lockTag=%").c(uid).c(lockTag).flush(); 6179 mWifiMulticastLockManager.acquireLock(uid, binder, lockTag, attributionTag, packageName); 6180 } 6181 6182 @Override 6183 public void releaseMulticastLock(IBinder binder, String lockTag) { 6184 enforceMulticastChangePermission(); 6185 int uid = Binder.getCallingUid(); 6186 mLog.info("releaseMulticastLock uid=% lockTag=%").c(uid).c(lockTag).flush(); 6187 mWifiMulticastLockManager.releaseLock(uid, binder, lockTag); 6188 } 6189 6190 @Override 6191 public boolean isMulticastEnabled() { 6192 enforceAccessPermission(); 6193 if (mVerboseLoggingEnabled) { 6194 mLog.info("isMulticastEnabled uid=%").c(Binder.getCallingUid()).flush(); 6195 } 6196 return mWifiMulticastLockManager.isMulticastEnabled(); 6197 } 6198 6199 @Override 6200 public void enableVerboseLogging(int verbose) { 6201 enforceAccessPermission(); 6202 if (!checkNetworkSettingsPermission(Binder.getCallingPid(), Binder.getCallingUid()) 6203 && mContext.checkPermission(android.Manifest.permission.DUMP, 6204 Binder.getCallingPid(), Binder.getCallingUid()) != PERMISSION_GRANTED) { 6205 throw new SecurityException("Caller has neither NETWORK_SETTING nor dump permissions"); 6206 } 6207 mLog.info("enableVerboseLogging uid=% verbose=%") 6208 .c(Binder.getCallingUid()) 6209 .c(verbose).flush(); 6210 boolean enabled = verbose == WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED 6211 || verbose == WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY; 6212 mSettingsConfigStore.put(WIFI_VERBOSE_LOGGING_ENABLED, enabled); 6213 mSettingsConfigStore.put( 6214 WIFI_AWARE_VERBOSE_LOGGING_ENABLED, 6215 enabled || verbose == VERBOSE_LOGGING_LEVEL_WIFI_AWARE_ENABLED_ONLY); 6216 onVerboseLoggingStatusChanged(enabled); 6217 enableVerboseLoggingInternal(verbose); 6218 } 6219 6220 private void onVerboseLoggingStatusChanged(boolean enabled) { 6221 synchronized (mRegisteredWifiLoggingStatusListeners) { 6222 int itemCount = mRegisteredWifiLoggingStatusListeners.beginBroadcast(); 6223 try { 6224 for (int i = 0; i < itemCount; i++) { 6225 try { 6226 mRegisteredWifiLoggingStatusListeners 6227 .getBroadcastItem(i) 6228 .onStatusChanged(enabled); 6229 } catch (RemoteException e) { 6230 Log.e(TAG, "onVerboseLoggingStatusChanged: RemoteException -- ", e); 6231 } 6232 } 6233 } finally { 6234 mRegisteredWifiLoggingStatusListeners.finishBroadcast(); 6235 } 6236 } 6237 } 6238 6239 private void updateVerboseLoggingEnabled() { 6240 final int verboseAlwaysOnLevel = mResourceCache.getInteger( 6241 R.integer.config_wifiVerboseLoggingAlwaysOnLevel); 6242 mVerboseLoggingEnabled = WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED == mVerboseLoggingLevel 6243 || WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY == mVerboseLoggingLevel 6244 || mFrameworkFacade.isVerboseLoggingAlwaysOn(verboseAlwaysOnLevel, 6245 mBuildProperties); 6246 } 6247 6248 private void enableVerboseLoggingInternal(int verboseLoggingLevel) { 6249 if (verboseLoggingLevel == WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY 6250 && mBuildProperties.isUserBuild()) { 6251 throw new SecurityException(TAG + ": Not allowed for the user build."); 6252 } 6253 mVerboseLoggingLevel = verboseLoggingLevel; 6254 6255 // Update wifi globals before sending the verbose logging change. 6256 mWifiThreadRunner.removeCallbacks(mAutoDisableShowKeyVerboseLoggingModeRunnable); 6257 mWifiGlobals.setVerboseLoggingLevel(verboseLoggingLevel); 6258 if (WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY == mVerboseLoggingLevel) { 6259 mWifiThreadRunner.postDelayed(mAutoDisableShowKeyVerboseLoggingModeRunnable, 6260 AUTO_DISABLE_SHOW_KEY_COUNTDOWN_MILLIS, 6261 TAG + "#AutoDisableShowKeyVerboseLoggingMode"); 6262 } 6263 updateVerboseLoggingEnabled(); 6264 final boolean halVerboseEnabled = 6265 WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED == mVerboseLoggingLevel 6266 || WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY 6267 == mVerboseLoggingLevel; 6268 mAfcManager.enableVerboseLogging(mVerboseLoggingEnabled); 6269 mActiveModeWarden.enableVerboseLogging(mVerboseLoggingEnabled); 6270 mWifiLockManager.enableVerboseLogging(mVerboseLoggingEnabled); 6271 mWifiMulticastLockManager.enableVerboseLogging(mVerboseLoggingEnabled); 6272 mWifiInjector.enableVerboseLogging(mVerboseLoggingEnabled, halVerboseEnabled); 6273 mWifiInjector.getSarManager().enableVerboseLogging(mVerboseLoggingEnabled); 6274 mWifiThreadRunner.mVerboseLoggingEnabled = mVerboseLoggingEnabled; 6275 WifiScanner wifiScanner = mWifiInjector.getWifiScanner(); 6276 if (wifiScanner != null) { 6277 wifiScanner.enableVerboseLogging(mVerboseLoggingEnabled); 6278 } 6279 ApConfigUtil.enableVerboseLogging(mVerboseLoggingEnabled); 6280 mApplicationQosPolicyRequestHandler.enableVerboseLogging(mVerboseLoggingEnabled); 6281 mWifiSettingsBackupRestore.enableVerboseLogging(mVerboseLoggingEnabled); 6282 mBackupRestoreController.enableVerboseLogging(mVerboseLoggingEnabled); 6283 if (SdkLevel.isAtLeastV() && mWifiInjector.getWifiVoipDetector() != null) { 6284 mWifiInjector.getWifiVoipDetector().enableVerboseLogging(mVerboseLoggingEnabled); 6285 } 6286 if (mFeatureFlags.wepDisabledInApm() 6287 && mWepNetworkUsageController != null) { 6288 mWepNetworkUsageController.enableVerboseLogging(mVerboseLoggingEnabled); 6289 } 6290 } 6291 6292 @Override 6293 public int getVerboseLoggingLevel() { 6294 if (mVerboseLoggingEnabled) { 6295 mLog.info("getVerboseLoggingLevel uid=%").c(Binder.getCallingUid()).flush(); 6296 } 6297 return mVerboseLoggingLevel; 6298 } 6299 6300 private Runnable mAutoDisableShowKeyVerboseLoggingModeRunnable = new Runnable() { 6301 @Override 6302 public void run() { 6303 // If still enabled, fallback to the regular verbose logging mode. 6304 if (mVerboseLoggingEnabled) { 6305 enableVerboseLoggingInternal(WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED); 6306 } 6307 } 6308 }; 6309 6310 @Override 6311 public void factoryReset(String packageName) { 6312 enforceNetworkSettingsPermission(); 6313 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 6314 return; 6315 } 6316 int callingUid = Binder.getCallingUid(); 6317 mWifiPermissionsUtil.checkPackage(callingUid, packageName); 6318 mLog.info("factoryReset uid=%").c(callingUid).flush(); 6319 long ident = Binder.clearCallingIdentity(); 6320 try { 6321 if (mUserManager.hasUserRestrictionForUser( 6322 UserManager.DISALLOW_NETWORK_RESET, 6323 UserHandle.getUserHandleForUid(callingUid))) { 6324 return; 6325 } 6326 if (!mUserManager.hasUserRestrictionForUser( 6327 UserManager.DISALLOW_CONFIG_TETHERING, 6328 UserHandle.getUserHandleForUid(callingUid))) { 6329 // Turn mobile hotspot off 6330 stopSoftApInternal(WifiManager.IFACE_IP_MODE_UNSPECIFIED); 6331 } 6332 if (mUserManager.hasUserRestrictionForUser( 6333 UserManager.DISALLOW_CONFIG_WIFI, 6334 UserHandle.getUserHandleForUid(callingUid))) { 6335 return; 6336 } 6337 } finally { 6338 Binder.restoreCallingIdentity(ident); 6339 } 6340 // Delete all Wifi SSIDs 6341 mWifiThreadRunner.run(() -> { 6342 List<WifiConfiguration> networks = mWifiConfigManager 6343 .getSavedNetworks(WIFI_UID); 6344 EventLog.writeEvent(0x534e4554, "231985227", -1, 6345 "Remove certs for factory reset"); 6346 for (WifiConfiguration network : networks) { 6347 if (network.isEnterprise()) { 6348 mWifiInjector.getWifiKeyStore().removeKeys(network.enterpriseConfig, true); 6349 } 6350 mWifiConfigManager.removeNetwork(network.networkId, callingUid, packageName); 6351 } 6352 }, TAG + "#factoryReset1"); 6353 // Delete all Passpoint configurations 6354 List<PasspointConfiguration> configs = mWifiThreadRunner.call( 6355 () -> mPasspointManager.getProviderConfigs(WIFI_UID /* ignored */, true), 6356 Collections.emptyList(), TAG + "#factoryReset2"); 6357 for (PasspointConfiguration config : configs) { 6358 removePasspointConfigurationInternal(null, config.getUniqueId()); 6359 } 6360 mWifiThreadRunner.post( 6361 () -> { 6362 // Reset SoftApConfiguration to default configuration 6363 mWifiApConfigStore.setApConfiguration(null); 6364 mPasspointManager.clearAnqpRequestsAndFlushCache(); 6365 mWifiConfigManager.clearUserTemporarilyDisabledList(); 6366 mWifiConfigManager.removeAllEphemeralOrPasspointConfiguredNetworks(); 6367 mWifiInjector.getWifiNetworkFactory().clear(); 6368 mWifiNetworkSuggestionsManager.clear(); 6369 mWifiInjector.getWifiScoreCard().clear(); 6370 mWifiHealthMonitor.clear(); 6371 mWifiCarrierInfoManager.clear(); 6372 notifyFactoryReset(); 6373 mContext.resetResourceCache(); 6374 }, TAG + "#factoryReset3"); 6375 } 6376 6377 /** 6378 * Notify the Factory Reset Event to application who may installed wifi configurations. 6379 */ 6380 private void notifyFactoryReset() { 6381 Intent intent = new Intent(WifiManager.ACTION_NETWORK_SETTINGS_RESET); 6382 6383 // Retrieve list of broadcast receivers for this broadcast & send them directed broadcasts 6384 // to wake them up (if they're in background). 6385 List<ResolveInfo> resolveInfos = 6386 mContext.getPackageManager().queryBroadcastReceiversAsUser( 6387 intent, 0, 6388 UserHandle.of(mWifiInjector.getWifiPermissionsWrapper().getCurrentUser())); 6389 if (resolveInfos == null || resolveInfos.isEmpty()) return; // No need to send broadcast. 6390 6391 for (ResolveInfo resolveInfo : resolveInfos) { 6392 Intent intentToSend = new Intent(intent); 6393 intentToSend.setComponent(new ComponentName( 6394 resolveInfo.activityInfo.applicationInfo.packageName, 6395 resolveInfo.activityInfo.name)); 6396 mContext.sendBroadcastAsUser(intentToSend, UserHandle.CURRENT, 6397 android.Manifest.permission.NETWORK_CARRIER_PROVISIONING); 6398 } 6399 } 6400 6401 @Override 6402 public Network getCurrentNetwork() { 6403 if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { 6404 throw new SecurityException(TAG + ": Permission denied"); 6405 } 6406 if (mVerboseLoggingEnabled) { 6407 mLog.info("getCurrentNetwork uid=%").c(Binder.getCallingUid()).flush(); 6408 } 6409 return mActiveModeWarden.getCurrentNetwork(); 6410 } 6411 6412 public static String toHexString(String s) { 6413 if (s == null) { 6414 return "null"; 6415 } 6416 StringBuilder sb = new StringBuilder(); 6417 sb.append('\'').append(s).append('\''); 6418 for (int n = 0; n < s.length(); n++) { 6419 sb.append(String.format(" %02x", s.charAt(n) & 0xffff)); 6420 } 6421 return sb.toString(); 6422 } 6423 6424 /** 6425 * Retrieve the data to be backed to save the current state. 6426 * 6427 * The data includes: 6428 * 1. Wifi Settings (WifiSettingsConfigStore) 6429 * 2. WifiConfiguration/IpConfiguration (original backup by retrieveBackupData) 6430 * 3. SoftApConfiguration (original backup by retrieveSoftApBackupData) 6431 * 6432 * @param listener the listener to be used to receive backup data. 6433 */ 6434 @Override 6435 public void retrieveWifiBackupData(IByteArrayListener listener) { 6436 if (!SdkLevel.isAtLeastV()) { 6437 throw new UnsupportedOperationException("SDK level too old"); 6438 } 6439 enforceNetworkSettingsPermission(); 6440 mLog.info("retrieveWifiBackupData uid=%").c(Binder.getCallingUid()).flush(); 6441 if (listener == null) { 6442 throw new IllegalArgumentException("listener should not be null"); 6443 } 6444 mWifiThreadRunner.post(() -> { 6445 try { 6446 listener.onResult(mBackupRestoreController.retrieveBackupData()); 6447 } catch (RemoteException e) { 6448 Log.e(TAG, e.getMessage(), e); 6449 } 6450 }, TAG + "#retrieveWifiBackupData"); 6451 } 6452 6453 /** 6454 * Restore state from the backed up data. 6455 * 6456 * The api will guarantee the device would not damage when adding new XML tag. 6457 * 6458 * @param data Raw byte stream of the backed up data. 6459 */ 6460 @Override 6461 public void restoreWifiBackupData(byte[] data) { 6462 if (!SdkLevel.isAtLeastV()) { 6463 throw new UnsupportedOperationException("SDK level too old"); 6464 } 6465 enforceNetworkSettingsPermission(); 6466 mWifiThreadRunner.post(() -> { 6467 mLog.info("restoreWifiBackupData uid=%").c(Binder.getCallingUid()).flush(); 6468 mBackupRestoreController.parserBackupDataAndDispatch(data); 6469 }, TAG + "#restoreWifiBackupData"); 6470 } 6471 6472 /** 6473 * Retrieve the data to be backed to save the current state. 6474 * 6475 * @return Raw byte stream of the data to be backed up. 6476 */ 6477 @Override 6478 public byte[] retrieveBackupData() { 6479 enforceNetworkSettingsPermission(); 6480 mLog.info("retrieveBackupData uid=%").c(Binder.getCallingUid()).flush(); 6481 Log.d(TAG, "Retrieving backup data"); 6482 List<WifiConfiguration> wifiConfigurations = mWifiThreadRunner.call( 6483 () -> mWifiConfigManager.getConfiguredNetworksWithPasswords(), null, 6484 TAG + "#retrieveBackupData"); 6485 byte[] backupData = 6486 mWifiBackupRestore.retrieveBackupDataFromConfigurations(wifiConfigurations); 6487 Log.d(TAG, "Retrieved backup data"); 6488 return backupData; 6489 } 6490 6491 /** 6492 * Helper method to restore networks retrieved from backup data. 6493 * 6494 * @param configurations list of WifiConfiguration objects parsed from the backup data. 6495 */ 6496 @VisibleForTesting 6497 void restoreNetworks(List<WifiConfiguration> configurations) { 6498 if (configurations == null) { 6499 Log.w(TAG, "No wifi configuration to restore."); 6500 return; 6501 } 6502 int callingUid = Binder.getCallingUid(); 6503 if (configurations.isEmpty()) return; 6504 mWifiThreadRunner.post(() -> { 6505 boolean notOverrideExisting = CompatChanges 6506 .isChangeEnabled(NOT_OVERRIDE_EXISTING_NETWORKS_ON_RESTORE, callingUid); 6507 int networkId; 6508 for (WifiConfiguration configuration : configurations) { 6509 if (notOverrideExisting) { 6510 networkId = mWifiConfigManager.addNetwork(configuration, callingUid) 6511 .getNetworkId(); 6512 } else { 6513 networkId = mWifiConfigManager.addOrUpdateNetwork(configuration, callingUid) 6514 .getNetworkId(); 6515 } 6516 if (networkId == WifiConfiguration.INVALID_NETWORK_ID) { 6517 Log.e(TAG, "Restore network failed: " 6518 + configuration.getProfileKey() + ", network might already exist in the" 6519 + " database"); 6520 } else { 6521 // Enable all networks restored. 6522 mWifiConfigManager.enableNetwork(networkId, false, callingUid, null); 6523 // Restore auto-join param. 6524 mWifiConfigManager.allowAutojoin(networkId, configuration.allowAutojoin); 6525 } 6526 } 6527 }, TAG + "#restoreNetworks"); 6528 } 6529 6530 /** 6531 * Restore state from the backed up data. 6532 * 6533 * @param data Raw byte stream of the backed up data. 6534 */ 6535 @Override 6536 public void restoreBackupData(byte[] data) { 6537 enforceNetworkSettingsPermission(); 6538 mLog.info("restoreBackupData uid=%").c(Binder.getCallingUid()).flush(); 6539 Log.d(TAG, "Restoring backup data"); 6540 restoreNetworks(mWifiBackupRestore.retrieveConfigurationsFromBackupData(data)); 6541 } 6542 6543 /** 6544 * Retrieve the soft ap config data to be backed to save current config data. 6545 * 6546 * @return Raw byte stream of the data to be backed up. 6547 */ 6548 @Override 6549 public byte[] retrieveSoftApBackupData() { 6550 enforceNetworkSettingsPermission(); 6551 mLog.info("retrieveSoftApBackupData uid=%").c(Binder.getCallingUid()).flush(); 6552 SoftApConfiguration config = mWifiThreadRunner.call(mWifiApConfigStore::getApConfiguration, 6553 new SoftApConfiguration.Builder().build(), TAG + "#retrieveSoftApBackupData"); 6554 byte[] backupData = 6555 mSoftApBackupRestore.retrieveBackupDataFromSoftApConfiguration(config); 6556 Log.d(TAG, "Retrieved soft ap backup data"); 6557 return backupData; 6558 } 6559 6560 /** 6561 * Restore soft ap config from the backed up data. 6562 * 6563 * @param data Raw byte stream of the backed up data. 6564 * @return restored SoftApConfiguration or Null if data is invalid. 6565 */ 6566 @Override 6567 public SoftApConfiguration restoreSoftApBackupData(byte[] data) { 6568 enforceNetworkSettingsPermission(); 6569 mLog.info("restoreSoftApBackupData uid=%").c(Binder.getCallingUid()).flush(); 6570 SoftApConfiguration softApConfig = 6571 mSoftApBackupRestore.retrieveSoftApConfigurationFromBackupData(data); 6572 if (softApConfig != null) { 6573 mWifiApConfigStore.setApConfiguration( 6574 mWifiApConfigStore.resetToDefaultForUnsupportedConfig( 6575 mWifiApConfigStore.upgradeSoftApConfiguration(softApConfig))); 6576 Log.d(TAG, "Restored soft ap backup data"); 6577 } 6578 return softApConfig; 6579 } 6580 6581 /** 6582 * Restore state from the older supplicant back up data. The old backup data was essentially a 6583 * backup of wpa_supplicant.conf & ipconfig.txt file. 6584 * 6585 * @param supplicantData Raw byte stream of wpa_supplicant.conf 6586 * @param ipConfigData Raw byte stream of ipconfig.txt 6587 */ 6588 @Override 6589 public void restoreSupplicantBackupData(byte[] supplicantData, byte[] ipConfigData) { 6590 enforceNetworkSettingsPermission(); 6591 mLog.trace("restoreSupplicantBackupData uid=%").c(Binder.getCallingUid()).flush(); 6592 Log.d(TAG, "Restoring supplicant backup data"); 6593 restoreNetworks(mWifiBackupRestore.retrieveConfigurationsFromSupplicantBackupData( 6594 supplicantData, ipConfigData)); 6595 } 6596 6597 /** 6598 * Starts subscription provisioning with a provider. 6599 * 6600 * @param provider {@link OsuProvider} the provider to provision with 6601 * @param callback {@link IProvisioningCallback} the callback object to inform status 6602 */ 6603 @Override 6604 public void startSubscriptionProvisioning(OsuProvider provider, 6605 IProvisioningCallback callback) { 6606 if (provider == null) { 6607 throw new IllegalArgumentException("Provider must not be null"); 6608 } 6609 if (callback == null) { 6610 throw new IllegalArgumentException("Callback must not be null"); 6611 } 6612 if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { 6613 throw new SecurityException(TAG + ": Permission denied"); 6614 } 6615 final int uid = Binder.getCallingUid(); 6616 mLog.trace("startSubscriptionProvisioning uid=%").c(uid).flush(); 6617 if (getPrimaryClientModeManagerBlockingThreadSafe() 6618 .syncStartSubscriptionProvisioning(uid, provider, callback)) { 6619 mLog.trace("Subscription provisioning started with %") 6620 .c(provider.toString()).flush(); 6621 } 6622 } 6623 6624 /** 6625 * See 6626 * {@link WifiManager#registerTrafficStateCallback(Executor, WifiManager.TrafficStateCallback)} 6627 * 6628 * @param callback Traffic State callback to register 6629 * 6630 * @throws SecurityException if the caller does not have permission to register a callback 6631 * @throws RemoteException if remote exception happens 6632 * @throws IllegalArgumentException if the arguments are null or invalid 6633 */ 6634 @Override 6635 public void registerTrafficStateCallback(ITrafficStateCallback callback) { 6636 // verify arguments 6637 if (callback == null) { 6638 throw new IllegalArgumentException("Callback must not be null"); 6639 } 6640 enforceNetworkSettingsPermission(); 6641 if (mVerboseLoggingEnabled) { 6642 mLog.info("registerTrafficStateCallback uid=%").c(Binder.getCallingUid()).flush(); 6643 } 6644 // Post operation to handler thread 6645 mWifiThreadRunner.post(() -> mWifiTrafficPoller.addCallback(callback), 6646 TAG + "#registerTrafficStateCallback"); 6647 } 6648 6649 /** 6650 * see {@link android.net.wifi.WifiManager#unregisterTrafficStateCallback( 6651 * WifiManager.TrafficStateCallback)} 6652 * 6653 * @param callback Traffic State callback to unregister 6654 * 6655 * @throws SecurityException if the caller does not have permission to register a callback 6656 */ 6657 @Override 6658 public void unregisterTrafficStateCallback(ITrafficStateCallback callback) { 6659 enforceNetworkSettingsPermission(); 6660 if (mVerboseLoggingEnabled) { 6661 mLog.info("unregisterTrafficStateCallback uid=%").c(Binder.getCallingUid()).flush(); 6662 } 6663 // Post operation to handler thread 6664 mWifiThreadRunner.post(() -> mWifiTrafficPoller.removeCallback(callback), 6665 TAG + "#unregisterTrafficStateCallback"); 6666 } 6667 6668 protected String getSupportedFeaturesString() { 6669 return FeatureBitsetUtils.formatSupportedFeatures(getSupportedFeaturesInternal()); 6670 } 6671 6672 private BitSet getSupportedFeaturesInternal() { 6673 return mActiveModeWarden.getSupportedFeatureSet(); 6674 } 6675 6676 /** 6677 * See 6678 * {@link WifiManager#registerNetworkRequestMatchCallback( 6679 * Executor, WifiManager.NetworkRequestMatchCallback)} 6680 * 6681 * @param callback Network Request Match callback to register 6682 * 6683 * @throws SecurityException if the caller does not have permission to register a callback 6684 * @throws RemoteException if remote exception happens 6685 * @throws IllegalArgumentException if the arguments are null or invalid 6686 */ 6687 @Override 6688 public void registerNetworkRequestMatchCallback(INetworkRequestMatchCallback callback) { 6689 // verify arguments 6690 if (callback == null) { 6691 throw new IllegalArgumentException("Callback must not be null"); 6692 } 6693 enforceNetworkSettingsPermission(); 6694 if (mVerboseLoggingEnabled) { 6695 mLog.info("registerNetworkRequestMatchCallback uid=%") 6696 .c(Binder.getCallingUid()).flush(); 6697 } 6698 // Post operation to handler thread 6699 mWifiThreadRunner.post(() -> 6700 mWifiInjector.getWifiNetworkFactory().addCallback(callback), 6701 TAG + "#registerNetworkRequestMatchCallback"); 6702 } 6703 6704 /** 6705 * see {@link android.net.wifi.WifiManager#unregisterNetworkRequestMatchCallback( 6706 * WifiManager.NetworkRequestMatchCallback)} 6707 * 6708 * @param callback Network Request Match callback to unregister 6709 * 6710 * @throws SecurityException if the caller does not have permission to register a callback 6711 */ 6712 @Override 6713 public void unregisterNetworkRequestMatchCallback(INetworkRequestMatchCallback callback) { 6714 enforceNetworkSettingsPermission(); 6715 if (mVerboseLoggingEnabled) { 6716 mLog.info("unregisterNetworkRequestMatchCallback uid=%") 6717 .c(Binder.getCallingUid()).flush(); 6718 } 6719 // Post operation to handler thread 6720 mWifiThreadRunner.post(() -> 6721 mWifiInjector.getWifiNetworkFactory().removeCallback(callback), 6722 TAG + "#unregisterNetworkRequestMatchCallback"); 6723 } 6724 6725 /** 6726 * See {@link android.net.wifi.WifiManager#addNetworkSuggestions(List)} 6727 * 6728 * @param networkSuggestions List of network suggestions to be added. 6729 * @param callingPackageName Package Name of the app adding the suggestions. 6730 * @param callingFeatureId Feature in the calling package 6731 * @throws SecurityException if the caller does not have permission. 6732 * @return One of status codes from {@link WifiManager.NetworkSuggestionsStatusCode}. 6733 */ 6734 @Override 6735 public int addNetworkSuggestions( 6736 ParceledListSlice<WifiNetworkSuggestion> networkSuggestions, String callingPackageName, 6737 String callingFeatureId) { 6738 if (enforceChangePermission(callingPackageName) != MODE_ALLOWED) { 6739 return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_APP_DISALLOWED; 6740 } 6741 int callingUid = Binder.getCallingUid(); 6742 int callingPid = Binder.getCallingPid(); 6743 6744 long ident = Binder.clearCallingIdentity(); 6745 try { 6746 if (SdkLevel.isAtLeastT()) { 6747 boolean isUserRestrictionSet = mUserManager.hasUserRestrictionForUser( 6748 UserManager.DISALLOW_ADD_WIFI_CONFIG, 6749 UserHandle.getUserHandleForUid(callingUid)); 6750 boolean isCarrierApp = mWifiInjector.makeTelephonyManager() 6751 .checkCarrierPrivilegesForPackageAnyPhone(callingPackageName) 6752 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; 6753 boolean hasPermission = !isUserRestrictionSet 6754 || isCarrierApp 6755 || isPrivileged(callingPid, callingUid) 6756 || mWifiPermissionsUtil.isSystem(callingPackageName, callingUid) 6757 || mWifiPermissionsUtil.isAdmin(callingUid, callingPackageName); 6758 if (!hasPermission) { 6759 return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_RESTRICTED_BY_ADMIN; 6760 } 6761 } 6762 } finally { 6763 Binder.restoreCallingIdentity(ident); 6764 } 6765 6766 if (mVerboseLoggingEnabled) { 6767 mLog.info("addNetworkSuggestions uid=%").c(callingUid).flush(); 6768 } 6769 if (networkSuggestions == null) { 6770 return STATUS_NETWORK_SUGGESTIONS_SUCCESS; 6771 } 6772 6773 int success = mWifiThreadRunner.call(() -> mWifiNetworkSuggestionsManager.add( 6774 networkSuggestions.getList(), callingUid, callingPackageName, callingFeatureId), 6775 WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL, 6776 TAG + "#addNetworkSuggestions"); 6777 if (success != STATUS_NETWORK_SUGGESTIONS_SUCCESS) { 6778 Log.e(TAG, "Failed to add network suggestions"); 6779 } 6780 return success; 6781 } 6782 6783 /** 6784 * See {@link android.net.wifi.WifiManager#removeNetworkSuggestions(List)} 6785 * 6786 * @param networkSuggestions List of network suggestions to be removed. 6787 * @param callingPackageName Package Name of the app removing the suggestions. 6788 * @throws SecurityException if the caller does not have permission. 6789 * @return One of status codes from {@link WifiManager.NetworkSuggestionsStatusCode}. 6790 */ 6791 @Override 6792 public int removeNetworkSuggestions( 6793 ParceledListSlice<WifiNetworkSuggestion> networkSuggestions, String callingPackageName, 6794 @WifiManager.ActionAfterRemovingSuggestion int action) { 6795 if (enforceChangePermission(callingPackageName) != MODE_ALLOWED) { 6796 return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_APP_DISALLOWED; 6797 } 6798 if (mVerboseLoggingEnabled) { 6799 mLog.info("removeNetworkSuggestions uid=%").c(Binder.getCallingUid()).flush(); 6800 } 6801 if (action != WifiManager.ACTION_REMOVE_SUGGESTION_DISCONNECT 6802 && action != WifiManager.ACTION_REMOVE_SUGGESTION_LINGER) { 6803 return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID; 6804 } 6805 int callingUid = Binder.getCallingUid(); 6806 6807 if (networkSuggestions == null) { 6808 return STATUS_NETWORK_SUGGESTIONS_SUCCESS; 6809 } 6810 int success = mWifiThreadRunner.call(() -> mWifiNetworkSuggestionsManager.remove( 6811 networkSuggestions.getList(), callingUid, callingPackageName, 6812 action), WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL, 6813 TAG + "#removeNetworkSuggestions"); 6814 if (success != STATUS_NETWORK_SUGGESTIONS_SUCCESS) { 6815 Log.e(TAG, "Failed to remove network suggestions"); 6816 } 6817 return success; 6818 } 6819 6820 /** 6821 * See {@link android.net.wifi.WifiManager#getNetworkSuggestions()} 6822 * @param callingPackageName Package Name of the app getting the suggestions. 6823 * @return a list of network suggestions suggested by this app 6824 */ 6825 @Override 6826 public ParceledListSlice<WifiNetworkSuggestion> getNetworkSuggestions( 6827 String callingPackageName) { 6828 int callingUid = Binder.getCallingUid(); 6829 mAppOps.checkPackage(callingUid, callingPackageName); 6830 enforceAccessPermission(); 6831 if (mVerboseLoggingEnabled) { 6832 mLog.info("getNetworkSuggestionList uid=%").c(Binder.getCallingUid()).flush(); 6833 } 6834 return new ParceledListSlice<>(mWifiThreadRunner.call(() -> 6835 mWifiNetworkSuggestionsManager.get(callingPackageName, callingUid), 6836 Collections.emptyList(), TAG + "#getNetworkSuggestions")); 6837 } 6838 6839 /** 6840 * Gets the factory Wi-Fi MAC addresses. 6841 * @throws SecurityException if the caller does not have permission. 6842 * @return Array of String representing Wi-Fi MAC addresses, or empty array if failed. 6843 */ 6844 @Override 6845 public String[] getFactoryMacAddresses() { 6846 final int uid = Binder.getCallingUid(); 6847 if (!mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { 6848 throw new SecurityException("App not allowed to get Wi-Fi factory MAC address " 6849 + "(uid = " + uid + ")"); 6850 } 6851 // Check the ConfigStore cache first 6852 if (mWifiGlobals.isSaveFactoryMacToConfigStoreEnabled()) { 6853 String factoryMacAddressStr = mSettingsConfigStore.get(WIFI_STA_FACTORY_MAC_ADDRESS); 6854 if (factoryMacAddressStr != null) return new String[] {factoryMacAddressStr}; 6855 } 6856 String result = mWifiThreadRunner.call( 6857 () -> mActiveModeWarden.getPrimaryClientModeManager().getFactoryMacAddress(), 6858 null, TAG + "#getFactoryMacAddresses"); 6859 // result can be empty array if either: WifiThreadRunner.call() timed out, or 6860 // ClientModeImpl.getFactoryMacAddress() returned null. 6861 // In this particular instance, we don't differentiate the two types of nulls. 6862 if (result == null) { 6863 return new String[0]; 6864 } 6865 return new String[]{result}; 6866 } 6867 6868 /** 6869 * Sets the current device mobility state. 6870 * @param state the new device mobility state 6871 */ 6872 @Override 6873 public void setDeviceMobilityState(@DeviceMobilityState int state) { 6874 mContext.enforceCallingOrSelfPermission( 6875 android.Manifest.permission.WIFI_SET_DEVICE_MOBILITY_STATE, "WifiService"); 6876 6877 if (mVerboseLoggingEnabled) { 6878 mLog.info("setDeviceMobilityState uid=% state=%") 6879 .c(Binder.getCallingUid()) 6880 .c(state) 6881 .flush(); 6882 } 6883 // Post operation to handler thread 6884 mWifiThreadRunner.post(() -> { 6885 mWifiConnectivityManager.setDeviceMobilityState(state); 6886 mWifiHealthMonitor.setDeviceMobilityState(state); 6887 mWifiDataStall.setDeviceMobilityState(state); 6888 mActiveModeWarden.setDeviceMobilityState(state); 6889 }, TAG + "#setDeviceMobilityState"); 6890 } 6891 6892 /** 6893 * Proxy for the final native call of the parent class. Enables mocking of 6894 * the function. 6895 */ 6896 public int getMockableCallingUid() { 6897 return getCallingUid(); 6898 } 6899 6900 /** 6901 * Start DPP in Configurator-Initiator role. The current device will initiate DPP bootstrapping 6902 * with a peer, and send the SSID and password of the selected network. 6903 * 6904 * @param binder Caller's binder context 6905 * @param packageName Package name of the calling app 6906 * @param enrolleeUri URI of the Enrollee obtained externally (e.g. QR code scanning) 6907 * @param selectedNetworkId Selected network ID to be sent to the peer 6908 * @param netRole The network role of the enrollee 6909 * @param callback Callback for status updates 6910 */ 6911 @Override 6912 public void startDppAsConfiguratorInitiator(IBinder binder, @NonNull String packageName, 6913 String enrolleeUri, int selectedNetworkId, int netRole, IDppCallback callback) { 6914 // verify arguments 6915 if (binder == null) { 6916 throw new IllegalArgumentException("Binder must not be null"); 6917 } 6918 if (TextUtils.isEmpty(enrolleeUri)) { 6919 throw new IllegalArgumentException("Enrollee URI must not be null or empty"); 6920 } 6921 if (selectedNetworkId < 0) { 6922 throw new IllegalArgumentException("Selected network ID invalid"); 6923 } 6924 if (callback == null) { 6925 throw new IllegalArgumentException("Callback must not be null"); 6926 } 6927 6928 final int uid = getMockableCallingUid(); 6929 6930 int callingUid = Binder.getCallingUid(); 6931 mWifiPermissionsUtil.checkPackage(callingUid, packageName); 6932 mAppOps.checkPackage(callingUid, packageName); 6933 if (!isSettingsOrSuw(Binder.getCallingPid(), callingUid)) { 6934 throw new SecurityException(TAG + ": Permission denied"); 6935 } 6936 // Stop MBB (if in progress) when DPP is initiated. Otherwise, DPP operation will fail 6937 // when the previous primary iface is removed after MBB completion. 6938 mWifiThreadRunner.post(() -> 6939 mMakeBeforeBreakManager.stopAllSecondaryTransientClientModeManagers(() -> 6940 mDppManager.startDppAsConfiguratorInitiator( 6941 uid, packageName, 6942 mActiveModeWarden.getPrimaryClientModeManager().getInterfaceName(), 6943 binder, enrolleeUri, selectedNetworkId, netRole, callback)), 6944 TAG + "#startDppAsConfiguratorInitiator"); 6945 } 6946 6947 /** 6948 * Start DPP in Enrollee-Initiator role. The current device will initiate DPP bootstrapping 6949 * with a peer, and receive the SSID and password from the peer configurator. 6950 * 6951 * @param binder Caller's binder context 6952 * @param configuratorUri URI of the Configurator obtained externally (e.g. QR code scanning) 6953 * @param callback Callback for status updates 6954 */ 6955 @Override 6956 public void startDppAsEnrolleeInitiator(IBinder binder, String configuratorUri, 6957 IDppCallback callback) { 6958 // verify arguments 6959 if (binder == null) { 6960 throw new IllegalArgumentException("Binder must not be null"); 6961 } 6962 if (TextUtils.isEmpty(configuratorUri)) { 6963 throw new IllegalArgumentException("Enrollee URI must not be null or empty"); 6964 } 6965 if (callback == null) { 6966 throw new IllegalArgumentException("Callback must not be null"); 6967 } 6968 6969 final int uid = getMockableCallingUid(); 6970 6971 if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { 6972 throw new SecurityException(TAG + ": Permission denied"); 6973 } 6974 6975 // Stop MBB (if in progress) when DPP is initiated. Otherwise, DPP operation will fail 6976 // when the previous primary iface is removed after MBB completion. 6977 mWifiThreadRunner.post(() -> 6978 mMakeBeforeBreakManager.stopAllSecondaryTransientClientModeManagers(() -> 6979 mDppManager.startDppAsEnrolleeInitiator(uid, 6980 mActiveModeWarden.getPrimaryClientModeManager().getInterfaceName(), 6981 binder, configuratorUri, callback)), 6982 TAG + "#startDppAsEnrolleeInitiator"); 6983 } 6984 6985 /** 6986 * Start DPP in Enrollee-Responder role. The current device will generate the 6987 * bootstrap code and wait for the peer device to start the DPP authentication process. 6988 * 6989 * @param binder Caller's binder context 6990 * @param deviceInfo Device specific info to display in QR code(e.g. Easy_connect_demo) 6991 * @param curve Elliptic curve cryptography type used to generate DPP public/private key pair. 6992 * @param callback Callback for status updates 6993 */ 6994 @Override 6995 @RequiresApi(Build.VERSION_CODES.S) 6996 public void startDppAsEnrolleeResponder(IBinder binder, @Nullable String deviceInfo, 6997 @WifiManager.EasyConnectCryptographyCurve int curve, IDppCallback callback) { 6998 if (!SdkLevel.isAtLeastS()) { 6999 throw new UnsupportedOperationException(); 7000 } 7001 // verify arguments 7002 if (binder == null) { 7003 throw new IllegalArgumentException("Binder must not be null"); 7004 } 7005 if (callback == null) { 7006 throw new IllegalArgumentException("Callback must not be null"); 7007 } 7008 7009 final int uid = getMockableCallingUid(); 7010 7011 if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { 7012 throw new SecurityException(TAG + ": Permission denied"); 7013 } 7014 7015 if (deviceInfo != null) { 7016 int deviceInfoLen = deviceInfo.length(); 7017 if (deviceInfoLen > WifiManager.getEasyConnectMaxAllowedResponderDeviceInfoLength()) { 7018 throw new IllegalArgumentException("Device info length: " + deviceInfoLen 7019 + " must be less than " 7020 + WifiManager.getEasyConnectMaxAllowedResponderDeviceInfoLength()); 7021 } 7022 char c; 7023 for (int i = 0; i < deviceInfoLen; i++) { 7024 c = deviceInfo.charAt(i); 7025 if (c < '!' || c > '~' || c == ';') { 7026 throw new IllegalArgumentException("Allowed Range of ASCII characters in" 7027 + "deviceInfo - %x20-7E; semicolon and space are not allowed!" 7028 + "Found c: " + c); 7029 } 7030 } 7031 } 7032 7033 // Stop MBB (if in progress) when DPP is initiated. Otherwise, DPP operation will fail 7034 // when the previous primary iface is removed after MBB completion. 7035 mWifiThreadRunner.post(() -> 7036 mMakeBeforeBreakManager.stopAllSecondaryTransientClientModeManagers(() -> 7037 mDppManager.startDppAsEnrolleeResponder(uid, 7038 mActiveModeWarden.getPrimaryClientModeManager().getInterfaceName(), 7039 binder, deviceInfo, curve, callback)), 7040 TAG + "#startDppAsEnrolleeResponder"); 7041 } 7042 7043 /** 7044 * Stop or abort a current DPP session. 7045 */ 7046 @Override 7047 public void stopDppSession() throws RemoteException { 7048 if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { 7049 throw new SecurityException(TAG + ": Permission denied"); 7050 } 7051 final int uid = getMockableCallingUid(); 7052 7053 mWifiThreadRunner.post(() -> mDppManager.stopDppSession(uid), 7054 TAG + "#stopDppSession"); 7055 } 7056 7057 /** 7058 * see {@link android.net.wifi.WifiManager#addWifiVerboseLoggingStatusChangedListener(Executor, 7059 * WifiManager.WifiVerboseLoggingStatusChangedListener)} 7060 * 7061 * @param listener IWifiVerboseLoggingStatusChangedListener listener to add 7062 * 7063 * @throws SecurityException if the caller does not have permission to add a listener. 7064 * @throws IllegalArgumentException if the argument is null. 7065 */ 7066 @Override 7067 public void addWifiVerboseLoggingStatusChangedListener( 7068 IWifiVerboseLoggingStatusChangedListener listener) { 7069 if (listener == null) { 7070 throw new IllegalArgumentException("Listener must not be null"); 7071 } 7072 enforceAccessPermission(); 7073 mRegisteredWifiLoggingStatusListeners.register(listener); 7074 } 7075 7076 /** 7077 * see {@link android.net.wifi.WifiManager#unregisterWifiVerboseLoggingStatusCallback 7078 * (WifiManager.WifiVerboseLoggingStatusCallback)} 7079 * 7080 * @param listener the listener to be removed. 7081 * 7082 * @throws SecurityException if the caller does not have permission to add a listener. 7083 * @throws IllegalArgumentException if the argument is null. 7084 */ 7085 @Override 7086 public void removeWifiVerboseLoggingStatusChangedListener( 7087 IWifiVerboseLoggingStatusChangedListener listener) { 7088 if (listener == null) { 7089 throw new IllegalArgumentException("Listener must not be null"); 7090 } 7091 enforceAccessPermission(); 7092 mRegisteredWifiLoggingStatusListeners.unregister(listener); 7093 } 7094 7095 /** 7096 * see {@link android.net.wifi.WifiManager#addOnWifiUsabilityStatsListener(Executor, 7097 * WifiManager.OnWifiUsabilityStatsListener)} 7098 * 7099 * @param listener WifiUsabilityStatsEntry listener to add 7100 * 7101 * @throws SecurityException if the caller does not have permission to add a listener 7102 * @throws RemoteException if remote exception happens 7103 * @throws IllegalArgumentException if the arguments are null or invalid 7104 */ 7105 @Override 7106 public void addOnWifiUsabilityStatsListener(IOnWifiUsabilityStatsListener listener) { 7107 if (listener == null) { 7108 throw new IllegalArgumentException("Listener must not be null"); 7109 } 7110 mContext.enforceCallingOrSelfPermission( 7111 android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE, "WifiService"); 7112 if (mVerboseLoggingEnabled) { 7113 mLog.info("addOnWifiUsabilityStatsListener uid=%") 7114 .c(Binder.getCallingUid()).flush(); 7115 } 7116 // Post operation to handler thread 7117 mWifiThreadRunner.post(() -> 7118 mWifiMetrics.addOnWifiUsabilityListener(listener), 7119 TAG + "#addOnWifiUsabilityStatsListener"); 7120 } 7121 7122 /** 7123 * see {@link android.net.wifi.WifiManager#removeOnWifiUsabilityStatsListener 7124 * (WifiManager.OnWifiUsabilityStatsListener)} 7125 * 7126 * @param listener listener to be removed. 7127 * 7128 * @throws SecurityException if the caller does not have permission to add a listener 7129 */ 7130 @Override 7131 public void removeOnWifiUsabilityStatsListener(IOnWifiUsabilityStatsListener listener) { 7132 if (listener == null) { 7133 throw new IllegalArgumentException("Listener must not be null"); 7134 } 7135 mContext.enforceCallingOrSelfPermission( 7136 android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE, "WifiService"); 7137 if (mVerboseLoggingEnabled) { 7138 mLog.info("removeOnWifiUsabilityStatsListener uid=%") 7139 .c(Binder.getCallingUid()).flush(); 7140 } 7141 // Post operation to handler thread 7142 mWifiThreadRunner.post(() -> 7143 mWifiMetrics.removeOnWifiUsabilityListener(listener), 7144 TAG + "#removeOnWifiUsabilityStatsListener"); 7145 } 7146 7147 /** 7148 * Updates the Wi-Fi usability score. 7149 * @param seqNum Sequence number of the Wi-Fi usability score. 7150 * @param score The Wi-Fi usability score. 7151 * @param predictionHorizonSec Prediction horizon of the Wi-Fi usability score in second. 7152 */ 7153 @Override 7154 public void updateWifiUsabilityScore(int seqNum, int score, int predictionHorizonSec) { 7155 mContext.enforceCallingOrSelfPermission( 7156 android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE, "WifiService"); 7157 7158 if (mVerboseLoggingEnabled) { 7159 mLog.info("updateWifiUsabilityScore uid=% seqNum=% score=% predictionHorizonSec=%") 7160 .c(Binder.getCallingUid()) 7161 .c(seqNum) 7162 .c(score) 7163 .c(predictionHorizonSec) 7164 .flush(); 7165 } 7166 // Post operation to handler thread 7167 mWifiThreadRunner.post(() -> { 7168 String ifaceName = mActiveModeWarden.getPrimaryClientModeManager().getInterfaceName(); 7169 mWifiMetrics.incrementWifiUsabilityScoreCount( 7170 ifaceName, seqNum, score, predictionHorizonSec); 7171 }, TAG + "#updateWifiUsabilityScore"); 7172 } 7173 7174 /** 7175 * Notify interested parties if a wifi config has been changed. 7176 * 7177 * @param wifiCredentialEventType WIFI_CREDENTIAL_SAVED or WIFI_CREDENTIAL_FORGOT 7178 * @param config Must have a WifiConfiguration object to succeed 7179 */ 7180 private void broadcastWifiCredentialChanged(int wifiCredentialEventType, 7181 WifiConfiguration config) { 7182 Intent intent = new Intent(WifiManager.WIFI_CREDENTIAL_CHANGED_ACTION); 7183 if (config != null && config.SSID != null && mWifiPermissionsUtil.isLocationModeEnabled()) { 7184 intent.putExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_SSID, config.SSID); 7185 } 7186 intent.putExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_EVENT_TYPE, 7187 wifiCredentialEventType); 7188 mContext.createContextAsUser(UserHandle.CURRENT, 0) 7189 .sendBroadcastWithMultiplePermissions( 7190 intent, 7191 new String[]{ 7192 android.Manifest.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE, 7193 android.Manifest.permission.ACCESS_FINE_LOCATION, 7194 }); 7195 } 7196 7197 /** 7198 * Connects to a network. 7199 * 7200 * If the supplied config is not null, then the netId argument will be ignored and the config 7201 * will be saved (or updated if its networkId or profile key already exist) and connected to. 7202 * 7203 * If the supplied config is null, then the netId argument will be matched to a saved config to 7204 * be connected to. 7205 * 7206 * @param config New or existing config to add/update and connect to 7207 * @param netId Network ID of existing config to connect to if the supplied config is null 7208 * @param callback Listener to notify action result 7209 * @param packageName Package name of the requesting App 7210 * @param extras Bundle of extras 7211 * 7212 * see: {@link WifiManager#connect(WifiConfiguration, WifiManager.ActionListener)} 7213 * {@link WifiManager#connect(int, WifiManager.ActionListener)} 7214 */ 7215 @Override 7216 public void connect(WifiConfiguration config, int netId, @Nullable IActionListener callback, 7217 @NonNull String packageName, Bundle extras) { 7218 int uid = getMockableCallingUid(); 7219 if (!isPrivileged(Binder.getCallingPid(), uid) 7220 // TODO(b/343881335): Longer term, we need a specific permission 7221 // for NFC. 7222 && UserHandle.getAppId(uid) != Process.NFC_UID) { 7223 throw new SecurityException(TAG + ": Permission denied"); 7224 } 7225 if (packageName == null) { 7226 throw new IllegalArgumentException("packageName must not be null"); 7227 } 7228 final String attributionTagToUse; 7229 final int uidToUse; 7230 final String packageNameToUse; 7231 if (SdkLevel.isAtLeastS() && UserHandle.getAppId(uid) == Process.SYSTEM_UID) { 7232 AttributionSource as = extras.getParcelable( 7233 WifiManager.EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE); 7234 if (as == null) { 7235 throw new SecurityException("connect attributionSource is null"); 7236 } 7237 if (!as.checkCallingUid()) { 7238 throw new SecurityException( 7239 "connect invalid (checkCallingUid fails) attribution source=" 7240 + as); 7241 } 7242 // an attribution chain is either of size 1: unregistered (valid by definition) or 7243 // size >1: in which case all are validated. 7244 AttributionSource asIt = as; 7245 AttributionSource asLast = as; 7246 if (as.getNext() != null) { 7247 do { 7248 if (!asIt.isTrusted(mContext)) { 7249 throw new SecurityException( 7250 "connect invalid (isTrusted fails) attribution source=" 7251 + asIt); 7252 } 7253 asIt = asIt.getNext(); 7254 if (asIt != null) asLast = asIt; 7255 } while (asIt != null); 7256 } 7257 // use the last AttributionSource in the chain - i.e. the original caller 7258 attributionTagToUse = asLast.getAttributionTag(); 7259 uidToUse = asLast.getUid(); 7260 packageNameToUse = asLast.getPackageName(); 7261 } else { 7262 attributionTagToUse = mContext.getAttributionTag(); 7263 uidToUse = uid; 7264 packageNameToUse = packageName; 7265 } 7266 mLog.info("connect uid=% uidToUse=% packageNameToUse=% attributionTagToUse=%") 7267 .c(uid).c(uidToUse).c(packageNameToUse).c(attributionTagToUse).flush(); 7268 mLastCallerInfoManager.put(config != null 7269 ? WifiManager.API_CONNECT_CONFIG : WifiManager.API_CONNECT_NETWORK_ID, 7270 Process.myTid(), uid, Binder.getCallingPid(), packageName, true); 7271 mWifiThreadRunner.post( 7272 () -> { 7273 ActionListenerWrapper wrapper = new ActionListenerWrapper(callback); 7274 final NetworkUpdateResult result; 7275 // if connecting using WifiConfiguration, save the network first 7276 if (config != null) { 7277 if (mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { 7278 mWifiMetrics.logUserActionEvent( 7279 UserActionEvent.EVENT_ADD_OR_UPDATE_NETWORK, config.networkId); 7280 } 7281 result = mWifiConfigManager.addOrUpdateNetwork(config, uid); 7282 if (!result.isSuccess()) { 7283 Log.e(TAG, "connect adding/updating config=" + config + " failed"); 7284 wrapper.sendFailure(WifiManager.ActionListener.FAILURE_INTERNAL_ERROR); 7285 return; 7286 } 7287 broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_SAVED, config); 7288 } else { 7289 if (mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { 7290 mWifiMetrics.logUserActionEvent( 7291 UserActionEvent.EVENT_MANUAL_CONNECT, netId); 7292 } 7293 result = new NetworkUpdateResult(netId); 7294 } 7295 WifiConfiguration configuration = 7296 mWifiConfigManager.getConfiguredNetwork(result.getNetworkId()); 7297 if (configuration == null) { 7298 Log.e(TAG, "connect to Invalid network Id=" + netId); 7299 wrapper.sendFailure(WifiManager.ActionListener.FAILURE_INTERNAL_ERROR); 7300 return; 7301 } 7302 if (mWifiPermissionsUtil.isAdminRestrictedNetwork(configuration)) { 7303 Log.e(TAG, "connect to network Id=" + netId + "restricted by admin"); 7304 wrapper.sendFailure(WifiManager.ActionListener.FAILURE_INTERNAL_ERROR); 7305 return; 7306 } 7307 if (mWifiGlobals.isDeprecatedSecurityTypeNetwork(configuration)) { 7308 Log.e(TAG, "connect to network Id=" + netId + " security type deprecated."); 7309 wrapper.sendFailure(WifiManager.ActionListener.FAILURE_INTERNAL_ERROR); 7310 return; 7311 } 7312 if (configuration.enterpriseConfig != null 7313 && configuration.enterpriseConfig.isAuthenticationSimBased()) { 7314 int subId = 7315 mWifiCarrierInfoManager.getBestMatchSubscriptionId(configuration); 7316 if (!mWifiCarrierInfoManager.isSimReady(subId)) { 7317 Log.e( 7318 TAG, 7319 "connect to SIM-based config=" 7320 + configuration 7321 + "while SIM is absent"); 7322 wrapper.sendFailure(WifiManager.ActionListener.FAILURE_INTERNAL_ERROR); 7323 return; 7324 } 7325 if (mWifiCarrierInfoManager.requiresImsiEncryption(subId) 7326 && !mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(subId)) { 7327 Log.e( 7328 TAG, 7329 "Imsi protection required but not available for Network=" 7330 + configuration); 7331 wrapper.sendFailure(WifiManager.ActionListener.FAILURE_INTERNAL_ERROR); 7332 return; 7333 } 7334 if (mWifiCarrierInfoManager.isOobPseudonymFeatureEnabled( 7335 configuration.carrierId)) { 7336 Optional<PseudonymInfo> pseudonymInfo = 7337 mWifiPseudonymManager.getValidPseudonymInfo( 7338 configuration.carrierId); 7339 if (pseudonymInfo.isEmpty()) { 7340 Log.e( 7341 TAG, 7342 "There isn't any valid pseudonym to update the Network=" 7343 + configuration); 7344 mWifiPseudonymManager.retrievePseudonymOnFailureTimeoutExpired( 7345 configuration); 7346 // TODO(b/274148786): new error code and UX for this failure. 7347 wrapper.sendFailure( 7348 WifiManager.ActionListener.FAILURE_INTERNAL_ERROR); 7349 return; 7350 } else { 7351 mWifiPseudonymManager.updateWifiConfiguration(configuration); 7352 } 7353 } 7354 } 7355 7356 // Tear down already connected secondary internet CMMs to avoid MCC. 7357 // Also tear down secondary CMMs that are already connected to the same network 7358 // to make sure the user's manual connection succeeds. 7359 ScanResultMatchInfo targetMatchInfo = 7360 ScanResultMatchInfo.fromWifiConfiguration(configuration); 7361 for (ClientModeManager cmm : mActiveModeWarden.getClientModeManagers()) { 7362 if (!cmm.isConnected()) { 7363 continue; 7364 } 7365 ActiveModeManager.ClientRole role = cmm.getRole(); 7366 if (role == ROLE_CLIENT_LOCAL_ONLY 7367 || role == ROLE_CLIENT_SECONDARY_LONG_LIVED) { 7368 WifiConfiguration connectedConfig = cmm.getConnectedWifiConfiguration(); 7369 if (connectedConfig == null) { 7370 continue; 7371 } 7372 ScanResultMatchInfo connectedMatchInfo = 7373 ScanResultMatchInfo.fromWifiConfiguration(connectedConfig); 7374 ConcreteClientModeManager concreteCmm = (ConcreteClientModeManager) cmm; 7375 if (concreteCmm.isSecondaryInternet() 7376 || targetMatchInfo.matchForNetworkSelection(connectedMatchInfo) 7377 != null) { 7378 if (mVerboseLoggingEnabled) { 7379 Log.v( 7380 TAG, 7381 "Shutting down client mode manager to satisfy user " 7382 + "connection: " 7383 + cmm); 7384 } 7385 cmm.stop(); 7386 } 7387 } 7388 } 7389 7390 mMakeBeforeBreakManager.stopAllSecondaryTransientClientModeManagers( 7391 () -> 7392 mConnectHelper.connectToNetwork( 7393 result, wrapper, uidToUse, packageNameToUse, 7394 attributionTagToUse)); 7395 }, TAG + "#connect"); 7396 } 7397 7398 /** 7399 * see {@link android.net.wifi.WifiManager#save(WifiConfiguration, 7400 * WifiManager.ActionListener)} 7401 */ 7402 @Override 7403 public void save(WifiConfiguration config, @Nullable IActionListener callback, 7404 @NonNull String packageName) { 7405 int uid = Binder.getCallingUid(); 7406 if (!isPrivileged(Binder.getCallingPid(), uid)) { 7407 throw new SecurityException(TAG + ": Permission denied"); 7408 } 7409 if (packageName == null) { 7410 throw new IllegalArgumentException("packageName must not be null"); 7411 } 7412 mLog.info("save uid=%").c(uid).flush(); 7413 mLastCallerInfoManager.put(WifiManager.API_SAVE, Process.myTid(), 7414 uid, Binder.getCallingPid(), packageName, true); 7415 mWifiThreadRunner.post(() -> { 7416 ActionListenerWrapper wrapper = new ActionListenerWrapper(callback); 7417 NetworkUpdateResult result = 7418 mWifiConfigManager.updateBeforeSaveNetwork(config, uid, packageName); 7419 if (result.isSuccess()) { 7420 broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_SAVED, config); 7421 mMakeBeforeBreakManager.stopAllSecondaryTransientClientModeManagers(() -> 7422 mActiveModeWarden.getPrimaryClientModeManager() 7423 .saveNetwork(result, wrapper, uid, packageName)); 7424 if (mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { 7425 mWifiMetrics.logUserActionEvent( 7426 UserActionEvent.EVENT_ADD_OR_UPDATE_NETWORK, config.networkId); 7427 } 7428 } else { 7429 wrapper.sendFailure(WifiManager.ActionListener.FAILURE_INTERNAL_ERROR); 7430 } 7431 }, TAG + "#save"); 7432 } 7433 7434 /** 7435 * see {@link android.net.wifi.WifiManager#forget(int, WifiManager.ActionListener)} 7436 */ 7437 @Override 7438 public void forget(int netId, @Nullable IActionListener callback) { 7439 int uid = Binder.getCallingUid(); 7440 if (!isPrivileged(Binder.getCallingPid(), uid)) { 7441 throw new SecurityException(TAG + ": Permission denied"); 7442 } 7443 mLog.info("forget uid=%").c(Binder.getCallingUid()).flush(); 7444 if (mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { 7445 // It's important to log this metric before the actual forget executes because 7446 // the netId becomes invalid after the forget operation. 7447 mWifiMetrics.logUserActionEvent(UserActionEvent.EVENT_FORGET_WIFI, netId); 7448 } 7449 mLastCallerInfoManager.put(WifiManager.API_FORGET, Process.myTid(), 7450 uid, Binder.getCallingPid(), "<unknown>", true); 7451 mWifiThreadRunner.post(() -> { 7452 WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(netId); 7453 boolean success = mWifiConfigManager.removeNetwork(netId, uid, null); 7454 ActionListenerWrapper wrapper = new ActionListenerWrapper(callback); 7455 if (success) { 7456 wrapper.sendSuccess(); 7457 broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_FORGOT, config); 7458 } else { 7459 Log.e(TAG, "Failed to remove network"); 7460 wrapper.sendFailure(WifiManager.ActionListener.FAILURE_INTERNAL_ERROR); 7461 } 7462 }, TAG + "#forget"); 7463 } 7464 7465 /** 7466 * See {@link WifiManager#registerScanResultsCallback(WifiManager.ScanResultsCallback)} 7467 */ 7468 @Override 7469 public void registerScanResultsCallback(@NonNull IScanResultsCallback callback) { 7470 if (callback == null) { 7471 throw new IllegalArgumentException("callback must not be null"); 7472 } 7473 enforceAccessPermission(); 7474 7475 if (mVerboseLoggingEnabled) { 7476 mLog.info("registerScanResultsCallback uid=%").c(Binder.getCallingUid()).flush(); 7477 } 7478 mWifiThreadRunner.post(() -> { 7479 if (!mWifiInjector.getScanRequestProxy().registerScanResultsCallback(callback)) { 7480 Log.e(TAG, "registerScanResultsCallback: Failed to register callback"); 7481 } 7482 }, TAG + "#registerScanResultsCallback"); 7483 } 7484 7485 /** 7486 * See {@link WifiManager#registerScanResultsCallback(WifiManager.ScanResultsCallback)} 7487 */ 7488 public void unregisterScanResultsCallback(@NonNull IScanResultsCallback callback) { 7489 if (callback == null) { 7490 throw new IllegalArgumentException("callback must not be null"); 7491 } 7492 enforceAccessPermission(); 7493 7494 if (mVerboseLoggingEnabled) { 7495 mLog.info("unregisterScanResultCallback uid=%").c(Binder.getCallingUid()).flush(); 7496 } 7497 // post operation to handler thread 7498 mWifiThreadRunner.post(() -> mWifiInjector.getScanRequestProxy() 7499 .unregisterScanResultsCallback(callback), 7500 TAG + "#unregisterScanResultsCallback"); 7501 7502 } 7503 7504 /** 7505 * See {@link WifiManager#addSuggestionConnectionStatusListener(Executor, 7506 * SuggestionConnectionStatusListener)} 7507 */ 7508 public void registerSuggestionConnectionStatusListener( 7509 @NonNull ISuggestionConnectionStatusListener listener, String packageName, 7510 @Nullable String featureId) { 7511 if (listener == null) { 7512 throw new IllegalArgumentException("listener must not be null"); 7513 } 7514 final int uid = Binder.getCallingUid(); 7515 mWifiPermissionsUtil.checkPackage(uid, packageName); 7516 enforceAccessPermission(); 7517 if (SdkLevel.isAtLeastT()) { 7518 enforceLocationPermissionInManifest(uid, false /* isCoarseOnly */); 7519 } else { 7520 enforceLocationPermission(packageName, featureId, uid); 7521 } 7522 if (mVerboseLoggingEnabled) { 7523 mLog.info("registerSuggestionConnectionStatusListener uid=%").c(uid).flush(); 7524 } 7525 mWifiThreadRunner.post(() -> 7526 mWifiNetworkSuggestionsManager 7527 .registerSuggestionConnectionStatusListener(listener, packageName, uid), 7528 TAG + "#registerSuggestionConnectionStatusListener"); 7529 } 7530 7531 /** 7532 * See {@link WifiManager#removeSuggestionConnectionStatusListener( 7533 * SuggestionConnectionStatusListener)} 7534 */ 7535 public void unregisterSuggestionConnectionStatusListener( 7536 @NonNull ISuggestionConnectionStatusListener listener, String packageName) { 7537 if (listener == null) { 7538 throw new IllegalArgumentException("listener must not be null"); 7539 } 7540 enforceAccessPermission(); 7541 int uid = Binder.getCallingUid(); 7542 mWifiPermissionsUtil.checkPackage(uid, packageName); 7543 if (mVerboseLoggingEnabled) { 7544 mLog.info("unregisterSuggestionConnectionStatusListener uid=%") 7545 .c(uid).flush(); 7546 } 7547 mWifiThreadRunner.post(() -> 7548 mWifiNetworkSuggestionsManager 7549 .unregisterSuggestionConnectionStatusListener(listener, packageName, uid), 7550 TAG + "#unregisterSuggestionConnectionStatusListener"); 7551 } 7552 7553 /** 7554 * {@link WifiManager#addLocalOnlyConnectionFailureListener(Executor, WifiManager.LocalOnlyConnectionFailureListener)} 7555 */ 7556 @Override 7557 public void addLocalOnlyConnectionStatusListener(ILocalOnlyConnectionStatusListener listener, 7558 String packageName, String featureId) { 7559 if (listener == null) { 7560 throw new IllegalArgumentException("listener must not be null"); 7561 } 7562 7563 final int uid = Binder.getCallingUid(); 7564 mWifiPermissionsUtil.checkPackage(uid, packageName); 7565 enforceAccessPermission(); 7566 long callingIdentity = Binder.clearCallingIdentity(); 7567 try { 7568 if (!mWifiPermissionsUtil.doesUidBelongToCurrentUserOrDeviceOwner(uid)) { 7569 Log.e(TAG, "UID " + uid + " not visible to the current user"); 7570 throw new SecurityException("UID " + uid + " not visible to the current user"); 7571 } 7572 } finally { 7573 // restore calling identity 7574 Binder.restoreCallingIdentity(callingIdentity); 7575 } 7576 if (mVerboseLoggingEnabled) { 7577 mLog.info("addLocalOnlyConnectionFailureListener uid=%").c(uid).flush(); 7578 } 7579 mWifiThreadRunner.post(() -> 7580 mWifiNetworkFactory.addLocalOnlyConnectionStatusListener(listener, packageName, 7581 featureId), TAG + "#addLocalOnlyConnectionStatusListener"); 7582 } 7583 7584 /** 7585 * {@link WifiManager#removeLocalOnlyConnectionFailureListener(WifiManager.LocalOnlyConnectionFailureListener)} 7586 */ 7587 @Override 7588 public void removeLocalOnlyConnectionStatusListener(ILocalOnlyConnectionStatusListener listener, 7589 String packageName) { 7590 if (listener == null) { 7591 throw new IllegalArgumentException("listener must not be null"); 7592 } 7593 enforceAccessPermission(); 7594 int uid = Binder.getCallingUid(); 7595 mWifiPermissionsUtil.checkPackage(uid, packageName); 7596 long callingIdentity = Binder.clearCallingIdentity(); 7597 try { 7598 if (!mWifiPermissionsUtil.doesUidBelongToCurrentUserOrDeviceOwner(uid)) { 7599 Log.e(TAG, "UID " + uid + " not visible to the current user"); 7600 throw new SecurityException("UID " + uid + " not visible to the current user"); 7601 } 7602 } finally { 7603 // restore calling identity 7604 Binder.restoreCallingIdentity(callingIdentity); 7605 } 7606 if (mVerboseLoggingEnabled) { 7607 mLog.info("removeLocalOnlyConnectionFailureListener uid=%") 7608 .c(uid).flush(); 7609 } 7610 mWifiThreadRunner.post(() -> 7611 mWifiNetworkFactory.removeLocalOnlyConnectionStatusListener(listener, packageName), 7612 TAG + "#removeLocalOnlyConnectionStatusListener"); 7613 } 7614 7615 @Override 7616 public int calculateSignalLevel(int rssi) { 7617 return RssiUtil.calculateSignalLevel(mContext, rssi); 7618 } 7619 7620 /** 7621 * See {@link WifiManager#setPnoScanState(int)} 7622 */ 7623 @Override 7624 public void setPnoScanEnabled(boolean enabled, boolean enablePnoScanAfterWifiToggle, 7625 String packageName) { 7626 int callingUid = Binder.getCallingUid(); 7627 boolean hasPermission = mWifiPermissionsUtil.checkNetworkSettingsPermission(callingUid) 7628 || mWifiPermissionsUtil.checkNetworkSetupWizardPermission(callingUid); 7629 if (!hasPermission && SdkLevel.isAtLeastT()) { 7630 // MANAGE_WIFI_NETWORK_SELECTION is a new permission added in T. 7631 hasPermission = mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission( 7632 callingUid); 7633 } 7634 if (!hasPermission) { 7635 throw new SecurityException("Uid " + callingUid 7636 + " is not allowed to set PNO scan state"); 7637 } 7638 7639 if (mVerboseLoggingEnabled) { 7640 Log.v(TAG, "setPnoScanEnabled " + Binder.getCallingUid() + " enabled=" + enabled 7641 + ", enablePnoScanAfterWifiToggle=" + enablePnoScanAfterWifiToggle); 7642 } 7643 mLastCallerInfoManager.put( 7644 WifiManager.API_SET_PNO_SCAN_ENABLED, 7645 Process.myTid(), Binder.getCallingUid(), Binder.getCallingPid(), packageName, 7646 enabled); 7647 mWifiThreadRunner.post(() -> { 7648 mWifiConnectivityManager.setPnoScanEnabledByFramework(enabled, 7649 enablePnoScanAfterWifiToggle); 7650 }, TAG + "#setPnoScanEnabled"); 7651 } 7652 7653 /** 7654 * See {@link WifiManager#setExternalPnoScanRequest(List, int[], Executor, 7655 * WifiManager.PnoScanResultsCallback)}. 7656 */ 7657 @Override 7658 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 7659 public void setExternalPnoScanRequest(@NonNull IBinder binder, 7660 @NonNull IPnoScanResultsCallback callback, 7661 @NonNull List<WifiSsid> ssids, @NonNull int[] frequencies, 7662 @NonNull String packageName, @NonNull String featureId) { 7663 if (!SdkLevel.isAtLeastT()) { 7664 throw new UnsupportedOperationException("SDK level too old"); 7665 } 7666 if (binder == null) throw new IllegalArgumentException("binder cannot be null"); 7667 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 7668 if (ssids == null || ssids.isEmpty()) throw new IllegalStateException( 7669 "Ssids can't be null or empty"); 7670 if (ssids.size() > 2) { 7671 throw new IllegalArgumentException("Ssid list can't be greater than 2"); 7672 } 7673 if (frequencies == null) { 7674 throw new IllegalArgumentException("frequencies should not be null"); 7675 } 7676 if (frequencies.length > 10) { 7677 throw new IllegalArgumentException("Length of frequencies must be smaller than 10"); 7678 } 7679 int uid = Binder.getCallingUid(); 7680 mWifiPermissionsUtil.checkPackage(uid, packageName); 7681 if (!mWifiPermissionsUtil.checkRequestCompanionProfileAutomotiveProjectionPermission(uid) 7682 || !mWifiPermissionsUtil.checkCallersLocationPermissionInManifest(uid, false)) { 7683 throw new SecurityException(TAG + " Caller uid " + uid + " has no permission"); 7684 } 7685 if (mVerboseLoggingEnabled) { 7686 mLog.info("setExternalPnoScanRequest uid=%").c(uid).flush(); 7687 } 7688 mWifiThreadRunner.post(() -> { 7689 try { 7690 if (!isPnoSupported()) { 7691 callback.onRegisterFailed(REGISTER_PNO_CALLBACK_PNO_NOT_SUPPORTED); 7692 return; 7693 } 7694 mWifiConnectivityManager.setExternalPnoScanRequest( 7695 uid, packageName, binder, callback, ssids, frequencies); 7696 } catch (RemoteException e) { 7697 Log.e(TAG, e.getMessage(), e); 7698 } 7699 }, TAG + "#setExternalPnoScanRequest"); 7700 } 7701 7702 /** 7703 * See {@link WifiManager#clearExternalPnoScanRequest()} 7704 */ 7705 @Override 7706 public void clearExternalPnoScanRequest() { 7707 int uid = Binder.getCallingUid(); 7708 if (!SdkLevel.isAtLeastT()) { 7709 throw new UnsupportedOperationException(); 7710 } 7711 if (mVerboseLoggingEnabled) { 7712 mLog.info("setExternalPnoScanRequest uid=%").c(uid).flush(); 7713 } 7714 mWifiThreadRunner.post(() -> { 7715 mWifiConnectivityManager.clearExternalPnoScanRequest(uid); 7716 }, TAG + "#clearExternalPnoScanRequest"); 7717 } 7718 7719 /** 7720 * See {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}. 7721 */ 7722 @Override 7723 public void getLastCallerInfoForApi(int apiType, @NonNull ILastCallerListener listener) { 7724 if (listener == null) { 7725 throw new IllegalArgumentException("listener should not be null"); 7726 } 7727 if (apiType < WifiManager.API_SCANNING_ENABLED || apiType > WifiManager.API_MAX) { 7728 throw new IllegalArgumentException("Invalid apiType " + apiType); 7729 } 7730 int uid = Binder.getCallingUid(); 7731 if (!mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) 7732 && !mWifiPermissionsUtil.checkNetworkStackPermission(uid) 7733 && !mWifiPermissionsUtil.checkMainlineNetworkStackPermission(uid)) { 7734 throw new SecurityException("Caller uid " + uid + " has no permission"); 7735 } 7736 7737 if (mVerboseLoggingEnabled) { 7738 Log.v(TAG, "getLastCallerInfoForApi " + Binder.getCallingUid()); 7739 } 7740 mWifiThreadRunner.post(() -> { 7741 LastCallerInfoManager.LastCallerInfo lastCallerInfo = 7742 mLastCallerInfoManager.get(apiType); 7743 try { 7744 if (lastCallerInfo == null) { 7745 listener.onResult(null, false); 7746 return; 7747 } 7748 listener.onResult(lastCallerInfo.getPackageName(), lastCallerInfo.getToggleState()); 7749 } catch (RemoteException e) { 7750 Log.e(TAG, e.getMessage(), e); 7751 } 7752 }, TAG + "#getLastCallerInfoForApi"); 7753 } 7754 7755 /** 7756 * See {@link android.net.wifi.WifiManager#setWifiConnectedNetworkScorer(Executor, 7757 * WifiManager.WifiConnectedNetworkScorer)} 7758 * 7759 * @param binder IBinder instance to allow cleanup if the app dies. 7760 * @param scorer Wifi connected network scorer to set. 7761 * @return true Scorer is set successfully. 7762 * 7763 * @throws RemoteException if remote exception happens 7764 * @throws IllegalArgumentException if the arguments are null or invalid 7765 */ 7766 @Override 7767 public boolean setWifiConnectedNetworkScorer(IBinder binder, 7768 IWifiConnectedNetworkScorer scorer) { 7769 if (binder == null) { 7770 throw new IllegalArgumentException("Binder must not be null"); 7771 } 7772 if (scorer == null) { 7773 throw new IllegalArgumentException("Scorer must not be null"); 7774 } 7775 mContext.enforceCallingOrSelfPermission( 7776 android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE, "WifiService"); 7777 int callingUid = Binder.getCallingUid(); 7778 if (mVerboseLoggingEnabled) { 7779 mLog.info("setWifiConnectedNetworkScorer uid=%").c(callingUid).flush(); 7780 } 7781 mWifiThreadRunner.post(() -> bindScorerService(callingUid)); 7782 // Post operation to handler thread 7783 return mWifiThreadRunner.call( 7784 () -> mActiveModeWarden.setWifiConnectedNetworkScorer(binder, scorer, callingUid), 7785 false, TAG + "#setWifiConnectedNetworkScorer"); 7786 } 7787 7788 /** 7789 * See {@link WifiManager#clearWifiConnectedNetworkScorer()} 7790 */ 7791 @Override 7792 public void clearWifiConnectedNetworkScorer() { 7793 mContext.enforceCallingOrSelfPermission( 7794 android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE, "WifiService"); 7795 if (mVerboseLoggingEnabled) { 7796 mLog.info("clearWifiConnectedNetworkScorer uid=%").c(Binder.getCallingUid()).flush(); 7797 } 7798 mWifiThreadRunner.post(() -> unbindScorerService(SCORER_BINDING_STATE_CLEARED)); 7799 // Post operation to handler thread 7800 mWifiThreadRunner.post(() -> mActiveModeWarden.clearWifiConnectedNetworkScorer(), 7801 TAG + "#clearWifiConnectedNetworkScorer"); 7802 } 7803 7804 /** 7805 * See {@link android.net.wifi.WifiManager#setScanThrottleEnabled(boolean)} 7806 */ 7807 @Override 7808 public void setScanThrottleEnabled(boolean enable) { 7809 enforceNetworkSettingsPermission(); 7810 mLog.info("setScanThrottleEnabled uid=% enable=%") 7811 .c(Binder.getCallingUid()) 7812 .c(enable).flush(); 7813 mScanRequestProxy.setScanThrottleEnabled(enable); 7814 } 7815 7816 /** 7817 * See {@link android.net.wifi.WifiManager#isScanThrottleEnabled()} 7818 */ 7819 @Override 7820 public boolean isScanThrottleEnabled() { 7821 enforceAccessPermission(); 7822 final boolean enable = mScanRequestProxy.isScanThrottleEnabled(); 7823 if (mVerboseLoggingEnabled) { 7824 mLog.info("isScanThrottleEnabled uid=% enable=%") 7825 .c(Binder.getCallingUid()).c(enable).flush(); 7826 } 7827 return enable; 7828 } 7829 7830 /** 7831 * See {@link android.net.wifi.WifiManager#setAutoWakeupEnabled(boolean)} 7832 */ 7833 @Override 7834 public void setAutoWakeupEnabled(boolean enable) { 7835 enforceNetworkSettingsPermission(); 7836 mLog.info("setWalkeupEnabled uid=% verbose=%") 7837 .c(Binder.getCallingUid()) 7838 .c(enable).flush(); 7839 long ident = Binder.clearCallingIdentity(); 7840 try { 7841 mWifiInjector.getWakeupController().setEnabled(enable); 7842 } finally { 7843 Binder.restoreCallingIdentity(ident); 7844 } 7845 } 7846 7847 /** 7848 * See {@link android.net.wifi.WifiManager#isAutoWakeupEnabled()} 7849 */ 7850 @Override 7851 public boolean isAutoWakeupEnabled() { 7852 enforceAccessPermission(); 7853 if (mVerboseLoggingEnabled) { 7854 mLog.info("isAutoWakeupEnabled uid=%").c(Binder.getCallingUid()).flush(); 7855 } 7856 long ident = Binder.clearCallingIdentity(); 7857 try { 7858 return mWifiInjector.getWakeupController().isEnabled(); 7859 } finally { 7860 Binder.restoreCallingIdentity(ident); 7861 } 7862 } 7863 7864 /** 7865 * See {@link android.net.wifi.WifiManager#setCarrierNetworkOffloadEnabled(int, boolean, boolean)} 7866 */ 7867 @Override 7868 public void setCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged, 7869 boolean enabled) { 7870 if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { 7871 throw new SecurityException(TAG + ": Permission denied"); 7872 } 7873 if (mVerboseLoggingEnabled) { 7874 mLog.info("setCarrierNetworkOffloadEnabled uid=%").c(Binder.getCallingUid()).flush(); 7875 } 7876 long ident = Binder.clearCallingIdentity(); 7877 try { 7878 mWifiCarrierInfoManager.setCarrierNetworkOffloadEnabled(subscriptionId, merged, 7879 enabled); 7880 } finally { 7881 Binder.restoreCallingIdentity(ident); 7882 } 7883 } 7884 7885 /** 7886 * See {@link android.net.wifi.WifiManager#isCarrierNetworkOffloadEnabled(int, boolean)} 7887 */ 7888 @Override 7889 public boolean isCarrierNetworkOffloadEnabled(int subId, boolean merged) { 7890 enforceAccessPermission(); 7891 if (mVerboseLoggingEnabled) { 7892 mLog.info("isCarrierNetworkOffload uid=%").c(Binder.getCallingUid()).flush(); 7893 } 7894 long ident = Binder.clearCallingIdentity(); 7895 try { 7896 return mWifiCarrierInfoManager.isCarrierNetworkOffloadEnabled(subId, merged); 7897 } finally { 7898 Binder.restoreCallingIdentity(ident); 7899 } 7900 } 7901 7902 /** 7903 * See {@link android.net.wifi.WifiManager#addSuggestionUserApprovalStatusListener(Executor, 7904 * WifiManager.SuggestionUserApprovalStatusListener)} 7905 */ 7906 @Override 7907 public void addSuggestionUserApprovalStatusListener( 7908 ISuggestionUserApprovalStatusListener listener, String packageName) { 7909 if (listener == null) { 7910 throw new NullPointerException("listener must not be null"); 7911 } 7912 final int uid = Binder.getCallingUid(); 7913 enforceAccessPermission(); 7914 mWifiPermissionsUtil.checkPackage(uid, packageName); 7915 long callingIdentity = Binder.clearCallingIdentity(); 7916 try { 7917 if (!mWifiPermissionsUtil.doesUidBelongToCurrentUserOrDeviceOwner(uid)) { 7918 Log.e(TAG, "UID " + uid + " not visible to the current user"); 7919 throw new SecurityException("UID " + uid + " not visible to the current user"); 7920 } 7921 } finally { 7922 // restore calling identity 7923 Binder.restoreCallingIdentity(callingIdentity); 7924 } 7925 if (mVerboseLoggingEnabled) { 7926 mLog.info("addSuggestionUserApprovalStatusListener uid=%").c(uid).flush(); 7927 } 7928 mWifiThreadRunner.post(() -> mWifiNetworkSuggestionsManager 7929 .addSuggestionUserApprovalStatusListener(listener, packageName, uid), 7930 TAG + "#addSuggestionUserApprovalStatusListener"); 7931 } 7932 7933 /** 7934 * See {@link android.net.wifi.WifiManager#removeSuggestionUserApprovalStatusListener( 7935 * WifiManager.SuggestionUserApprovalStatusListener)} 7936 */ 7937 @Override 7938 public void removeSuggestionUserApprovalStatusListener( 7939 ISuggestionUserApprovalStatusListener listener, String packageName) { 7940 enforceAccessPermission(); 7941 int uid = Binder.getCallingUid(); 7942 mWifiPermissionsUtil.checkPackage(uid, packageName); 7943 long callingIdentity = Binder.clearCallingIdentity(); 7944 try { 7945 if (!mWifiPermissionsUtil.doesUidBelongToCurrentUserOrDeviceOwner(uid)) { 7946 Log.e(TAG, "UID " + uid + " not visible to the current user"); 7947 throw new SecurityException("UID " + uid + " not visible to the current user"); 7948 } 7949 } finally { 7950 // restore calling identity 7951 Binder.restoreCallingIdentity(callingIdentity); 7952 } 7953 if (mVerboseLoggingEnabled) { 7954 mLog.info("removeSuggestionUserApprovalStatusListener uid=%") 7955 .c(uid).flush(); 7956 } 7957 mWifiThreadRunner.post(() -> 7958 mWifiNetworkSuggestionsManager 7959 .removeSuggestionUserApprovalStatusListener(listener, packageName, uid), 7960 TAG + "#removeSuggestionUserApprovalStatusListener"); 7961 } 7962 7963 /** 7964 * See {@link android.net.wifi.WifiManager#setEmergencyScanRequestInProgress(boolean)}. 7965 */ 7966 @Override 7967 public void setEmergencyScanRequestInProgress(boolean inProgress) { 7968 enforceNetworkStackPermission(); 7969 int uid = Binder.getCallingUid(); 7970 mLog.info("setEmergencyScanRequestInProgress uid=%").c(uid).flush(); 7971 mActiveModeWarden.setEmergencyScanRequestInProgress(inProgress); 7972 } 7973 7974 /** 7975 * See {@link android.net.wifi.WifiManager#removeAppState(int, String)}. 7976 */ 7977 @Override 7978 public void removeAppState(int targetAppUid, @NonNull String targetAppPackageName) { 7979 enforceNetworkSettingsPermission(); 7980 mLog.info("removeAppState uid=%").c(Binder.getCallingUid()).flush(); 7981 7982 mWifiThreadRunner.post(() -> { 7983 removeAppStateInternal(targetAppUid, targetAppPackageName); 7984 }, TAG + "#removeAppState"); 7985 } 7986 7987 /** 7988 * See {@link android.net.wifi.WifiManager#setWifiScoringEnabled(boolean)}. 7989 */ 7990 @Override 7991 public boolean setWifiScoringEnabled(boolean enabled) { 7992 mContext.enforceCallingOrSelfPermission( 7993 android.Manifest.permission.NETWORK_SETTINGS, "WifiService"); 7994 // Post operation to handler thread 7995 return mSettingsStore.handleWifiScoringEnabled(enabled); 7996 } 7997 7998 /** 7999 * See {@link android.net.wifi.WifiManager#storeCapturedData(Executor, IntConsumer, int, 8000 * booloan, long, long)}. 8001 */ 8002 @Override 8003 public void storeCapturedData(int triggerType, boolean isFullCapture, 8004 long triggerStartTimeMillis, long triggerStopTimeMillis, 8005 @NonNull IIntegerListener listener) { 8006 if (listener == null) { 8007 throw new IllegalArgumentException("listener should not be null"); 8008 } 8009 mContext.enforceCallingOrSelfPermission( 8010 android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE, "WifiService"); 8011 mWifiThreadRunner.post(() -> { 8012 try { 8013 listener.onResult(mWifiMetrics.storeCapturedData(triggerType, isFullCapture, 8014 triggerStartTimeMillis, triggerStopTimeMillis)); 8015 } catch (RemoteException e) { 8016 Log.e(TAG, e.getMessage(), e); 8017 } 8018 }, TAG + "#storeCapturedData"); 8019 } 8020 8021 @VisibleForTesting 8022 static boolean isValidBandForGetUsableChannels(@WifiScanner.WifiBand int band) { 8023 switch (band) { 8024 case WifiScanner.WIFI_BAND_UNSPECIFIED: 8025 case WifiScanner.WIFI_BAND_24_GHZ: 8026 case WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS: 8027 case WifiScanner.WIFI_BAND_BOTH_WITH_DFS: 8028 case WifiScanner.WIFI_BAND_6_GHZ: 8029 case WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_GHZ: 8030 case WifiScanner.WIFI_BAND_60_GHZ: 8031 case WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_60_GHZ: 8032 return true; 8033 default: 8034 return false; 8035 } 8036 } 8037 8038 private List<WifiAvailableChannel> getStoredSoftApAvailableChannels( 8039 @WifiScanner.WifiBand int band) { 8040 List<Integer> freqs = new ArrayList<>(); 8041 try { 8042 JSONArray json = 8043 new JSONArray( 8044 mSettingsConfigStore.get( 8045 WifiSettingsConfigStore.WIFI_AVAILABLE_SOFT_AP_FREQS_MHZ)); 8046 for (int i = 0; i < json.length(); i++) { 8047 freqs.add(json.getInt(i)); 8048 } 8049 } catch (JSONException e) { 8050 Log.i(TAG, "Failed to read stored JSON for available Soft AP channels: " + e); 8051 } 8052 List<WifiAvailableChannel> channels = new ArrayList<>(); 8053 for (int freq : freqs) { 8054 if ((band & ScanResult.toBand(freq)) == 0) { 8055 continue; 8056 } 8057 // TODO b/340956906: Save and retrieve channel width in config store along with 8058 // frequency. 8059 channels.add(new WifiAvailableChannel(freq, WifiAvailableChannel.OP_MODE_SAP, 8060 ScanResult.CHANNEL_WIDTH_20MHZ)); 8061 } 8062 return channels; 8063 } 8064 8065 /** 8066 * See {@link android.net.wifi.WifiManager#getUsableChannels(int, int) and 8067 * See {@link android.net.wifi.WifiManager#getAllowedChannels(int, int). 8068 * 8069 * @throws SecurityException if the caller does not have permission 8070 * or IllegalArgumentException if the band is invalid for this method. 8071 */ 8072 @Override 8073 public List<WifiAvailableChannel> getUsableChannels(@WifiScanner.WifiBand int band, 8074 @WifiAvailableChannel.OpMode int mode, @WifiAvailableChannel.Filter int filter, 8075 String packageName, Bundle extras) { 8076 final int uid = Binder.getCallingUid(); 8077 if (isPlatformOrTargetSdkLessThanU(packageName, uid)) { 8078 // Location mode must be enabled 8079 long ident = Binder.clearCallingIdentity(); 8080 try { 8081 if (!mWifiPermissionsUtil.isLocationModeEnabled()) { 8082 throw new SecurityException("Location mode is disabled for the device"); 8083 } 8084 } finally { 8085 Binder.restoreCallingIdentity(ident); 8086 } 8087 if (!mWifiPermissionsUtil.checkCallersHardwareLocationPermission(uid)) { 8088 throw new SecurityException( 8089 "UID " + uid + " does not have location h/w permission"); 8090 } 8091 } else { 8092 mWifiPermissionsUtil.enforceNearbyDevicesPermission( 8093 extras.getParcelable(WifiManager.EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE), 8094 true, TAG + " getUsableChannels"); 8095 } 8096 if (mVerboseLoggingEnabled) { 8097 mLog.info("getUsableChannels uid=% band=% mode=% filter=%").c(Binder.getCallingUid()).c( 8098 band).c(mode).c(filter).flush(); 8099 } 8100 if (!isValidBandForGetUsableChannels(band)) { 8101 throw new IllegalArgumentException("Unsupported band: " + band); 8102 } 8103 // Use stored values if the HAL isn't started and the stored country code matches. 8104 // This is to show the band availability based on the regulatory domain. 8105 if (mWifiNative.isHalSupported() && !mWifiNative.isHalStarted() 8106 && mode == WifiAvailableChannel.OP_MODE_SAP 8107 && filter == WifiAvailableChannel.FILTER_REGULATORY 8108 && TextUtils.equals( 8109 mSettingsConfigStore.get(WifiSettingsConfigStore.WIFI_SOFT_AP_COUNTRY_CODE), 8110 mCountryCode.getCountryCode())) { 8111 List<WifiAvailableChannel> storedChannels = getStoredSoftApAvailableChannels(band); 8112 if (!storedChannels.isEmpty()) { 8113 return storedChannels; 8114 } 8115 } 8116 List<WifiAvailableChannel> channels = mWifiThreadRunner.call( 8117 () -> mWifiNative.getUsableChannels(band, mode, filter), null, 8118 TAG + "#getUsableChannels"); 8119 if (channels == null) { 8120 throw new UnsupportedOperationException(); 8121 } 8122 return channels; 8123 } 8124 8125 private void resetNotificationManager() { 8126 mWifiInjector.getWifiNotificationManager().createNotificationChannels(); 8127 mWifiInjector.getOpenNetworkNotifier().clearPendingNotification(false); 8128 mWifiCarrierInfoManager.resetNotification(); 8129 mWifiNetworkSuggestionsManager.resetNotification(); 8130 mWifiInjector.getWakeupController().resetNotification(); 8131 } 8132 8133 /** 8134 * See {@link android.net.wifi.WifiManager#flushPasspointAnqpCache()}. 8135 */ 8136 @Override 8137 public void flushPasspointAnqpCache(@NonNull String packageName) { 8138 int callingUid = Binder.getCallingUid(); 8139 mWifiPermissionsUtil.checkPackage(callingUid, packageName); 8140 8141 if (!isDeviceOrProfileOwner(callingUid, packageName)) { 8142 enforceAnyPermissionOf(android.Manifest.permission.NETWORK_SETTINGS, 8143 android.Manifest.permission.NETWORK_MANAGED_PROVISIONING, 8144 android.Manifest.permission.NETWORK_CARRIER_PROVISIONING); 8145 } 8146 mWifiThreadRunner.post(mPasspointManager::clearAnqpRequestsAndFlushCache, 8147 TAG + "#flushPasspointAnqpCache"); 8148 } 8149 8150 /** 8151 * See {@link android.net.wifi.WifiManager#isWifiPasspointEnabled()}. 8152 */ 8153 @Override 8154 public boolean isWifiPasspointEnabled() { 8155 enforceAccessPermission(); 8156 8157 if (mVerboseLoggingEnabled) { 8158 mLog.info("isWifiPasspointEnabled uid=%").c(Binder.getCallingUid()).flush(); 8159 } 8160 // Post operation to handler thread 8161 return mWifiThreadRunner.call(() -> mPasspointManager.isWifiPasspointEnabled(), false, 8162 TAG + "#isWifiPasspointEnabled"); 8163 } 8164 8165 /** 8166 * See {@link android.net.wifi.WifiManager#setWifiPasspointEnabled()}. 8167 */ 8168 @Override 8169 public void setWifiPasspointEnabled(boolean enabled) { 8170 int uid = Binder.getCallingUid(); 8171 int pid = Binder.getCallingPid(); 8172 if (!isSettingsOrSuw(pid, uid)) { 8173 throw new SecurityException(TAG + ": Permission denied"); 8174 } 8175 8176 if (mVerboseLoggingEnabled) { 8177 mLog.info("setWifiPasspointEnabled uid=% pid=% enable=%") 8178 .c(uid).c(pid).c(enabled) 8179 .flush(); 8180 } 8181 8182 // Post operation to handler thread 8183 mWifiThreadRunner.post(() -> mPasspointManager.setWifiPasspointEnabled(enabled), 8184 TAG + "#setWifiPasspointEnabled" 8185 ); 8186 } 8187 8188 /** 8189 * See {@link android.net.wifi.WifiManager#isPreferredNetworkOffloadSupported()}. 8190 */ 8191 @Override 8192 public boolean isPnoSupported() { 8193 boolean featureSetSupportsPno = isFeatureSupported(WifiManager.WIFI_FEATURE_PNO); 8194 return mWifiGlobals.isSwPnoEnabled() 8195 || (mWifiGlobals.isBackgroundScanSupported() && featureSetSupportsPno); 8196 } 8197 8198 private boolean isAggressiveRoamingModeSupported() { 8199 return isFeatureSupported(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT); 8200 } 8201 8202 /** 8203 * @return true if this device supports Trust On First Use 8204 */ 8205 private boolean isTrustOnFirstUseSupported() { 8206 return isFeatureSupported(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE); 8207 } 8208 8209 /** 8210 * See {@link android.net.wifi.WifiManager#getStaConcurrencyForMultiInternetMode()}. 8211 */ 8212 @Override 8213 public @WifiManager.WifiMultiInternetMode int getStaConcurrencyForMultiInternetMode() { 8214 if (!SdkLevel.isAtLeastT()) { 8215 throw new UnsupportedOperationException(); 8216 } 8217 enforceAccessPermission(); 8218 8219 if (mVerboseLoggingEnabled) { 8220 mLog.info("getStaConcurrencyForMultiInternetMode uid=%") 8221 .c(Binder.getCallingUid()).flush(); 8222 } 8223 // Post operation to handler thread 8224 return mWifiThreadRunner.call( 8225 () -> mMultiInternetManager.getStaConcurrencyForMultiInternetMode(), 8226 WifiManager.WIFI_MULTI_INTERNET_MODE_DISABLED, 8227 TAG + "#getStaConcurrencyForMultiInternetMode"); 8228 } 8229 8230 /** 8231 * See {@link android.net.wifi.WifiManager#setStaConcurrencyForMultiInternetMode()}. 8232 */ 8233 @Override 8234 public boolean setStaConcurrencyForMultiInternetMode( 8235 @WifiManager.WifiMultiInternetMode int mode) { 8236 if (!SdkLevel.isAtLeastT()) { 8237 throw new UnsupportedOperationException(); 8238 } 8239 int uid = Binder.getCallingUid(); 8240 int pid = Binder.getCallingPid(); 8241 if (!isSettingsOrSuw(pid, uid)) { 8242 throw new SecurityException(TAG + ": Permission denied"); 8243 } 8244 8245 if (mVerboseLoggingEnabled) { 8246 mLog.info("setStaConcurrencyForMultiInternetMode uid=% pid=% mode=%") 8247 .c(uid).c(pid).c(mode) 8248 .flush(); 8249 } 8250 // Post operation to handler thread 8251 return mWifiThreadRunner.call(() -> 8252 mMultiInternetManager.setStaConcurrencyForMultiInternetMode(mode), false, 8253 TAG + "#setStaConcurrencyForMultiInternetMode"); 8254 } 8255 8256 /** 8257 * See {@link android.net.wifi.WifiManager#notifyMinimumRequiredWifiSecurityLevelChanged(int)}. 8258 */ 8259 @Override 8260 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 8261 public void notifyMinimumRequiredWifiSecurityLevelChanged(int adminMinimumSecurityLevel) { 8262 if (!SdkLevel.isAtLeastT()) { 8263 throw new UnsupportedOperationException(); 8264 } 8265 if (!Arrays.asList(DevicePolicyManager.WIFI_SECURITY_OPEN, 8266 DevicePolicyManager.WIFI_SECURITY_PERSONAL, 8267 DevicePolicyManager.WIFI_SECURITY_ENTERPRISE_EAP, 8268 DevicePolicyManager.WIFI_SECURITY_ENTERPRISE_192) 8269 .contains(adminMinimumSecurityLevel)) { 8270 throw new IllegalArgumentException("Input security level is invalid"); 8271 } 8272 if (!checkManageDeviceAdminsPermission(Binder.getCallingPid(), Binder.getCallingUid())) { 8273 throw new SecurityException("Caller does not have MANAGE_DEVICE_ADMINS permission"); 8274 } 8275 mWifiThreadRunner.post(() -> { 8276 for (ClientModeManager cmm : mActiveModeWarden.getClientModeManagers()) { 8277 WifiInfo wifiInfo = cmm.getConnectionInfo(); 8278 if (wifiInfo == null) continue; 8279 8280 //check minimum security level restriction 8281 int currentSecurityLevel = WifiInfo.convertSecurityTypeToDpmWifiSecurity( 8282 wifiInfo.getCurrentSecurityType()); 8283 8284 // Unknown security type is permitted when security type restriction is not set 8285 if (adminMinimumSecurityLevel == DevicePolicyManager.WIFI_SECURITY_OPEN 8286 && currentSecurityLevel == WifiInfo.DPM_SECURITY_TYPE_UNKNOWN) { 8287 continue; 8288 } 8289 if (adminMinimumSecurityLevel > currentSecurityLevel) { 8290 cmm.disconnect(); 8291 mLog.info("disconnect admin restricted network").flush(); 8292 continue; 8293 } 8294 } 8295 }, TAG + "#notifyMinimumRequiredWifiSecurityLevelChanged"); 8296 } 8297 8298 /** 8299 * See {@link android.net.wifi.WifiManager#notifyWifiSsidPolicyChanged(WifiSsidPolicy)}. 8300 */ 8301 @Override 8302 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 8303 public void notifyWifiSsidPolicyChanged(int policyType, ParceledListSlice<WifiSsid> ssids) { 8304 if (!SdkLevel.isAtLeastT()) { 8305 throw new UnsupportedOperationException(); 8306 } 8307 if (ssids == null || ssids.getList() == null) { 8308 throw new IllegalArgumentException("SSID list may not be null"); 8309 } 8310 if (!checkManageDeviceAdminsPermission(Binder.getCallingPid(), Binder.getCallingUid())) { 8311 throw new SecurityException("Caller does not have MANAGE_DEVICE_ADMINS permission"); 8312 } 8313 mWifiThreadRunner.post(() -> { 8314 for (ClientModeManager cmm : mActiveModeWarden.getClientModeManagers()) { 8315 WifiInfo wifiInfo = cmm.getConnectionInfo(); 8316 if (wifiInfo == null) continue; 8317 8318 //skip SSID restriction check for Osu and Passpoint networks 8319 if (wifiInfo.isOsuAp() || wifiInfo.isPasspointAp()) continue; 8320 8321 WifiSsid ssid = wifiInfo.getWifiSsid(); 8322 8323 if (policyType == WifiSsidPolicy.WIFI_SSID_POLICY_TYPE_ALLOWLIST 8324 && !ssids.getList().contains(ssid)) { 8325 cmm.disconnect(); 8326 mLog.info("disconnect admin restricted network").flush(); 8327 continue; 8328 } 8329 if (policyType == WifiSsidPolicy.WIFI_SSID_POLICY_TYPE_DENYLIST 8330 && ssids.getList().contains(ssid)) { 8331 cmm.disconnect(); 8332 mLog.info("disconnect admin restricted network").flush(); 8333 continue; 8334 } 8335 } 8336 }, TAG + "#notifyWifiSsidPolicyChanged"); 8337 } 8338 8339 /** 8340 * See {@link WifiManager#replyToSimpleDialog(int, int)} 8341 */ 8342 public void replyToSimpleDialog(int dialogId, @WifiManager.DialogReply int reply) { 8343 int uid = Binder.getCallingUid(); 8344 int pid = Binder.getCallingPid(); 8345 mWifiPermissionsUtil.checkPackage(uid, mContext.getWifiDialogApkPkgName()); 8346 if (mVerboseLoggingEnabled) { 8347 mLog.info("replyToSimpleDialog uid=% pid=%" 8348 + " dialogId=% reply=%") 8349 .c(uid).c(pid).c(dialogId).c(reply) 8350 .flush(); 8351 } 8352 mWifiThreadRunner.post(() -> mWifiDialogManager.replyToSimpleDialog(dialogId, reply), 8353 TAG + "#replyToSimpleDialog"); 8354 } 8355 8356 /** 8357 * See {@link WifiManager#replyToP2pInvitationReceivedDialog(int, boolean, String)} 8358 */ 8359 @Override 8360 public void replyToP2pInvitationReceivedDialog( 8361 int dialogId, boolean accepted, @Nullable String optionalPin) { 8362 int uid = Binder.getCallingUid(); 8363 int pid = Binder.getCallingPid(); 8364 mWifiPermissionsUtil.checkPackage(uid, mContext.getWifiDialogApkPkgName()); 8365 if (mVerboseLoggingEnabled) { 8366 mLog.info("replyToP2pInvitationReceivedDialog uid=% pid=%" 8367 + " dialogId=% accepted=% optionalPin=%") 8368 .c(uid).c(pid).c(dialogId).c(accepted).c(optionalPin) 8369 .flush(); 8370 } 8371 mWifiThreadRunner.post(() -> mWifiDialogManager.replyToP2pInvitationReceivedDialog( 8372 dialogId, accepted, optionalPin), TAG + "#replyToP2pInvitationReceivedDialog" 8373 ); 8374 } 8375 8376 /** 8377 * See {@link android.net.wifi.WifiManager#addCustomDhcpOptions}. 8378 */ 8379 @Override 8380 public void addCustomDhcpOptions(@NonNull WifiSsid ssid, @NonNull byte[] oui, 8381 @NonNull ParceledListSlice<DhcpOption> options) { 8382 enforceAnyPermissionOf(android.Manifest.permission.NETWORK_SETTINGS, 8383 android.Manifest.permission.OVERRIDE_WIFI_CONFIG); 8384 if (mVerboseLoggingEnabled) { 8385 Log.v(TAG, "addCustomDhcpOptions: ssid=" 8386 + ssid + ", oui=" + Arrays.toString(oui) + ", options=" + options); 8387 } 8388 List<DhcpOption> dhcpOptionList = options == null ? null : options.getList(); 8389 mWifiThreadRunner.post(() -> mWifiConfigManager.addCustomDhcpOptions(ssid, oui, 8390 dhcpOptionList), 8391 TAG + "#addCustomDhcpOptions"); 8392 } 8393 8394 /** 8395 * See {@link android.net.wifi.WifiManager#removeCustomDhcpOptions}. 8396 */ 8397 @Override 8398 public void removeCustomDhcpOptions(@NonNull WifiSsid ssid, @NonNull byte[] oui) { 8399 enforceAnyPermissionOf(android.Manifest.permission.NETWORK_SETTINGS, 8400 android.Manifest.permission.OVERRIDE_WIFI_CONFIG); 8401 if (mVerboseLoggingEnabled) { 8402 Log.v(TAG, "removeCustomDhcpOptions: ssid=" + ssid + ", oui=" + Arrays.toString(oui)); 8403 } 8404 mWifiThreadRunner.post(() -> mWifiConfigManager.removeCustomDhcpOptions(ssid, oui), 8405 TAG + "#removeCustomDhcpOptions"); 8406 } 8407 8408 /** 8409 * See {@link android.net.wifi.WifiManager#getOemPrivilegedWifiAdminPackages 8410 */ 8411 @Override 8412 public String[] getOemPrivilegedWifiAdminPackages() { 8413 return mResourceCache 8414 .getStringArray(R.array.config_oemPrivilegedWifiAdminPackages); 8415 } 8416 8417 /** 8418 * See {@link WifiManager#reportImpactToCreateIfaceRequest(int, boolean, Executor, BiConsumer)}. 8419 */ 8420 @Override 8421 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 8422 public void reportCreateInterfaceImpact(String packageName, int interfaceType, 8423 boolean requireNewInterface, IInterfaceCreationInfoCallback callback) { 8424 if (!SdkLevel.isAtLeastT()) { 8425 throw new UnsupportedOperationException("SDK level too old"); 8426 } 8427 8428 final SparseIntArray hdmIfaceToWifiIfaceMap = new SparseIntArray() {{ 8429 put(HDM_CREATE_IFACE_STA, WIFI_INTERFACE_TYPE_STA); 8430 put(HDM_CREATE_IFACE_AP, WIFI_INTERFACE_TYPE_AP); 8431 put(HDM_CREATE_IFACE_AP_BRIDGE, WIFI_INTERFACE_TYPE_AP); 8432 put(HDM_CREATE_IFACE_P2P, WIFI_INTERFACE_TYPE_DIRECT); 8433 put(HDM_CREATE_IFACE_NAN, WIFI_INTERFACE_TYPE_AWARE); 8434 }}; 8435 final SparseIntArray wifiIfaceToHdmIfaceMap = new SparseIntArray() {{ 8436 put(WIFI_INTERFACE_TYPE_STA, HDM_CREATE_IFACE_STA); 8437 put(WIFI_INTERFACE_TYPE_AP, HDM_CREATE_IFACE_AP); 8438 put(WIFI_INTERFACE_TYPE_AWARE, HDM_CREATE_IFACE_NAN); 8439 put(WIFI_INTERFACE_TYPE_DIRECT, HDM_CREATE_IFACE_P2P); 8440 }}; 8441 8442 if (packageName == null) throw new IllegalArgumentException("Null packageName"); 8443 if (callback == null) throw new IllegalArgumentException("Null callback"); 8444 if (interfaceType != WIFI_INTERFACE_TYPE_STA && interfaceType != WIFI_INTERFACE_TYPE_AP 8445 && interfaceType != WIFI_INTERFACE_TYPE_AWARE 8446 && interfaceType != WIFI_INTERFACE_TYPE_DIRECT) { 8447 throw new IllegalArgumentException("Invalid interfaceType"); 8448 } 8449 enforceAccessPermission(); 8450 int callingUid = getMockableCallingUid(); 8451 if (!mWifiPermissionsUtil.checkManageWifiInterfacesPermission(callingUid)) { 8452 throw new SecurityException( 8453 TAG + " Uid " + callingUid + " Missing MANAGE_WIFI_INTERFACES permission"); 8454 } 8455 mWifiPermissionsUtil.checkPackage(callingUid, packageName); 8456 mWifiThreadRunner.post(() -> { 8457 List<Pair<Integer, WorkSource>> details = 8458 mHalDeviceManager.reportImpactToCreateIface( 8459 wifiIfaceToHdmIfaceMap.get(interfaceType), requireNewInterface, 8460 new WorkSource(callingUid, packageName)); 8461 try { 8462 if (details == null) { 8463 callback.onResults(false, null, null); 8464 } else { 8465 int[] interfaces = new int[details.size()]; 8466 String[] packagesForInterfaces = new String[details.size()]; 8467 int i = 0; 8468 for (Pair<Integer, WorkSource> detail: details) { 8469 interfaces[i] = hdmIfaceToWifiIfaceMap.get(detail.first); 8470 if (detail.second.size() == 1 8471 && detail.second.getUid(0) == WIFI_UID) { 8472 i++; 8473 continue; 8474 } 8475 StringBuilder packages = new StringBuilder(); 8476 for (int j = 0; j < detail.second.size(); ++j) { 8477 if (j != 0) packages.append(","); 8478 packages.append(detail.second.getPackageName(j)); 8479 mContext.getPackageManager().makeUidVisible(callingUid, 8480 detail.second.getUid(j)); 8481 } 8482 packagesForInterfaces[i] = packages.toString(); 8483 ++i; 8484 } 8485 callback.onResults(true, interfaces, packagesForInterfaces); 8486 } 8487 } catch (RemoteException e) { 8488 Log.e(TAG, 8489 "Failed calling back with results of isItPossibleToCreateInterface - " + e); 8490 } 8491 }, TAG + "#reportCreateInterfaceImpact"); 8492 } 8493 @Override 8494 public int getMaxNumberOfChannelsPerRequest() { 8495 return mResourceCache 8496 .getInteger(R.integer.config_wifiNetworkSpecifierMaxPreferredChannels); 8497 } 8498 8499 private boolean policyIdsAreUnique(List<QosPolicyParams> policies) { 8500 Set<Integer> policyIdSet = new HashSet<>(); 8501 for (QosPolicyParams policy : policies) { 8502 policyIdSet.add(policy.getPolicyId()); 8503 } 8504 return policyIdSet.size() == policies.size(); 8505 } 8506 8507 private boolean policyIdsAreUnique(int[] policyIds) { 8508 Set<Integer> policyIdSet = new HashSet<>(); 8509 for (int policyId : policyIds) { 8510 policyIdSet.add(policyId); 8511 } 8512 return policyIdSet.size() == policyIds.length; 8513 } 8514 8515 private boolean policiesHaveSameDirection(List<QosPolicyParams> policyList) { 8516 int direction = policyList.get(0).getDirection(); 8517 for (QosPolicyParams policy : policyList) { 8518 if (policy.getDirection() != direction) { 8519 return false; 8520 } 8521 } 8522 return true; 8523 } 8524 8525 private void rejectAllQosPolicies( 8526 List<QosPolicyParams> policyParamsList, IListListener listener) { 8527 try { 8528 List<Integer> statusList = new ArrayList<>(); 8529 for (QosPolicyParams policy : policyParamsList) { 8530 statusList.add(WifiManager.QOS_REQUEST_STATUS_FAILURE_UNKNOWN); 8531 } 8532 listener.onResult(statusList); 8533 } catch (RemoteException e) { 8534 Log.e(TAG, e.getMessage(), e); 8535 } 8536 } 8537 8538 /** 8539 * See {@link WifiManager#addQosPolicies(List, Executor, Consumer)}. 8540 */ 8541 @Override 8542 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 8543 public void addQosPolicies(@NonNull ParceledListSlice<QosPolicyParams> policyParamsList, 8544 @NonNull IBinder binder, @NonNull String packageName, 8545 @NonNull IListListener listener) { 8546 if (!SdkLevel.isAtLeastU()) { 8547 throw new UnsupportedOperationException("SDK level too old"); 8548 } 8549 8550 int uid = Binder.getCallingUid(); 8551 mWifiPermissionsUtil.checkPackage(uid, packageName); 8552 if (!mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) 8553 && !mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) { 8554 throw new SecurityException("Uid=" + uid + " is not allowed to add QoS policies"); 8555 } 8556 8557 Objects.requireNonNull(policyParamsList, "policyParamsList cannot be null"); 8558 Objects.requireNonNull(policyParamsList.getList(), 8559 "policyParamsList contents cannot be null"); 8560 Objects.requireNonNull(binder, "binder cannot be null"); 8561 Objects.requireNonNull(listener, "listener cannot be null"); 8562 8563 if (policyParamsList.getList().size() == 0 8564 || policyParamsList.getList().size() 8565 > WifiManager.getMaxNumberOfPoliciesPerQosRequest() 8566 || !policyIdsAreUnique(policyParamsList.getList()) 8567 || !policiesHaveSameDirection(policyParamsList.getList())) { 8568 throw new IllegalArgumentException("policyParamsList is invalid"); 8569 } 8570 8571 if (!mApplicationQosPolicyRequestHandler.isFeatureEnabled()) { 8572 Log.i(TAG, "addQosPolicies is disabled on this device"); 8573 rejectAllQosPolicies(policyParamsList.getList(), listener); 8574 return; 8575 } 8576 8577 8578 8579 if (!(SdkLevel.isAtLeastV() && isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AX)) 8580 && policyParamsList.getList().get(0).getDirection() 8581 == QosPolicyParams.DIRECTION_UPLINK) { 8582 Log.e(TAG, "Uplink QoS policies are only supported on devices with SDK >= V" 8583 + " and 11ax support"); 8584 rejectAllQosPolicies(policyParamsList.getList(), listener); 8585 return; 8586 } 8587 8588 mWifiThreadRunner.post(() -> { 8589 mApplicationQosPolicyRequestHandler.queueAddRequest( 8590 policyParamsList.getList(), listener, binder, uid); 8591 }, TAG + "#addQosPolicies"); 8592 } 8593 8594 /** 8595 * See {@link WifiManager#removeQosPolicies(int[])}. 8596 */ 8597 @Override 8598 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 8599 public void removeQosPolicies(@NonNull int[] policyIds, @NonNull String packageName) { 8600 if (!SdkLevel.isAtLeastU()) { 8601 throw new UnsupportedOperationException("SDK level too old"); 8602 } else if (!mApplicationQosPolicyRequestHandler.isFeatureEnabled()) { 8603 Log.i(TAG, "removeQosPolicies is disabled on this device"); 8604 return; 8605 } 8606 int uid = Binder.getCallingUid(); 8607 mWifiPermissionsUtil.checkPackage(uid, packageName); 8608 if (!mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) 8609 && !mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) { 8610 throw new SecurityException("Uid=" + uid + " is not allowed to remove QoS policies"); 8611 } 8612 Objects.requireNonNull(policyIds, "policyIdList cannot be null"); 8613 if (policyIds.length == 0 8614 || policyIds.length > WifiManager.getMaxNumberOfPoliciesPerQosRequest() 8615 || !policyIdsAreUnique(policyIds)) { 8616 throw new IllegalArgumentException("policyIdList is invalid"); 8617 } 8618 8619 List<Integer> policyIdList = Arrays.stream(policyIds).boxed().toList(); 8620 mWifiThreadRunner.post(() -> { 8621 mApplicationQosPolicyRequestHandler.queueRemoveRequest(policyIdList, uid); 8622 }, TAG + "#removeQosPolicies"); 8623 } 8624 8625 /** 8626 * See {@link WifiManager#removeAllQosPolicies()}. 8627 */ 8628 @Override 8629 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 8630 public void removeAllQosPolicies(@NonNull String packageName) { 8631 if (!SdkLevel.isAtLeastU()) { 8632 throw new UnsupportedOperationException("SDK level too old"); 8633 } else if (!mApplicationQosPolicyRequestHandler.isFeatureEnabled()) { 8634 Log.i(TAG, "removeAllQosPolicies is disabled on this device"); 8635 return; 8636 } 8637 int uid = Binder.getCallingUid(); 8638 mWifiPermissionsUtil.checkPackage(uid, packageName); 8639 if (!mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) 8640 && !mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) { 8641 throw new SecurityException("Uid=" + uid + " is not allowed to remove QoS policies"); 8642 } 8643 8644 mWifiThreadRunner.post(() -> { 8645 mApplicationQosPolicyRequestHandler.queueRemoveAllRequest(uid); 8646 }, TAG + "#removeAllQosPolicies"); 8647 } 8648 8649 /** 8650 * See {@link WifiManager#setLinkLayerStatsPollingInterval(int)}. 8651 */ 8652 @Override 8653 public void setLinkLayerStatsPollingInterval(int intervalMs) { 8654 if (!SdkLevel.isAtLeastT()) { 8655 throw new UnsupportedOperationException("SDK level too old"); 8656 } 8657 enforceAnyPermissionOf(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION); 8658 if (intervalMs < 0) { 8659 throw new IllegalArgumentException("intervalMs should not be smaller than 0"); 8660 } 8661 mWifiThreadRunner.post(() -> mActiveModeWarden.getPrimaryClientModeManager() 8662 .setLinkLayerStatsPollingInterval(intervalMs), 8663 TAG + "#setLinkLayerStatsPollingInterval"); 8664 } 8665 8666 /** 8667 * See {@link WifiManager#getLinkLayerStatsPollingInterval(Executor, Consumer)}. 8668 */ 8669 @Override 8670 public void getLinkLayerStatsPollingInterval(@NonNull IIntegerListener listener) { 8671 if (!SdkLevel.isAtLeastT()) { 8672 throw new UnsupportedOperationException("SDK level too old"); 8673 } 8674 if (listener == null) { 8675 throw new NullPointerException("listener should not be null"); 8676 } 8677 enforceAnyPermissionOf(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION); 8678 mWifiThreadRunner.post(() -> { 8679 try { 8680 listener.onResult(mWifiGlobals.getPollRssiIntervalMillis()); 8681 } catch (RemoteException e) { 8682 Log.e(TAG, e.getMessage(), e); 8683 } 8684 }, TAG + "#getLinkLayerStatsPollingInterval"); 8685 } 8686 8687 /** 8688 * See {@link WifiManager#setMloMode(int, Executor, Consumer)} 8689 */ 8690 @Override 8691 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 8692 public void setMloMode(@WifiManager.MloMode int mode, @NonNull IBooleanListener listener) { 8693 // SDK check. 8694 if (!SdkLevel.isAtLeastU()) { 8695 throw new UnsupportedOperationException("SDK level too old"); 8696 } 8697 // Permission check. 8698 int uid = Binder.getCallingUid(); 8699 if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) { 8700 throw new SecurityException("Uid=" + uid + " is not allowed to set MLO mode"); 8701 } 8702 // Argument check 8703 Objects.requireNonNull(listener, "listener cannot be null"); 8704 if (mode < WifiManager.MLO_MODE_DEFAULT || mode > WifiManager.MLO_MODE_LOW_POWER) { 8705 throw new IllegalArgumentException("invalid mode: " + mode); 8706 } 8707 // Set MLO mode and process error status. 8708 mWifiThreadRunner.post(() -> { 8709 try { 8710 listener.onResult(mWifiNative.setMloMode(mode) == WifiStatusCode.SUCCESS); 8711 } catch (RemoteException e) { 8712 Log.e(TAG, e.getMessage(), e); 8713 } 8714 }, TAG + "#setMloMode"); 8715 } 8716 8717 /** 8718 * See {@link WifiManager#getMloMode(Executor, Consumer)} 8719 */ 8720 @Override 8721 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 8722 public void getMloMode(IIntegerListener listener) { 8723 // SDK check. 8724 if (!SdkLevel.isAtLeastU()) { 8725 throw new UnsupportedOperationException("SDK level too old"); 8726 } 8727 // Permission check. 8728 int uid = Binder.getCallingUid(); 8729 if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) { 8730 throw new SecurityException("Uid=" + uid + " is not allowed to get MLO mode"); 8731 } 8732 // Argument check 8733 Objects.requireNonNull(listener, "listener cannot be null"); 8734 // Get MLO mode. 8735 mWifiThreadRunner.post(() -> { 8736 try { 8737 listener.onResult(mWifiNative.getMloMode()); 8738 } catch (RemoteException e) { 8739 Log.e(TAG, e.getMessage(), e); 8740 } 8741 }, TAG + "#getMloMode"); 8742 } 8743 8744 /** 8745 * See {@link WifiManager#addWifiLowLatencyLockListener(Executor, 8746 * WifiManager.WifiLowLatencyLockListener)} 8747 */ 8748 public void addWifiLowLatencyLockListener(IWifiLowLatencyLockListener listener) { 8749 if (listener == null) { 8750 throw new IllegalArgumentException(); 8751 } 8752 int callingUid = Binder.getCallingUid(); 8753 if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(callingUid) 8754 && !mWifiPermissionsUtil.checkNetworkSettingsPermission(callingUid)) { 8755 throw new SecurityException(TAG + " Uid " + callingUid 8756 + " Missing MANAGE_WIFI_NETWORK_SELECTION permission"); 8757 } 8758 if (mVerboseLoggingEnabled) { 8759 mLog.info("addWifiLowLatencyLockListener uid=%").c(Binder.getCallingUid()).flush(); 8760 } 8761 mWifiThreadRunner.post(() -> { 8762 mWifiLockManager.addWifiLowLatencyLockListener(listener); 8763 }, TAG + "#addWifiLowLatencyLockListener"); 8764 } 8765 8766 /** 8767 * See {@link WifiManager#removeWifiLowLatencyLockListener( 8768 * WifiManager.WifiLowLatencyLockListener)} 8769 */ 8770 @Override 8771 public void removeWifiLowLatencyLockListener(IWifiLowLatencyLockListener listener) { 8772 if (listener == null) { 8773 throw new IllegalArgumentException(); 8774 } 8775 if (mVerboseLoggingEnabled) { 8776 mLog.info("removeWifiLowLatencyLockListener uid=%").c(Binder.getCallingUid()).flush(); 8777 } 8778 mWifiThreadRunner.post(() -> { 8779 mWifiLockManager.removeWifiLowLatencyLockListener(listener); 8780 }, TAG + "#removeWifiLowLatencyLockListener"); 8781 } 8782 8783 private String getPackageName(Bundle extras) { 8784 // AttributionSource#getPackageName() is added in API level 31. 8785 if (!SdkLevel.isAtLeastS() || extras == null) { 8786 return PACKAGE_NAME_NOT_AVAILABLE; 8787 } 8788 AttributionSource attributionSource = extras.getParcelable( 8789 WifiManager.EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE); 8790 if (attributionSource == null) return PACKAGE_NAME_NOT_AVAILABLE; 8791 String packageName = attributionSource.getPackageName(); 8792 if (packageName == null) return PACKAGE_NAME_NOT_AVAILABLE; 8793 return packageName; 8794 } 8795 8796 /** 8797 * See {@link WifiManager#getMaxMloAssociationLinkCount(Executor, Consumer)} 8798 */ 8799 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 8800 @Override 8801 public void getMaxMloAssociationLinkCount(@NonNull IIntegerListener listener, Bundle extras) { 8802 // SDK check. 8803 if (!SdkLevel.isAtLeastU()) { 8804 throw new UnsupportedOperationException("SDK level too old"); 8805 } 8806 // Permission check. 8807 int uid = Binder.getCallingUid(); 8808 if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) { 8809 throw new SecurityException( 8810 "Caller does not have MANAGE_WIFI_NETWORK_SELECTION permission"); 8811 } 8812 8813 Objects.requireNonNull(listener, "listener cannot be null"); 8814 if (mVerboseLoggingEnabled) { 8815 mLog.info("getMaxMloAssociationLinkCount: Uid=% Package Name=%").c( 8816 Binder.getCallingUid()).c(getPackageName(extras)).flush(); 8817 } 8818 8819 mWifiThreadRunner.post(() -> { 8820 try { 8821 listener.onResult(mWifiNative.getMaxMloAssociationLinkCount( 8822 mActiveModeWarden.getPrimaryClientModeManager().getInterfaceName())); 8823 } catch (RemoteException e) { 8824 Log.e(TAG, e.getMessage(), e); 8825 } 8826 }, TAG + "#getMaxMloAssociationLinkCount"); 8827 } 8828 8829 /** 8830 * See {@link WifiManager#getMaxMloStrLinkCount(Executor, Consumer)} 8831 */ 8832 @Override 8833 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 8834 public void getMaxMloStrLinkCount(@NonNull IIntegerListener listener, Bundle extras) { 8835 // SDK check. 8836 if (!SdkLevel.isAtLeastU()) { 8837 throw new UnsupportedOperationException("SDK level too old"); 8838 } 8839 // Permission check. 8840 int uid = Binder.getCallingUid(); 8841 if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) { 8842 throw new SecurityException( 8843 "Caller does not have MANAGE_WIFI_NETWORK_SELECTION permission"); 8844 } 8845 8846 Objects.requireNonNull(listener, "listener cannot be null"); 8847 if (mVerboseLoggingEnabled) { 8848 mLog.info("getMaxMloStrLinkCount: Uid=% Package Name=%").c( 8849 Binder.getCallingUid()).c(getPackageName(extras)).flush(); 8850 } 8851 8852 mWifiThreadRunner.post(() -> { 8853 try { 8854 listener.onResult(mWifiNative.getMaxMloStrLinkCount( 8855 mActiveModeWarden.getPrimaryClientModeManager().getInterfaceName())); 8856 } catch (RemoteException e) { 8857 Log.e(TAG, e.getMessage(), e); 8858 } 8859 }, TAG + "#getMaxMloStrLinkCount"); 8860 } 8861 8862 /** 8863 * See {@link WifiManager#getSupportedSimultaneousBandCombinations(Executor, Consumer)}. 8864 */ 8865 @Override 8866 public void getSupportedSimultaneousBandCombinations(@NonNull IWifiBandsListener listener, 8867 Bundle extras) { 8868 // SDK check. 8869 if (!SdkLevel.isAtLeastU()) { 8870 throw new UnsupportedOperationException("SDK level too old"); 8871 } 8872 // Permission check. 8873 int uid = Binder.getCallingUid(); 8874 if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) { 8875 throw new SecurityException( 8876 "Caller does not have MANAGE_WIFI_NETWORK_SELECTION permission"); 8877 } 8878 // Argument check. 8879 Objects.requireNonNull(listener, "listener cannot be null"); 8880 if (mVerboseLoggingEnabled) { 8881 mLog.info("getSupportedSimultaneousBandCombinations: Uid=% Package Name=%").c( 8882 Binder.getCallingUid()).c(getPackageName(extras)).flush(); 8883 } 8884 // Get supported band combinations from chip. 8885 mWifiThreadRunner.post(() -> { 8886 try { 8887 Set<List<Integer>> bandsSet = mWifiNative.getSupportedBandCombinations( 8888 mActiveModeWarden.getPrimaryClientModeManager().getInterfaceName()); 8889 if (bandsSet == null) { 8890 listener.onResult(new WifiBands[0]); 8891 return; 8892 } 8893 WifiBands[] supportedBands = new WifiBands[bandsSet.size()]; 8894 int i = 0; 8895 for (List<Integer> bands : bandsSet) { 8896 supportedBands[i] = new WifiBands(); 8897 supportedBands[i].bands = bands.stream().mapToInt( 8898 Integer::intValue).toArray(); 8899 i++; 8900 } 8901 listener.onResult(supportedBands); 8902 } catch (RemoteException e) { 8903 Log.e(TAG, e.getMessage(), e); 8904 } 8905 }, TAG + "#getSupportedSimultaneousBandCombinations"); 8906 } 8907 8908 /** 8909 * Set the mock wifi service for testing 8910 */ 8911 public void setMockWifiService(String serviceName) { 8912 int uid = Binder.getCallingUid(); 8913 if (!mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { 8914 throw new SecurityException(TAG + " Uid " + uid 8915 + " Missing NETWORK_SETTINGS permission"); 8916 } 8917 mWifiNative.setMockWifiService(serviceName); 8918 } 8919 8920 /** 8921 * Set the mock wifi methods for testing 8922 */ 8923 public boolean setMockWifiMethods(String methods) { 8924 int uid = Binder.getCallingUid(); 8925 if (!mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { 8926 throw new SecurityException(TAG + " Uid " + uid 8927 + " Missing NETWORK_SETTINGS permission"); 8928 } 8929 return mWifiNative.setMockWifiMethods(methods); 8930 } 8931 8932 /** 8933 * See {@link WifiManager#setWepAllowed(boolean)}. 8934 */ 8935 @Override 8936 public void setWepAllowed(boolean isAllowed) { 8937 int callingUid = Binder.getCallingUid(); 8938 if (!mWifiPermissionsUtil.checkNetworkSettingsPermission(callingUid)) { 8939 throw new SecurityException("Uid " + callingUid 8940 + " is not allowed to set wifi web allowed by user"); 8941 } 8942 mLog.info("setWepAllowed=% uid=%").c(isAllowed).c(callingUid).flush(); 8943 mSettingsConfigStore.put(WIFI_WEP_ALLOWED, isAllowed); 8944 } 8945 8946 /** 8947 * @deprecated Use mWepNetworkUsageController.handleWepAllowedChanged() instead. 8948 */ 8949 private void handleWepAllowedChanged(boolean isAllowed) { 8950 mWifiGlobals.setWepAllowed(isAllowed); 8951 if (!isAllowed) { 8952 for (ClientModeManager clientModeManager 8953 : mActiveModeWarden.getClientModeManagers()) { 8954 if (!(clientModeManager instanceof ConcreteClientModeManager)) { 8955 continue; 8956 } 8957 ConcreteClientModeManager cmm = (ConcreteClientModeManager) clientModeManager; 8958 WifiInfo info = cmm.getConnectionInfo(); 8959 if (info != null 8960 && info.getCurrentSecurityType() == WifiInfo.SECURITY_TYPE_WEP) { 8961 clientModeManager.disconnect(); 8962 } 8963 } 8964 } 8965 } 8966 8967 /** 8968 * See {@link WifiManager#queryWepAllowed(Executor, Consumer)} 8969 */ 8970 @Override 8971 public void queryWepAllowed(@NonNull IBooleanListener listener) { 8972 if (listener == null) { 8973 throw new IllegalArgumentException("listener should not be null"); 8974 } 8975 int callingUid = Binder.getCallingUid(); 8976 if (!mWifiPermissionsUtil.checkNetworkSettingsPermission(callingUid)) { 8977 throw new SecurityException("Uid " + callingUid 8978 + " is not allowed to get wifi web allowed by user"); 8979 } 8980 mWifiThreadRunner.post(() -> { 8981 try { 8982 listener.onResult(mSettingsConfigStore.get(WIFI_WEP_ALLOWED)); 8983 } catch (RemoteException e) { 8984 Log.e(TAG, e.getMessage(), e); 8985 } 8986 }, TAG + "#setWepAllowed"); 8987 } 8988 8989 /** 8990 * See {@link WifiManager#enableMscs(MscsParams)} 8991 */ 8992 @Override 8993 public void enableMscs(@NonNull MscsParams mscsParams) { 8994 int uid = Binder.getCallingUid(); 8995 if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) { 8996 throw new SecurityException( 8997 "UID=" + uid + " is not allowed to set network selection config"); 8998 } 8999 Objects.requireNonNull(mscsParams); 9000 mWifiThreadRunner.post(() -> { 9001 List<ClientModeManager> clientModeManagers = 9002 mActiveModeWarden.getInternetConnectivityClientModeManagers(); 9003 for (ClientModeManager cmm : clientModeManagers) { 9004 mWifiNative.enableMscs(mscsParams, cmm.getInterfaceName()); 9005 } 9006 }, TAG + "#enableMscs"); 9007 } 9008 9009 /** 9010 * See {@link WifiManager#disableMscs()} 9011 */ 9012 @Override 9013 public void disableMscs() { 9014 int uid = Binder.getCallingUid(); 9015 if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) { 9016 throw new SecurityException( 9017 "UID=" + uid + " is not allowed to set network selection config"); 9018 } 9019 mWifiThreadRunner.post(() -> { 9020 List<ClientModeManager> clientModeManagers = 9021 mActiveModeWarden.getInternetConnectivityClientModeManagers(); 9022 for (ClientModeManager cmm : clientModeManagers) { 9023 mWifiNative.disableMscs(cmm.getInterfaceName()); 9024 } 9025 }, TAG + "#disableMscs"); 9026 } 9027 9028 /** 9029 * See {@link android.net.wifi.WifiManager#setSendDhcpHostnameRestriction(int)}. 9030 */ 9031 public void setSendDhcpHostnameRestriction(@NonNull String packageName, 9032 @WifiManager.SendDhcpHostnameRestriction int restriction) { 9033 int callingUid = Binder.getCallingUid(); 9034 int callingPid = Binder.getCallingPid(); 9035 if (mVerboseLoggingEnabled) { 9036 mLog.info("setSendDhcpHostnameRestriction:% uid=% package=%").c(restriction) 9037 .c(callingUid).c(packageName).flush(); 9038 } 9039 if ((restriction 9040 & ~WifiManager.FLAG_SEND_DHCP_HOSTNAME_RESTRICTION_OPEN 9041 & ~WifiManager.FLAG_SEND_DHCP_HOSTNAME_RESTRICTION_SECURE) != 0) { 9042 throw new IllegalArgumentException("Unknown dhcp hostname restriction flags: " 9043 + restriction); 9044 } 9045 if (!isSettingsOrSuw(callingPid, callingUid) 9046 && !mWifiPermissionsUtil.isDeviceOwner(callingUid, packageName)) { 9047 throw new SecurityException("Uid " + callingUid 9048 + " is not allowed to query the global dhcp hostname restriction"); 9049 } 9050 mWifiThreadRunner.post(() -> mWifiGlobals.setSendDhcpHostnameRestriction(restriction), 9051 TAG + "#setSendDhcpHostnameRestriction"); 9052 } 9053 9054 /** 9055 * See {@link WifiManager#querySendDhcpHostnameRestriction(Executor, IntConsumer)} 9056 */ 9057 @Override 9058 public void querySendDhcpHostnameRestriction(@NonNull String packageName, 9059 @NonNull IIntegerListener listener) { 9060 if (listener == null) { 9061 throw new IllegalArgumentException("listener should not be null"); 9062 } 9063 int callingUid = Binder.getCallingUid(); 9064 int callingPid = Binder.getCallingPid(); 9065 if (mVerboseLoggingEnabled) { 9066 mLog.info("querySendDhcpHostnameRestriction: uid=% package=%") 9067 .c(callingUid).c(packageName).flush(); 9068 } 9069 if (!isSettingsOrSuw(callingPid, callingUid) 9070 && !mWifiPermissionsUtil.isDeviceOwner(callingUid, packageName)) { 9071 throw new SecurityException("Uid " + callingUid 9072 + " is not allowed to query the global dhcp hostname restriction"); 9073 } 9074 mWifiThreadRunner.post(() -> { 9075 try { 9076 listener.onResult(mWifiGlobals.getSendDhcpHostnameRestriction()); 9077 } catch (RemoteException e) { 9078 Log.e(TAG, e.getMessage(), e); 9079 } 9080 }, TAG + "#querySendDhcpHostnameRestriction"); 9081 } 9082 9083 /** 9084 * See {@link WifiManager#setPerSsidRoamingMode(WifiSsid, int)} 9085 */ 9086 @Override 9087 public void setPerSsidRoamingMode(WifiSsid ssid, @RoamingMode int roamingMode, 9088 @NonNull String packageName) { 9089 if (!SdkLevel.isAtLeastV()) { 9090 throw new UnsupportedOperationException("SDK level too old"); 9091 } 9092 if (!isAggressiveRoamingModeSupported() && roamingMode == ROAMING_MODE_AGGRESSIVE) { 9093 throw new UnsupportedOperationException("Aggressive roaming mode not supported"); 9094 } 9095 Objects.requireNonNull(ssid, "ssid cannot be null"); 9096 Objects.requireNonNull(packageName, "packageName cannot be null"); 9097 9098 if (roamingMode < WifiManager.ROAMING_MODE_NONE 9099 || roamingMode > WifiManager.ROAMING_MODE_AGGRESSIVE) { 9100 throw new IllegalArgumentException("invalid roaming mode: " + roamingMode); 9101 } 9102 9103 int uid = Binder.getCallingUid(); 9104 mWifiPermissionsUtil.checkPackage(uid, packageName); 9105 boolean isDeviceOwner = mWifiPermissionsUtil.isOrganizationOwnedDeviceAdmin( 9106 uid, packageName); 9107 if (!isDeviceOwner && !mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) 9108 && !mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) { 9109 throw new SecurityException("Uid=" + uid + " is not allowed to add roaming policies"); 9110 } 9111 9112 //Store Roaming Mode per ssid 9113 mWifiThreadRunner.post(() -> { 9114 mWifiInjector.getWifiRoamingModeManager().setPerSsidRoamingMode(ssid, 9115 roamingMode, isDeviceOwner); 9116 }, TAG + "#setPerSsidRoamingMode"); 9117 } 9118 9119 /** 9120 * See {@link WifiManager#removePerSsidRoamingMode(WifiSsid)} 9121 */ 9122 @Override 9123 public void removePerSsidRoamingMode(WifiSsid ssid, @NonNull String packageName) { 9124 if (!SdkLevel.isAtLeastV()) { 9125 throw new UnsupportedOperationException("SDK level too old"); 9126 } 9127 Objects.requireNonNull(ssid, "ssid cannot be null"); 9128 Objects.requireNonNull(packageName, "packageName cannot be null"); 9129 9130 int uid = Binder.getCallingUid(); 9131 mWifiPermissionsUtil.checkPackage(uid, packageName); 9132 boolean isDeviceOwner = mWifiPermissionsUtil.isOrganizationOwnedDeviceAdmin( 9133 uid, packageName); 9134 if (!isDeviceOwner && !mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) 9135 && !mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) { 9136 throw new SecurityException("Uid=" + uid + " is not allowed " 9137 + "to remove roaming policies"); 9138 } 9139 9140 // Remove Roaming Mode per ssid 9141 mWifiThreadRunner.post(() -> { 9142 mWifiInjector.getWifiRoamingModeManager().removePerSsidRoamingMode( 9143 ssid, isDeviceOwner); 9144 }, TAG + "#removePerSsidRoamingMode"); 9145 } 9146 9147 /** 9148 * See {@link WifiManager#getPerSsidRoamingModes(Executor, Consumer)} 9149 */ 9150 @Override 9151 public void getPerSsidRoamingModes(@NonNull String packageName, 9152 @NonNull IMapListener listener) { 9153 if (!SdkLevel.isAtLeastV()) { 9154 throw new UnsupportedOperationException("SDK level too old"); 9155 } 9156 Objects.requireNonNull(packageName, "packageName cannot be null"); 9157 Objects.requireNonNull(listener, "listener cannot be null"); 9158 9159 int uid = Binder.getCallingUid(); 9160 boolean isDeviceOwner = mWifiPermissionsUtil.isOrganizationOwnedDeviceAdmin( 9161 uid, packageName); 9162 mWifiPermissionsUtil.checkPackage(uid, packageName); 9163 if (!isDeviceOwner && !mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) 9164 && !mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) { 9165 throw new SecurityException("Uid=" + uid + " is not allowed to get roaming policies"); 9166 } 9167 9168 // Get Roaming Modes per ssid 9169 mWifiThreadRunner.post(() -> { 9170 try { 9171 Map<String, Integer> roamingPolicies = 9172 mWifiInjector.getWifiRoamingModeManager().getPerSsidRoamingModes( 9173 isDeviceOwner); 9174 listener.onResult(roamingPolicies); 9175 } catch (RemoteException e) { 9176 Log.e(TAG, e.getMessage(), e); 9177 } 9178 }, TAG + "#getPerSsidRoamingModes"); 9179 } 9180 9181 /** 9182 * See {@link WifiManager#getTwtCapabilities(Executor, Consumer)} 9183 */ 9184 @Override 9185 public void getTwtCapabilities(ITwtCapabilitiesListener listener, Bundle extras) { 9186 if (!SdkLevel.isAtLeastV()) { 9187 throw new UnsupportedOperationException("SDK level too old"); 9188 } 9189 enforceAnyPermissionOf(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION); 9190 if (mVerboseLoggingEnabled) { 9191 mLog.info("getTwtCapabilities: Uid=% Package Name=%").c(Binder.getCallingUid()).c( 9192 getPackageName(extras)).flush(); 9193 } 9194 if (listener == null) { 9195 throw new IllegalArgumentException("listener should not be null"); 9196 } 9197 mWifiThreadRunner.post(() -> { 9198 mTwtManager.getTwtCapabilities( 9199 mActiveModeWarden.getPrimaryClientModeManager().getInterfaceName(), listener); 9200 }, TAG + "#getTwtCapabilities"); 9201 } 9202 9203 /** 9204 * See {@link WifiManager#setupTwtSession(TwtRequest, Executor, TwtSessionCallback)} 9205 */ 9206 @Override 9207 public void setupTwtSession(TwtRequest twtRequest, ITwtCallback iTwtCallback, Bundle extras) { 9208 if (!SdkLevel.isAtLeastV()) { 9209 throw new UnsupportedOperationException("SDK level too old"); 9210 } 9211 if (iTwtCallback == null) { 9212 throw new IllegalArgumentException("Callback should not be null"); 9213 } 9214 if (twtRequest == null) { 9215 throw new IllegalArgumentException("twtRequest should not be null"); 9216 } 9217 enforceAnyPermissionOf(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION); 9218 int callingUid = Binder.getCallingUid(); 9219 if (mVerboseLoggingEnabled) { 9220 mLog.info("setupTwtSession: Uid=% Package Name=%").c(callingUid).c( 9221 getPackageName(extras)).flush(); 9222 } 9223 mWifiThreadRunner.post(() -> { 9224 try { 9225 String bssid = mActiveModeWarden.getPrimaryClientModeManager().getConnectedBssid(); 9226 if (!mActiveModeWarden.getPrimaryClientModeManager().isConnected() 9227 || bssid == null) { 9228 iTwtCallback.onFailure(TwtSessionCallback.TWT_ERROR_CODE_NOT_AVAILABLE); 9229 return; 9230 } 9231 mTwtManager.setupTwtSession( 9232 mActiveModeWarden.getPrimaryClientModeManager().getInterfaceName(), 9233 twtRequest, iTwtCallback, callingUid, bssid); 9234 } catch (RemoteException e) { 9235 Log.e(TAG, e.getMessage(), e); 9236 } 9237 }, TAG + "#setupTwtSession"); 9238 } 9239 9240 /** 9241 /** 9242 * See {@link TwtSession#getStats(Executor, Consumer)}} 9243 */ 9244 @Override 9245 public void getStatsTwtSession(int sessionId, ITwtStatsListener iTwtStatsListener, 9246 Bundle extras) { 9247 if (!SdkLevel.isAtLeastV()) { 9248 throw new UnsupportedOperationException("SDK level too old"); 9249 } 9250 if (iTwtStatsListener == null) { 9251 throw new IllegalArgumentException("Callback should not be null"); 9252 } 9253 enforceAnyPermissionOf(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION); 9254 if (mVerboseLoggingEnabled) { 9255 mLog.info("getStatsTwtSession: Uid=% Package Name=%").c(Binder.getCallingUid()).c( 9256 getPackageName(extras)).flush(); 9257 } 9258 mWifiThreadRunner.post(() -> { 9259 mTwtManager.getStatsTwtSession( 9260 mActiveModeWarden.getPrimaryClientModeManager().getInterfaceName(), 9261 iTwtStatsListener, sessionId); 9262 }, TAG + "#getStatsTwtSession"); 9263 } 9264 9265 /** 9266 * See {@link TwtSession#teardown()} 9267 */ 9268 @Override 9269 public void teardownTwtSession(int sessionId, Bundle extras) { 9270 if (!SdkLevel.isAtLeastV()) { 9271 throw new UnsupportedOperationException("SDK level too old"); 9272 } 9273 enforceAnyPermissionOf(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION); 9274 if (mVerboseLoggingEnabled) { 9275 mLog.info("teardownTwtSession: Uid=% Package Name=%").c(Binder.getCallingUid()).c( 9276 getPackageName(extras)).flush(); 9277 } 9278 mWifiThreadRunner.post(() -> { 9279 mTwtManager.tearDownTwtSession( 9280 mActiveModeWarden.getPrimaryClientModeManager().getInterfaceName(), sessionId); 9281 }, TAG + "#teardownTwtSession"); 9282 } 9283 9284 /** 9285 * See {@link WifiManager#setD2dAllowedWhenInfraStaDisabled(boolean)}. 9286 */ 9287 @Override 9288 public void setD2dAllowedWhenInfraStaDisabled(boolean isAllowed) { 9289 int callingUid = Binder.getCallingUid(); 9290 if (!isSettingsOrSuw(Binder.getCallingPid(), callingUid)) { 9291 throw new SecurityException("Uid " + callingUid 9292 + " is not allowed to set d2d allowed when infra Sta is disabled"); 9293 } 9294 mLog.info("setD2dAllowedWhenInfraStaDisabled=% uid=%").c(isAllowed).c(callingUid).flush(); 9295 mWifiThreadRunner.post( 9296 () -> mSettingsConfigStore.put(D2D_ALLOWED_WHEN_INFRA_STA_DISABLED, isAllowed), 9297 TAG + "#setD2dAllowedWhenInfraStaDisabled"); 9298 } 9299 9300 /** 9301 * See {@link WifiManager#queryD2dAllowedWhenInfraStaDisabled(Executor, Consumer)} 9302 */ 9303 @Override 9304 public void queryD2dAllowedWhenInfraStaDisabled(@NonNull IBooleanListener listener) { 9305 if (listener == null) { 9306 throw new IllegalArgumentException("listener should not be null"); 9307 } 9308 mWifiThreadRunner.post(() -> { 9309 try { 9310 listener.onResult(mSettingsConfigStore.get(D2D_ALLOWED_WHEN_INFRA_STA_DISABLED)); 9311 } catch (RemoteException e) { 9312 Log.e(TAG, e.getMessage(), e); 9313 } 9314 }, TAG + "#queryD2dAllowedWhenInfraStaDisabled"); 9315 } 9316 9317 /** 9318 * See {@link WifiManager#setAutojoinDisallowedSecurityTypes(int)} 9319 * @param restrictions The autojoin restriction security types to be set. 9320 * @throws SecurityException if the caller does not have permission. 9321 * @throws IllegalArgumentException if the arguments are null or invalid 9322 */ 9323 @Override 9324 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 9325 public void setAutojoinDisallowedSecurityTypes(int restrictions, @NonNull Bundle extras) { 9326 // SDK check. 9327 if (!SdkLevel.isAtLeastT()) { 9328 throw new UnsupportedOperationException("SDK level too old"); 9329 } 9330 // Check null argument 9331 if (extras == null) { 9332 throw new IllegalArgumentException("extras cannot be null"); 9333 } 9334 // Check invalid argument 9335 if ((restrictions & (0x1 << WifiInfo.SECURITY_TYPE_OPEN)) == 0 9336 && (restrictions & (0x1 << WifiInfo.SECURITY_TYPE_OWE)) != 0) { 9337 throw new IllegalArgumentException("Restricting OWE but not OPEN is not allowed"); 9338 } 9339 if ((restrictions & (0x1 << WifiInfo.SECURITY_TYPE_PSK)) == 0 9340 && (restrictions & (0x1 << WifiInfo.SECURITY_TYPE_SAE)) != 0) { 9341 throw new IllegalArgumentException("Restricting SAE but not PSK is not allowed"); 9342 } 9343 if ((restrictions & (0x1 << WifiInfo.SECURITY_TYPE_EAP)) == 0 9344 && (restrictions & (0x1 << WifiInfo.SECURITY_TYPE_EAP_WPA3_ENTERPRISE)) != 0) { 9345 throw new IllegalArgumentException( 9346 "Restricting EAP_WPA3_ENTERPRISE but not EAP is not allowed"); 9347 } 9348 // Permission check. 9349 int uid = Binder.getCallingUid(); 9350 if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid) 9351 && !mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { 9352 throw new SecurityException( 9353 "Uid=" + uid + " is not allowed to set AutoJoinRestrictionSecurityTypes"); 9354 } 9355 if (mVerboseLoggingEnabled) { 9356 mLog.info("setAutojoinDisallowedSecurityTypes uid=% Package Name=% restrictions=%") 9357 .c(uid).c(getPackageName(extras)).c(restrictions).flush(); 9358 } 9359 mWifiThreadRunner.post(() -> { 9360 mWifiConnectivityManager.setAutojoinDisallowedSecurityTypes(restrictions); 9361 }, TAG + "#setAutojoinDisallowedSecurityTypes"); 9362 } 9363 9364 /** 9365 * See {@link WifiManager#getAutojoinDisallowedSecurityTypes(Executor, Consumer)} 9366 */ 9367 @Override 9368 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 9369 public void getAutojoinDisallowedSecurityTypes(@NonNull IIntegerListener listener, 9370 @NonNull Bundle extras) { 9371 // SDK check. 9372 if (!SdkLevel.isAtLeastT()) { 9373 throw new UnsupportedOperationException("SDK level too old"); 9374 } 9375 // Argument check 9376 if (listener == null) { 9377 throw new IllegalArgumentException("listener cannot be null"); 9378 } 9379 if (extras == null) { 9380 throw new IllegalArgumentException("extras cannot be null"); 9381 } 9382 // Permission check. 9383 int uid = Binder.getCallingUid(); 9384 if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid) 9385 && !mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { 9386 throw new SecurityException( 9387 "Uid=" + uid + " is not allowed to get AutoJoinRestrictionSecurityTypes"); 9388 } 9389 if (mVerboseLoggingEnabled) { 9390 mLog.info("getAutojoinDisallowedSecurityTypes: Uid=% Package Name=%").c( 9391 Binder.getCallingUid()).c(getPackageName(extras)).flush(); 9392 } 9393 9394 mWifiThreadRunner.post(() -> { 9395 try { 9396 listener.onResult(mWifiConnectivityManager.getAutojoinDisallowedSecurityTypes()); 9397 } catch (RemoteException e) { 9398 Log.e(TAG, e.getMessage(), e); 9399 } 9400 }, TAG + "#getAutojoinDisallowedSecurityTypes"); 9401 } 9402 9403 @Override 9404 public void disallowCurrentSuggestedNetwork(@NonNull BlockingOption option, 9405 @NonNull String packageName) { 9406 Objects.requireNonNull(option, "blockingOption cannot be null"); 9407 int callingUid = Binder.getCallingUid(); 9408 mWifiPermissionsUtil.checkPackage(callingUid, packageName); 9409 if (enforceChangePermission(packageName) != MODE_ALLOWED) { 9410 throw new SecurityException("Caller does not hold CHANGE_WIFI_STATE permission"); 9411 } 9412 if (mVerboseLoggingEnabled) { 9413 mLog.info("disallowCurrentSuggestedNetwork: Uid=% Package Name=%").c( 9414 callingUid).c(option.toString()).flush(); 9415 } 9416 if (mActiveModeWarden.getWifiState() != WIFI_STATE_ENABLED) { 9417 return; 9418 } 9419 WifiInfo info = mActiveModeWarden.getConnectionInfo(); 9420 if (!packageName.equals(info.getRequestingPackageName())) { 9421 return; 9422 } 9423 mWifiThreadRunner.post( 9424 () -> mActiveModeWarden.getPrimaryClientModeManager().blockNetwork(option), 9425 "disallowCurrentSuggestedNetwork"); 9426 } 9427 9428 /** 9429 * See {@link WifiManager#isUsdSubscriberSupported()} 9430 */ 9431 @Override 9432 public boolean isUsdSubscriberSupported() { 9433 if (!Environment.isSdkAtLeastB()) { 9434 throw new UnsupportedOperationException("SDK level too old"); 9435 } 9436 int uid = getMockableCallingUid(); 9437 if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) { 9438 throw new SecurityException("App not allowed to use USD (uid = " + uid + ")"); 9439 } 9440 if (!mIsUsdSupported) { 9441 return false; 9442 } 9443 return mWifiNative.isUsdSubscriberSupported(); 9444 } 9445 9446 /** 9447 * See {@link WifiManager#isUsdPublisherSupported()} 9448 */ 9449 @Override 9450 public boolean isUsdPublisherSupported() { 9451 if (!Environment.isSdkAtLeastB()) { 9452 throw new UnsupportedOperationException("SDK level too old"); 9453 } 9454 int uid = getMockableCallingUid(); 9455 if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) { 9456 throw new SecurityException("App not allowed to use USD (uid = " + uid + ")"); 9457 } 9458 if (!mIsUsdSupported) { 9459 return false; 9460 } 9461 return mWifiNative.isUsdPublisherSupported(); 9462 } 9463 } 9464