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