1 /* 2 * Copyright (C) 2016 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.aware; 18 19 import static android.net.wifi.aware.Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_PK_PASN_128; 20 import static android.net.wifi.aware.Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_PK_PASN_256; 21 22 import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_AWARE_VERBOSE_LOGGING_ENABLED; 23 24 import android.Manifest; 25 import android.annotation.NonNull; 26 import android.content.Context; 27 import android.content.pm.PackageManager; 28 import android.net.wifi.IBooleanListener; 29 import android.net.wifi.IIntegerListener; 30 import android.net.wifi.IListListener; 31 import android.net.wifi.WifiManager; 32 import android.net.wifi.aware.AwareParams; 33 import android.net.wifi.aware.AwareResources; 34 import android.net.wifi.aware.Characteristics; 35 import android.net.wifi.aware.ConfigRequest; 36 import android.net.wifi.aware.DiscoverySession; 37 import android.net.wifi.aware.IWifiAwareDiscoverySessionCallback; 38 import android.net.wifi.aware.IWifiAwareEventCallback; 39 import android.net.wifi.aware.IWifiAwareMacAddressProvider; 40 import android.net.wifi.aware.IWifiAwareManager; 41 import android.net.wifi.aware.PublishConfig; 42 import android.net.wifi.aware.SubscribeConfig; 43 import android.os.Binder; 44 import android.os.Build; 45 import android.os.Bundle; 46 import android.os.Handler; 47 import android.os.HandlerThread; 48 import android.os.IBinder; 49 import android.os.ParcelFileDescriptor; 50 import android.os.Process; 51 import android.os.RemoteException; 52 import android.util.Log; 53 import android.util.SparseArray; 54 import android.util.SparseIntArray; 55 56 import com.android.modules.utils.build.SdkLevel; 57 import com.android.server.wifi.BuildProperties; 58 import com.android.server.wifi.Clock; 59 import com.android.server.wifi.FrameworkFacade; 60 import com.android.server.wifi.InterfaceConflictManager; 61 import com.android.server.wifi.RunnerHandler; 62 import com.android.server.wifi.SystemBuildProperties; 63 import com.android.server.wifi.WifiInjector; 64 import com.android.server.wifi.WifiSettingsConfigStore; 65 import com.android.server.wifi.WifiThreadRunner; 66 import com.android.server.wifi.hal.WifiNanIface.NanStatusCode; 67 import com.android.server.wifi.util.NetdWrapper; 68 import com.android.server.wifi.util.WifiPermissionsUtil; 69 import com.android.server.wifi.util.WifiPermissionsWrapper; 70 import com.android.wifi.resources.R; 71 72 import java.io.FileDescriptor; 73 import java.io.PrintWriter; 74 75 /** 76 * Implementation of the IWifiAwareManager AIDL interface. Performs validity 77 * (permission and clientID-UID mapping) checks and delegates execution to the 78 * WifiAwareStateManager singleton handler. Limited state to feedback which has to 79 * be provided instantly: client and session IDs. 80 */ 81 public class WifiAwareServiceImpl extends IWifiAwareManager.Stub { 82 private static final String TAG = "WifiAwareService"; 83 private boolean mVerboseLoggingEnabled = false; 84 private boolean mVerboseHalLoggingEnabled = false; 85 86 private WifiPermissionsUtil mWifiPermissionsUtil; 87 private WifiAwareStateManager mStateManager; 88 private WifiAwareNativeManager mWifiAwareNativeManager; 89 private WifiAwareNativeApi mWifiAwareNativeApi; 90 private WifiAwareNativeCallback mWifiAwareNativeCallback; 91 private WifiAwareShellCommand mShellCommand; 92 private Handler mHandler; 93 94 private final Object mLock = new Object(); 95 private final SparseArray<IBinder.DeathRecipient> mDeathRecipientsByClientId = 96 new SparseArray<>(); 97 private int mNextClientId = 1; 98 private final SparseIntArray mUidByClientId = new SparseIntArray(); 99 private final Context mContext; 100 private final BuildProperties mBuildProperties; 101 private final FrameworkFacade mFrameworkFacade; 102 WifiAwareServiceImpl(Context context)103 public WifiAwareServiceImpl(Context context) { 104 mContext = context; 105 mBuildProperties = new SystemBuildProperties(); 106 mFrameworkFacade = new FrameworkFacade(); 107 } 108 109 /** 110 * Proxy for the final native call of the parent class. Enables mocking of 111 * the function. 112 */ getMockableCallingUid()113 public int getMockableCallingUid() { 114 return getCallingUid(); 115 } 116 117 /** 118 * Start the service: allocate a new thread (for now), start the handlers of 119 * the components of the service. 120 */ start(HandlerThread handlerThread, WifiAwareStateManager awareStateManager, WifiAwareShellCommand awareShellCommand, WifiAwareMetrics awareMetrics, WifiPermissionsUtil wifiPermissionsUtil, WifiPermissionsWrapper permissionsWrapper, WifiSettingsConfigStore settingsConfigStore, WifiAwareNativeManager wifiAwareNativeManager, WifiAwareNativeApi wifiAwareNativeApi, WifiAwareNativeCallback wifiAwareNativeCallback, NetdWrapper netdWrapper, InterfaceConflictManager interfaceConflictManager)121 public void start(HandlerThread handlerThread, WifiAwareStateManager awareStateManager, 122 WifiAwareShellCommand awareShellCommand, WifiAwareMetrics awareMetrics, 123 WifiPermissionsUtil wifiPermissionsUtil, WifiPermissionsWrapper permissionsWrapper, 124 WifiSettingsConfigStore settingsConfigStore, 125 WifiAwareNativeManager wifiAwareNativeManager, WifiAwareNativeApi wifiAwareNativeApi, 126 WifiAwareNativeCallback wifiAwareNativeCallback, NetdWrapper netdWrapper, 127 InterfaceConflictManager interfaceConflictManager) { 128 Log.i(TAG, "Starting Wi-Fi Aware service"); 129 130 mWifiPermissionsUtil = wifiPermissionsUtil; 131 mStateManager = awareStateManager; 132 mShellCommand = awareShellCommand; 133 mHandler = new RunnerHandler(handlerThread.getLooper(), mContext.getResources() 134 .getInteger(R.integer.config_wifiConfigurationWifiRunnerThresholdInMs), 135 WifiInjector.getInstance().getWifiHandlerLocalLog()); 136 mWifiAwareNativeManager = wifiAwareNativeManager; 137 mWifiAwareNativeApi = wifiAwareNativeApi; 138 mWifiAwareNativeCallback = wifiAwareNativeCallback; 139 140 mHandler.post(() -> { 141 mStateManager.start(mContext, handlerThread.getLooper(), awareMetrics, 142 wifiPermissionsUtil, permissionsWrapper, new Clock(), netdWrapper, 143 interfaceConflictManager); 144 145 settingsConfigStore.registerChangeListener( 146 WIFI_AWARE_VERBOSE_LOGGING_ENABLED, 147 (key, newValue) -> enableVerboseLogging(newValue), 148 mHandler); 149 enableVerboseLogging(settingsConfigStore.get(WIFI_AWARE_VERBOSE_LOGGING_ENABLED)); 150 }); 151 } 152 enableVerboseLogging(boolean verboseEnabled)153 private void enableVerboseLogging(boolean verboseEnabled) { 154 mVerboseHalLoggingEnabled = verboseEnabled; 155 updateVerboseLoggingEnabled(); 156 boolean vDbg = verboseEnabled || mContext.getResources() 157 .getBoolean(R.bool.config_aware_vdbg_enable_on_verbose_logging); 158 mStateManager.enableVerboseLogging(mVerboseLoggingEnabled, mVerboseLoggingEnabled, vDbg); 159 mWifiAwareNativeCallback.enableVerboseLogging(mVerboseLoggingEnabled); 160 mWifiAwareNativeManager.enableVerboseLogging(mVerboseLoggingEnabled, 161 mVerboseLoggingEnabled); 162 mWifiAwareNativeApi.enableVerboseLogging(mVerboseLoggingEnabled, vDbg); 163 } 164 165 /** 166 * Start/initialize portions of the service which require the boot stage to be complete. 167 */ startLate()168 public void startLate() { 169 Log.i(TAG, "Late initialization of Wi-Fi Aware service"); 170 updateVerboseLoggingEnabled(); 171 mHandler.post(() -> mStateManager.startLate()); 172 } 173 updateVerboseLoggingEnabled()174 private void updateVerboseLoggingEnabled() { 175 final int verboseAlwaysOnLevel = mContext.getResources().getInteger( 176 R.integer.config_wifiVerboseLoggingAlwaysOnLevel); 177 mVerboseLoggingEnabled = mFrameworkFacade.isVerboseLoggingAlwaysOn(verboseAlwaysOnLevel, 178 mBuildProperties) || mVerboseHalLoggingEnabled; 179 } 180 181 @Override isUsageEnabled()182 public boolean isUsageEnabled() { 183 enforceAccessPermission(); 184 185 return mStateManager.isUsageEnabled(); 186 } 187 188 @Override getCharacteristics()189 public Characteristics getCharacteristics() { 190 enforceAccessPermission(); 191 192 return mStateManager.getCapabilities() == null ? null 193 : mStateManager.getCapabilities().toPublicCharacteristics( 194 WifiInjector.getInstance().getDeviceConfigFacade()); 195 } 196 197 @Override getAvailableAwareResources()198 public AwareResources getAvailableAwareResources() { 199 enforceAccessPermission(); 200 return new WifiThreadRunner(mHandler) 201 .call(() -> mStateManager.getAvailableAwareResources(), null, 202 TAG + "#getAvailableAwareResources"); 203 } 204 205 @Override isDeviceAttached()206 public boolean isDeviceAttached() { 207 enforceAccessPermission(); 208 return mStateManager.isDeviceAttached(); 209 } 210 211 @Override enableInstantCommunicationMode(String callingPackage, boolean enable)212 public void enableInstantCommunicationMode(String callingPackage, boolean enable) { 213 enforceChangePermission(); 214 int uid = getMockableCallingUid(); 215 if (uid != Process.SHELL_UID && uid != Process.ROOT_UID) { 216 mWifiPermissionsUtil.checkPackage(uid, callingPackage); 217 if (!mWifiPermissionsUtil.isSystem(callingPackage, uid) 218 && !mWifiPermissionsUtil.checkConfigOverridePermission(uid)) { 219 Log.i(TAG, "enableInstantCommunicationMode not allowed for uid=" + uid); 220 return; 221 } 222 } 223 mStateManager.enableInstantCommunicationMode(enable); 224 } 225 226 @Override isInstantCommunicationModeEnabled()227 public boolean isInstantCommunicationModeEnabled() { 228 enforceAccessPermission(); 229 return mStateManager.isInstantCommModeGlobalEnable(); 230 } 231 232 @Override isSetChannelOnDataPathSupported()233 public boolean isSetChannelOnDataPathSupported() { 234 enforceAccessPermission(); 235 return mStateManager.isSetChannelOnDataPathSupported(); 236 } 237 238 @Override setAwareParams(AwareParams params)239 public void setAwareParams(AwareParams params) { 240 enforceChangePermission(); 241 int uid = getMockableCallingUid(); 242 if (!mWifiPermissionsUtil.checkConfigOverridePermission(uid)) { 243 throw new SecurityException("App not allowed to update Aware parameters " 244 + "(uid = " + uid + ")"); 245 } 246 mStateManager.setAwareParams(params); 247 } 248 249 @Override resetPairedDevices(String callingPackage)250 public void resetPairedDevices(String callingPackage) { 251 int uid = getMockableCallingUid(); 252 mWifiPermissionsUtil.checkPackage(uid, callingPackage); 253 enforceChangePermission(); 254 if (mVerboseLoggingEnabled) { 255 Log.v(TAG, "resetPairedDevices: callingPackage=" + callingPackage); 256 } 257 mStateManager.resetPairedDevices(callingPackage); 258 } 259 260 @Override removePairedDevice(String callingPackage, String alias)261 public void removePairedDevice(String callingPackage, String alias) { 262 int uid = getMockableCallingUid(); 263 mWifiPermissionsUtil.checkPackage(uid, callingPackage); 264 enforceChangePermission(); 265 if (mVerboseLoggingEnabled) { 266 Log.v(TAG, "removePairedDevice: callingPackage=" + callingPackage + ", alias=" + alias); 267 } 268 mStateManager.removePairedDevice(callingPackage, alias); 269 } 270 271 @Override getPairedDevices(String callingPackage, @NonNull IListListener listener)272 public void getPairedDevices(String callingPackage, @NonNull IListListener listener) { 273 if (listener == null) { 274 throw new IllegalArgumentException("listener should not be null"); 275 } 276 int uid = getMockableCallingUid(); 277 mWifiPermissionsUtil.checkPackage(uid, callingPackage); 278 enforceAccessPermission(); 279 mStateManager.getPairedDevices(callingPackage, listener); 280 } 281 282 @Override setOpportunisticModeEnabled(String callingPackage, boolean enabled)283 public void setOpportunisticModeEnabled(String callingPackage, boolean enabled) { 284 int uid = getMockableCallingUid(); 285 mWifiPermissionsUtil.checkPackage(uid, callingPackage); 286 enforceChangePermission(); 287 if (mVerboseLoggingEnabled) { 288 Log.v( 289 TAG, 290 "setOpportunisticModeEnabled: callingPackage=" 291 + callingPackage 292 + ", enabled=" 293 + enabled); 294 } 295 mStateManager.setOpportunisticPackage(callingPackage, enabled); 296 } 297 298 @Override isOpportunisticModeEnabled(String callingPackage, @NonNull IBooleanListener listener)299 public void isOpportunisticModeEnabled(String callingPackage, 300 @NonNull IBooleanListener listener) { 301 if (listener == null) { 302 throw new IllegalArgumentException("listener should not be null"); 303 } 304 int uid = getMockableCallingUid(); 305 mWifiPermissionsUtil.checkPackage(uid, callingPackage); 306 enforceAccessPermission(); 307 mStateManager.isOpportunistic(callingPackage, listener); 308 } 309 310 @Override connect(final IBinder binder, String callingPackage, String callingFeatureId, IWifiAwareEventCallback callback, ConfigRequest configRequest, boolean notifyOnIdentityChanged, Bundle extras, boolean forOffloading)311 public void connect(final IBinder binder, String callingPackage, String callingFeatureId, 312 IWifiAwareEventCallback callback, ConfigRequest configRequest, 313 boolean notifyOnIdentityChanged, Bundle extras, boolean forOffloading) { 314 enforceAccessPermission(); 315 enforceChangePermission(); 316 317 final int uid = getMockableCallingUid(); 318 mWifiPermissionsUtil.checkPackage(uid, callingPackage); 319 320 if (callback == null) { 321 throw new IllegalArgumentException("Callback must not be null"); 322 } 323 if (binder == null) { 324 throw new IllegalArgumentException("Binder must not be null"); 325 } 326 327 if (extras == null) { 328 throw new IllegalArgumentException("extras bundle must not be null"); 329 } 330 331 if (notifyOnIdentityChanged) { 332 enforceNearbyOrLocationPermission(callingPackage, callingFeatureId, 333 getMockableCallingUid(), extras, "Wifi Aware attach"); 334 } 335 if (forOffloading && !mWifiPermissionsUtil.checkConfigOverridePermission(uid)) { 336 throw new SecurityException("Enable Wifi Aware for offloading require" 337 + "OVERRIDE_WIFI_CONFIG permission"); 338 } 339 340 if (configRequest != null) { 341 boolean networkStackPermission = checkNetworkStackPermission(); 342 boolean manageNetworkSelectionPermission = 343 mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid); 344 if (!(networkStackPermission || manageNetworkSelectionPermission)) { 345 throw new SecurityException("Insufficient permission to include a ConfigRequest"); 346 } 347 348 if (!networkStackPermission) { 349 // OEM apps with only the network selection permission can provide a config request, 350 // but they should only modify the vendor data field. 351 ConfigRequest.Builder builder = new ConfigRequest.Builder(); 352 if (SdkLevel.isAtLeastV()) { 353 builder.setVendorData(configRequest.getVendorData()); 354 } 355 configRequest = builder.build(); 356 } 357 } else { 358 configRequest = new ConfigRequest.Builder().build(); 359 } 360 configRequest.validate(); 361 362 363 int pid = getCallingPid(); 364 365 final int clientId; 366 synchronized (mLock) { 367 clientId = mNextClientId++; 368 } 369 370 if (mVerboseLoggingEnabled) { 371 Log.v(TAG, "connect: uid=" + uid + ", clientId=" + clientId + ", configRequest=" 372 + configRequest + ", notifyOnIdentityChanged=" + notifyOnIdentityChanged); 373 } 374 375 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() { 376 @Override 377 public void binderDied() { 378 if (mVerboseLoggingEnabled) Log.v(TAG, "binderDied: clientId=" + clientId); 379 binder.unlinkToDeath(this, 0); 380 381 synchronized (mLock) { 382 mDeathRecipientsByClientId.delete(clientId); 383 mUidByClientId.delete(clientId); 384 } 385 386 mStateManager.disconnect(clientId); 387 } 388 }; 389 390 try { 391 binder.linkToDeath(dr, 0); 392 } catch (RemoteException e) { 393 Log.e(TAG, "Error on linkToDeath - " + e); 394 try { 395 callback.onConnectFail(NanStatusCode.INTERNAL_FAILURE); 396 } catch (RemoteException e1) { 397 Log.e(TAG, "Error on onConnectFail()"); 398 } 399 return; 400 } 401 402 synchronized (mLock) { 403 mDeathRecipientsByClientId.put(clientId, dr); 404 mUidByClientId.put(clientId, uid); 405 } 406 407 mStateManager.connect(clientId, uid, pid, callingPackage, callingFeatureId, callback, 408 configRequest, notifyOnIdentityChanged, extras, forOffloading); 409 } 410 411 @Override disconnect(int clientId, IBinder binder)412 public void disconnect(int clientId, IBinder binder) { 413 enforceAccessPermission(); 414 enforceChangePermission(); 415 416 int uid = getMockableCallingUid(); 417 enforceClientValidity(uid, clientId); 418 if (mVerboseLoggingEnabled) { 419 Log.v(TAG, "disconnect: uid=" + uid + ", clientId=" + clientId); 420 } 421 422 if (binder == null) { 423 throw new IllegalArgumentException("Binder must not be null"); 424 } 425 426 synchronized (mLock) { 427 IBinder.DeathRecipient dr = mDeathRecipientsByClientId.get(clientId); 428 if (dr != null) { 429 binder.unlinkToDeath(dr, 0); 430 mDeathRecipientsByClientId.delete(clientId); 431 } 432 mUidByClientId.delete(clientId); 433 } 434 435 mStateManager.disconnect(clientId); 436 } 437 438 @Override setMasterPreference(int clientId, IBinder binder, int mp)439 public void setMasterPreference(int clientId, IBinder binder, int mp) { 440 int uid = getMockableCallingUid(); 441 enforceClientValidity(uid, clientId); 442 if (binder == null) { 443 throw new IllegalArgumentException("Binder must not be null"); 444 } 445 if (!mWifiPermissionsUtil.checkConfigOverridePermission(uid)) { 446 throw new SecurityException("setMasterPreference requires " 447 + "OVERRIDE_WIFI_CONFIG permission"); 448 } 449 450 if (mp < 0) { 451 throw new IllegalArgumentException( 452 "Master Preference specification must be non-negative"); 453 } 454 if (mp == 1 || mp == 255 || mp > 255) { 455 throw new IllegalArgumentException("Master Preference specification must not " 456 + "exceed 255 or use 1 or 255 (reserved values)"); 457 } 458 459 if (mVerboseLoggingEnabled) { 460 Log.v(TAG, "setMasterPreference: uid=" + uid + ", clientId=" + clientId); 461 } 462 463 mStateManager.setMasterPreference(clientId, mp); 464 } 465 466 @Override getMasterPreference(int clientId, IBinder binder, IIntegerListener listener)467 public void getMasterPreference(int clientId, IBinder binder, IIntegerListener listener) { 468 int uid = getMockableCallingUid(); 469 enforceClientValidity(uid, clientId); 470 if (binder == null) { 471 throw new IllegalArgumentException("Binder must not be null"); 472 } 473 if (!mWifiPermissionsUtil.checkConfigOverridePermission(uid)) { 474 throw new SecurityException("getMasterPreference requires " 475 + "OVERRIDE_WIFI_CONFIG permission"); 476 } 477 478 if (mVerboseLoggingEnabled) { 479 Log.v(TAG, "getMasterPreference: uid=" + uid + ", clientId=" + clientId); 480 } 481 mStateManager.getMasterPreference(clientId, listener); 482 } 483 484 485 @Override terminateSession(int clientId, int sessionId)486 public void terminateSession(int clientId, int sessionId) { 487 enforceAccessPermission(); 488 enforceChangePermission(); 489 490 int uid = getMockableCallingUid(); 491 enforceClientValidity(uid, clientId); 492 if (mVerboseLoggingEnabled) { 493 Log.v(TAG, "terminateSession: sessionId=" + sessionId + ", uid=" + uid + ", clientId=" 494 + clientId); 495 } 496 497 mStateManager.terminateSession(clientId, sessionId); 498 } 499 500 @Override publish(String callingPackage, String callingFeatureId, int clientId, PublishConfig publishConfig, IWifiAwareDiscoverySessionCallback callback, Bundle extras)501 public void publish(String callingPackage, String callingFeatureId, int clientId, 502 PublishConfig publishConfig, IWifiAwareDiscoverySessionCallback callback, 503 Bundle extras) { 504 enforceAccessPermission(); 505 enforceChangePermission(); 506 507 int uid = getMockableCallingUid(); 508 mWifiPermissionsUtil.checkPackage(uid, callingPackage); 509 510 enforceNearbyOrLocationPermission(callingPackage, callingFeatureId, 511 getMockableCallingUid(), extras, "Wifi Aware publish"); 512 513 if (callback == null) { 514 throw new IllegalArgumentException("Callback must not be null"); 515 } 516 if (publishConfig == null) { 517 throw new IllegalArgumentException("PublishConfig must not be null"); 518 } 519 publishConfig.assertValid(mStateManager.getCharacteristics(), 520 mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)); 521 522 if (SdkLevel.isAtLeastU() && publishConfig.isSuspendable() 523 && !mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) { 524 throw new SecurityException("App not allowed to use Aware suspension" 525 + "(uid = " + uid + ")"); 526 } 527 528 enforceClientValidity(uid, clientId); 529 if (mVerboseLoggingEnabled) { 530 Log.v(TAG, "publish: uid=" + uid + ", clientId=" + clientId + ", publishConfig=" 531 + publishConfig + ", callback=" + callback); 532 } 533 534 mStateManager.publish(clientId, publishConfig, callback); 535 } 536 537 @Override updatePublish(int clientId, int sessionId, PublishConfig publishConfig)538 public void updatePublish(int clientId, int sessionId, PublishConfig publishConfig) { 539 enforceAccessPermission(); 540 enforceChangePermission(); 541 542 if (publishConfig == null) { 543 throw new IllegalArgumentException("PublishConfig must not be null"); 544 } 545 publishConfig.assertValid(mStateManager.getCharacteristics(), 546 mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)); 547 548 int uid = getMockableCallingUid(); 549 if (SdkLevel.isAtLeastU() && publishConfig.isSuspendable() 550 && !mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) { 551 throw new SecurityException("App not allowed to use Aware suspension" 552 + "(uid = " + uid + ")"); 553 } 554 555 enforceClientValidity(uid, clientId); 556 if (mVerboseLoggingEnabled) { 557 Log.v(TAG, "updatePublish: uid=" + uid + ", clientId=" + clientId + ", sessionId=" 558 + sessionId + ", config=" + publishConfig); 559 } 560 561 mStateManager.updatePublish(clientId, sessionId, publishConfig); 562 } 563 564 @Override subscribe(String callingPackage, String callingFeatureId, int clientId, SubscribeConfig subscribeConfig, IWifiAwareDiscoverySessionCallback callback, Bundle extras)565 public void subscribe(String callingPackage, String callingFeatureId, int clientId, 566 SubscribeConfig subscribeConfig, IWifiAwareDiscoverySessionCallback callback, 567 Bundle extras) { 568 enforceAccessPermission(); 569 enforceChangePermission(); 570 571 int uid = getMockableCallingUid(); 572 mWifiPermissionsUtil.checkPackage(uid, callingPackage); 573 574 enforceNearbyOrLocationPermission(callingPackage, callingFeatureId, 575 getMockableCallingUid(), extras, "Wifi Aware subscribe"); 576 577 if (callback == null) { 578 throw new IllegalArgumentException("Callback must not be null"); 579 } 580 if (subscribeConfig == null) { 581 throw new IllegalArgumentException("SubscribeConfig must not be null"); 582 } 583 subscribeConfig.assertValid(mStateManager.getCharacteristics(), 584 mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)); 585 586 if (SdkLevel.isAtLeastU() && subscribeConfig.isSuspendable() 587 && !mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) { 588 throw new SecurityException("App not allowed to use Aware suspension" 589 + "(uid = " + uid + ")"); 590 } 591 592 enforceClientValidity(uid, clientId); 593 if (mVerboseLoggingEnabled) { 594 Log.v(TAG, "subscribe: uid=" + uid + ", clientId=" + clientId + ", config=" 595 + subscribeConfig + ", callback=" + callback); 596 } 597 598 mStateManager.subscribe(clientId, subscribeConfig, callback); 599 } 600 601 @Override updateSubscribe(int clientId, int sessionId, SubscribeConfig subscribeConfig)602 public void updateSubscribe(int clientId, int sessionId, SubscribeConfig subscribeConfig) { 603 enforceAccessPermission(); 604 enforceChangePermission(); 605 606 if (subscribeConfig == null) { 607 throw new IllegalArgumentException("SubscribeConfig must not be null"); 608 } 609 subscribeConfig.assertValid(mStateManager.getCharacteristics(), 610 mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)); 611 612 int uid = getMockableCallingUid(); 613 if (SdkLevel.isAtLeastU() && subscribeConfig.isSuspendable() 614 && !mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) { 615 throw new SecurityException("App not allowed to use Aware suspension" 616 + "(uid = " + uid + ")"); 617 } 618 619 enforceClientValidity(uid, clientId); 620 if (mVerboseLoggingEnabled) { 621 Log.v(TAG, "updateSubscribe: uid=" + uid + ", clientId=" + clientId + ", sessionId=" 622 + sessionId + ", config=" + subscribeConfig); 623 } 624 625 mStateManager.updateSubscribe(clientId, sessionId, subscribeConfig); 626 } 627 628 @Override sendMessage(int clientId, int sessionId, int peerId, byte[] message, int messageId, int retryCount)629 public void sendMessage(int clientId, int sessionId, int peerId, byte[] message, int messageId, 630 int retryCount) { 631 enforceAccessPermission(); 632 enforceChangePermission(); 633 634 if (retryCount != 0) { 635 enforceNetworkStackPermission(); 636 } 637 638 if (message != null && message.length 639 > mStateManager.getCharacteristics().getMaxServiceSpecificInfoLength()) { 640 throw new IllegalArgumentException( 641 "Message length longer than supported by device characteristics"); 642 } 643 if (retryCount < 0 || retryCount > DiscoverySession.getMaxSendRetryCount()) { 644 throw new IllegalArgumentException("Invalid 'retryCount' must be non-negative " 645 + "and <= DiscoverySession.MAX_SEND_RETRY_COUNT"); 646 } 647 648 int uid = getMockableCallingUid(); 649 enforceClientValidity(uid, clientId); 650 if (mVerboseLoggingEnabled) { 651 Log.v(TAG, 652 "sendMessage: sessionId=" + sessionId + ", uid=" + uid + ", clientId=" 653 + clientId + ", peerId=" + peerId + ", messageId=" + messageId 654 + ", retryCount=" + retryCount); 655 } 656 657 mStateManager.sendMessage(uid, clientId, sessionId, peerId, message, messageId, retryCount); 658 } 659 660 @Override requestMacAddresses(int uid, int[] peerIds, IWifiAwareMacAddressProvider callback)661 public void requestMacAddresses(int uid, int[] peerIds, IWifiAwareMacAddressProvider callback) { 662 enforceNetworkStackPermission(); 663 664 mStateManager.requestMacAddresses(uid, peerIds, callback); 665 } 666 667 @Override initiateNanPairingSetupRequest(int clientId, int sessionId, int peerId, String password, String pairingDeviceAlias, int cipherSuite)668 public void initiateNanPairingSetupRequest(int clientId, int sessionId, int peerId, 669 String password, String pairingDeviceAlias, int cipherSuite) { 670 enforceAccessPermission(); 671 enforceChangePermission(); 672 if (!mStateManager.getCharacteristics().isAwarePairingSupported()) { 673 throw new IllegalArgumentException( 674 "NAN pairing is not supported"); 675 } 676 if (pairingDeviceAlias == null) { 677 throw new IllegalArgumentException( 678 "initiateNanPairingRequest: invalid pairingDeviceAlias - must be non-null"); 679 } 680 if (cipherSuite != WIFI_AWARE_CIPHER_SUITE_NCS_PK_PASN_128 681 && cipherSuite != WIFI_AWARE_CIPHER_SUITE_NCS_PK_PASN_256) { 682 throw new IllegalArgumentException( 683 "initiateNanPairingRequest: cipher suite is invalid"); 684 } 685 int uid = getMockableCallingUid(); 686 enforceClientValidity(uid, clientId); 687 if (mVerboseLoggingEnabled) { 688 Log.v(TAG, 689 "initiateNanPairingRequest: sessionId=" + sessionId + ", uid=" + uid 690 + ", clientId=" + clientId + ", peerId=" + peerId); 691 } 692 mStateManager.initiateNanPairingSetupRequest(clientId, sessionId, peerId, password, 693 pairingDeviceAlias, cipherSuite); 694 } 695 696 @Override responseNanPairingSetupRequest(int clientId, int sessionId, int peerId, int requestId, String password, String pairingDeviceAlias, boolean accept, int cipherSuite)697 public void responseNanPairingSetupRequest(int clientId, int sessionId, int peerId, 698 int requestId, String password, String pairingDeviceAlias, boolean accept, 699 int cipherSuite) { 700 enforceAccessPermission(); 701 enforceChangePermission(); 702 if (!mStateManager.getCharacteristics().isAwarePairingSupported()) { 703 throw new IllegalArgumentException( 704 "NAN pairing is not supported"); 705 } 706 if (accept) { 707 if (pairingDeviceAlias == null) { 708 throw new IllegalArgumentException( 709 "responseNanPairingSetupRequest: invalid pairingDeviceAlias - " 710 + "must be non-null"); 711 } 712 if (cipherSuite != WIFI_AWARE_CIPHER_SUITE_NCS_PK_PASN_128 713 && cipherSuite != WIFI_AWARE_CIPHER_SUITE_NCS_PK_PASN_256) { 714 throw new IllegalArgumentException( 715 "responseNanPairingSetupRequest: cipher suite is invalid"); 716 } 717 } 718 int uid = getMockableCallingUid(); 719 enforceClientValidity(uid, clientId); 720 if (mVerboseLoggingEnabled) { 721 Log.v(TAG, 722 "responsePairingRequest: sessionId=" + sessionId + ", uid=" + uid 723 + ", clientId=" + clientId + ", peerId=" + peerId); 724 } 725 mStateManager.responseNanPairingSetupRequest(clientId, sessionId, peerId, requestId, 726 password, pairingDeviceAlias, accept, cipherSuite); 727 } 728 729 @Override initiateBootStrappingSetupRequest(int clientId, int sessionId, int peerId, int method)730 public void initiateBootStrappingSetupRequest(int clientId, int sessionId, int peerId, 731 int method) { 732 enforceAccessPermission(); 733 enforceChangePermission(); 734 if (!mStateManager.getCharacteristics().isAwarePairingSupported()) { 735 throw new IllegalArgumentException( 736 "NAN pairing is not supported"); 737 } 738 int uid = getMockableCallingUid(); 739 enforceClientValidity(uid, clientId); 740 if (mVerboseLoggingEnabled) { 741 Log.v(TAG, 742 "initiateBootStrappingSetupRequest: sessionId=" + sessionId 743 + ", uid=" + uid + ", clientId=" + clientId + ", peerId=" + peerId); 744 } 745 mStateManager.initiateBootStrappingSetupRequest(clientId, sessionId, peerId, method, 0, 746 null); 747 } 748 749 @Override suspend(int clientId, int sessionId)750 public void suspend(int clientId, int sessionId) { 751 enforceAccessPermission(); 752 enforceChangePermission(); 753 754 int uid = getMockableCallingUid(); 755 enforceClientValidity(uid, clientId); 756 if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) { 757 throw new SecurityException("App not allowed to use Aware suspension" 758 + "(uid = " + uid + ")"); 759 } 760 761 if (!mStateManager.getCharacteristics().isSuspensionSupported()) { 762 throw new UnsupportedOperationException("NAN suspension is not supported."); 763 } 764 765 if (mVerboseLoggingEnabled) { 766 Log.v(TAG, "suspend: clientId=" + clientId + ", sessionId=" + sessionId); 767 } 768 769 mStateManager.suspend(clientId, sessionId); 770 } 771 772 @Override resume(int clientId, int sessionId)773 public void resume(int clientId, int sessionId) { 774 enforceAccessPermission(); 775 enforceChangePermission(); 776 777 int uid = getMockableCallingUid(); 778 enforceClientValidity(uid, clientId); 779 if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) { 780 throw new SecurityException("App not allowed to use Aware suspension" 781 + "(uid = " + uid + ")"); 782 } 783 784 if (!mStateManager.getCharacteristics().isSuspensionSupported()) { 785 throw new UnsupportedOperationException("NAN suspension is not supported."); 786 } 787 788 if (mVerboseLoggingEnabled) { 789 Log.v(TAG, "resume: clientId=" + clientId + ", sessionId=" + sessionId); 790 } 791 792 mStateManager.resume(clientId, sessionId); 793 } 794 795 @Override handleShellCommand(@onNull ParcelFileDescriptor in, @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err, @NonNull String[] args)796 public int handleShellCommand(@NonNull ParcelFileDescriptor in, 797 @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err, 798 @NonNull String[] args) { 799 return mShellCommand.exec( 800 this, in.getFileDescriptor(), out.getFileDescriptor(), err.getFileDescriptor(), 801 args); 802 } 803 804 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)805 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 806 if (mContext.checkCallingOrSelfPermission( 807 android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) { 808 pw.println("Permission Denial: can't dump WifiAwareService from pid=" 809 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 810 return; 811 } 812 pw.println("Wi-Fi Aware Service"); 813 synchronized (mLock) { 814 pw.println(" mNextClientId: " + mNextClientId); 815 pw.println(" mDeathRecipientsByClientId: " + mDeathRecipientsByClientId); 816 pw.println(" mUidByClientId: " + mUidByClientId); 817 } 818 mStateManager.dump(fd, pw, args); 819 } 820 enforceClientValidity(int uid, int clientId)821 private void enforceClientValidity(int uid, int clientId) { 822 synchronized (mLock) { 823 int uidIndex = mUidByClientId.indexOfKey(clientId); 824 if (uidIndex < 0 || mUidByClientId.valueAt(uidIndex) != uid) { 825 throw new SecurityException("Attempting to use invalid uid+clientId mapping: uid=" 826 + uid + ", clientId=" + clientId); 827 } 828 } 829 } 830 enforceAccessPermission()831 private void enforceAccessPermission() { 832 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE, TAG); 833 } 834 enforceChangePermission()835 private void enforceChangePermission() { 836 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE, TAG); 837 } 838 enforceNearbyOrLocationPermission(String callingPackage, String callingFeatureId, int uid, Bundle extras, String message)839 private void enforceNearbyOrLocationPermission(String callingPackage, String callingFeatureId, 840 int uid, Bundle extras, String message) { 841 if (!SdkLevel.isAtLeastT() || mWifiPermissionsUtil.isTargetSdkLessThan(callingPackage, 842 Build.VERSION_CODES.TIRAMISU, 843 uid)) { 844 mWifiPermissionsUtil.enforceLocationPermission(callingPackage, callingFeatureId, uid); 845 } else { 846 mWifiPermissionsUtil.enforceNearbyDevicesPermission(extras.getParcelable( 847 WifiManager.EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE), true, message); 848 } 849 } 850 enforceNetworkStackPermission()851 private void enforceNetworkStackPermission() { 852 mContext.enforceCallingOrSelfPermission(Manifest.permission.NETWORK_STACK, TAG); 853 } 854 checkNetworkStackPermission()855 private boolean checkNetworkStackPermission() { 856 return mContext.checkCallingOrSelfPermission(Manifest.permission.NETWORK_STACK) 857 == PackageManager.PERMISSION_GRANTED; 858 } 859 } 860