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