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