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