diff options
author | 2024-11-08 11:02:11 -0800 | |
---|---|---|
committer | 2024-11-22 08:56:27 -0800 | |
commit | 04d2edc4feeac84fe0de33633263fafbdfb665e7 (patch) | |
tree | 0db3431fe70e1bbcba1ef87787108a6f46df4003 | |
parent | df7a809ff77014aa24c753d6baf7b9350af0ac40 (diff) |
Add USD publish and subscribe APIs
Flag: android.net.wifi.flags.usd
Bug: 340878198
Test: atest FrameworksWifiApiTests
Change-Id: Iee93c15a8914fcd9fb4ae9fb06112ed9c96e453b
8 files changed, 325 insertions, 1 deletions
diff --git a/framework/aidl-export/android/net/wifi/usd/PublishConfig.aidl b/framework/aidl-export/android/net/wifi/usd/PublishConfig.aidl new file mode 100644 index 0000000000..80e5421eab --- /dev/null +++ b/framework/aidl-export/android/net/wifi/usd/PublishConfig.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2024, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi.usd; + +parcelable PublishConfig; diff --git a/framework/aidl-export/android/net/wifi/usd/SubscribeConfig.aidl b/framework/aidl-export/android/net/wifi/usd/SubscribeConfig.aidl new file mode 100644 index 0000000000..71a168423b --- /dev/null +++ b/framework/aidl-export/android/net/wifi/usd/SubscribeConfig.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2024, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi.usd; + +parcelable SubscribeConfig; diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index b44a7a5433..75eb99a950 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -1976,7 +1976,9 @@ package android.net.wifi.usd { method @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) public boolean isPublisherSupported(); method @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) public boolean isSubscriberAvailable(); method @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) public boolean isSubscriberSupported(); + method @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) public void publish(@NonNull android.net.wifi.usd.PublishConfig, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.usd.PublishSessionCallback); method @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) public void registerAvailabilityCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.usd.UsdManager.AvailabilityCallback); + method @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) public void subscribe(@NonNull android.net.wifi.usd.SubscribeConfig, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.usd.SubscribeSessionCallback); method @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) public void unregisterAvailabilityCallback(@NonNull android.net.wifi.usd.UsdManager.AvailabilityCallback); } diff --git a/framework/java/android/net/wifi/usd/IPublishSessionCallback.aidl b/framework/java/android/net/wifi/usd/IPublishSessionCallback.aidl new file mode 100644 index 0000000000..5037085644 --- /dev/null +++ b/framework/java/android/net/wifi/usd/IPublishSessionCallback.aidl @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi.usd; + +/** + * Interface for USD publish session callback. + * + * @hide + */ +oneway interface IPublishSessionCallback { + void onPublishFailed(int reasonCode); + void onPublishStarted(int sessionId); + void onPublishReplied(int peerId, in byte[] ssi, int protoType, boolean isFsdEnabled); + void onPublishSessionTerminated(int reasonCode); + void onMessageReceived(int peerId, in byte[] message); +} diff --git a/framework/java/android/net/wifi/usd/ISubscribeSessionCallback.aidl b/framework/java/android/net/wifi/usd/ISubscribeSessionCallback.aidl new file mode 100644 index 0000000000..581d50dfeb --- /dev/null +++ b/framework/java/android/net/wifi/usd/ISubscribeSessionCallback.aidl @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi.usd; + +/** + * Interface for USD subscribe session callback. + * + * @hide + */ +oneway interface ISubscribeSessionCallback { + void onSubscribeFailed(int reasonCode); + void onSubscribeStarted(int sessionId); + void onSubscribeDiscovered(int peerId, in byte[] ssi, int protoType, boolean isFsdEnabled); + void onSubscribeSessionTerminated(int reasonCode); + void onMessageReceived(int peerId, in byte[] message); +} diff --git a/framework/java/android/net/wifi/usd/IUsdManager.aidl b/framework/java/android/net/wifi/usd/IUsdManager.aidl index 084b9d7948..f591639b0e 100644 --- a/framework/java/android/net/wifi/usd/IUsdManager.aidl +++ b/framework/java/android/net/wifi/usd/IUsdManager.aidl @@ -19,6 +19,10 @@ package android.net.wifi.usd; import android.net.wifi.IBooleanListener; import android.net.wifi.usd.Characteristics; import android.net.wifi.usd.IAvailabilityCallback; +import android.net.wifi.usd.IPublishSessionCallback; +import android.net.wifi.usd.ISubscribeSessionCallback; +import android.net.wifi.usd.PublishConfig; +import android.net.wifi.usd.SubscribeConfig; /** * Interface that UsdService implements @@ -37,4 +41,6 @@ interface IUsdManager { void cancelSubscribe(int sessionId); void cancelPublish(int sessionId); void updatePublish(int sessionId, in byte[] ssi); + void publish(in PublishConfig publishConfig, IPublishSessionCallback callback); + void subscribe(in SubscribeConfig subscribeConfig, ISubscribeSessionCallback callback); } diff --git a/framework/java/android/net/wifi/usd/UsdManager.java b/framework/java/android/net/wifi/usd/UsdManager.java index dd6654788f..fa762f2d2f 100644 --- a/framework/java/android/net/wifi/usd/UsdManager.java +++ b/framework/java/android/net/wifi/usd/UsdManager.java @@ -221,7 +221,6 @@ public class UsdManager { Binder.clearCallingIdentity(); mExecutor.execute(mAvailabilityCallback::onPublisherAvailable); } - } /** @@ -320,4 +319,189 @@ public class UsdManager { throw e.rethrowFromSystemServer(); } } + + private static class PublishSessionCallbackProxy extends IPublishSessionCallback.Stub { + private final Executor mExecutor; + private final PublishSessionCallback mPublishSessionCallback; + private final UsdManager mUsdManager; + + private PublishSessionCallbackProxy(UsdManager usdManager, Executor executor, + PublishSessionCallback publishSessionCallback) { + mUsdManager = usdManager; + mExecutor = executor; + mPublishSessionCallback = publishSessionCallback; + } + + @Override + public void onPublishFailed(int reasonCode) throws RemoteException { + Log.d(TAG, "onPublishFailed (reasonCode = " + reasonCode + " )"); + Binder.clearCallingIdentity(); + mExecutor.execute(() -> mPublishSessionCallback.onPublishFailed(reasonCode)); + } + + @Override + public void onPublishStarted(int sessionId) throws RemoteException { + Log.d(TAG, "onPublishStarted ( sessionId = " + sessionId + " )"); + Binder.clearCallingIdentity(); + mExecutor.execute(() -> mPublishSessionCallback.onPublishStarted( + new PublishSession(mUsdManager, sessionId))); + } + + @Override + public void onPublishReplied(int peerId, byte[] ssi, int protoType, boolean isFsdEnabled) + throws RemoteException { + Log.d(TAG, "onPublishReplied ( peerId = " + peerId + ", protoType = " + protoType + + ", isFsdEnabled = " + isFsdEnabled + " )"); + Binder.clearCallingIdentity(); + DiscoveryResult discoveryResult = new DiscoveryResult.Builder(peerId) + .setServiceSpecificInfo(ssi) + .setServiceProtoType(protoType) + .setFsdEnabled(isFsdEnabled) + .build(); + mExecutor.execute(() -> mPublishSessionCallback.onPublishReplied(discoveryResult)); + } + + @Override + public void onPublishSessionTerminated(int reasonCode) throws RemoteException { + Log.d(TAG, "onPublishSessionTerminated ( reasonCode = " + reasonCode + " )"); + Binder.clearCallingIdentity(); + mExecutor.execute(() -> mPublishSessionCallback.onSessionTerminated(reasonCode)); + } + + @Override + public void onMessageReceived(int peerId, byte[] message) throws RemoteException { + Log.d(TAG, "onMessageReceived ( peerId = " + peerId + " )"); + Binder.clearCallingIdentity(); + mExecutor.execute(() -> mPublishSessionCallback.onMessageReceived(peerId, message)); + } + } + + + /** + * Issue a request to the USD service to create a new publish session using the specified + * {@link PublishConfig} configuration. The result of the publish operation are routed to the + * callbacks of {@link PublishSessionCallback}. + * + * <p>Note: Maximum number of publish sessions are limited by + * {@link Characteristics#getMaxNumberOfPublishSessions()}. + * + * @param publishConfig The {@link PublishConfig} specifying the configuration of the + * requested publish session. + * @param executor The Executor on whose thread to execute the callbacks of the + * {@link PublishSessionCallback} + * @param publishSessionCallback A {@link PublishSessionCallback} object to be used for session + * event callback + */ + @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION) + public void publish(@NonNull PublishConfig publishConfig, + @NonNull @CallbackExecutor Executor executor, + @NonNull PublishSessionCallback publishSessionCallback) { + Objects.requireNonNull(publishConfig, "publishConfig must not be null"); + Objects.requireNonNull(executor, "executor must not be null"); + Objects.requireNonNull(publishSessionCallback, "publishSessionCallback must not be null"); + if (!Environment.isSdkAtLeastB()) { + throw new UnsupportedOperationException(); + } + try { + PublishSessionCallbackProxy publishSessionCallbackProxy = + new PublishSessionCallbackProxy(this, executor, publishSessionCallback); + mService.publish(publishConfig, publishSessionCallbackProxy); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + private static class SubscribeSessionCallbackProxy extends ISubscribeSessionCallback.Stub { + private final UsdManager mUsdManager; + private final Executor mExecutor; + private final SubscribeSessionCallback mSubscribeSessionCallback; + + private SubscribeSessionCallbackProxy(UsdManager usdManager, Executor executor, + SubscribeSessionCallback subscribeSessionCallback) { + mUsdManager = usdManager; + mExecutor = executor; + mSubscribeSessionCallback = subscribeSessionCallback; + } + + @Override + public void onSubscribeFailed(int reasonCode) throws RemoteException { + Log.d(TAG, "onSubscribeFailed (reasonCode = " + reasonCode + " )"); + Binder.clearCallingIdentity(); + mExecutor.execute(() -> mSubscribeSessionCallback.onSubscribeFailed(reasonCode)); + } + + @Override + public void onSubscribeStarted(int sessionId) throws RemoteException { + Log.d(TAG, "onSubscribeStarted ( sessionId = " + sessionId + " )"); + Binder.clearCallingIdentity(); + mExecutor.execute(() -> mSubscribeSessionCallback.onSubscribeStarted( + new SubscribeSession(mUsdManager, sessionId))); + } + + @Override + public void onSubscribeDiscovered(int peerId, byte[] ssi, int protoType, + boolean isFsdEnabled) + throws RemoteException { + Log.d(TAG, "onSubscribeDiscovered ( peerId = " + peerId + ", protoType = " + protoType + + ", isFsdEnabled = " + isFsdEnabled + " )"); + Binder.clearCallingIdentity(); + DiscoveryResult discoveryResult = new DiscoveryResult.Builder(peerId) + .setServiceSpecificInfo(ssi) + .setServiceProtoType(protoType) + .setFsdEnabled(isFsdEnabled) + .build(); + mExecutor.execute(() -> mSubscribeSessionCallback.onServiceDiscovered(discoveryResult)); + } + + @Override + public void onSubscribeSessionTerminated(int reasonCode) throws RemoteException { + Log.d(TAG, "onSubscribeSessionTerminated ( reasonCode = " + reasonCode + " )"); + Binder.clearCallingIdentity(); + mExecutor.execute(() -> mSubscribeSessionCallback.onSessionTerminated(reasonCode)); + } + + @Override + public void onMessageReceived(int peerId, byte[] message) throws RemoteException { + Log.d(TAG, "onMessageReceived ( peerId = " + peerId + " )"); + Binder.clearCallingIdentity(); + mExecutor.execute(() -> mSubscribeSessionCallback.onMessageReceived(peerId, message)); + } + } + + + /** + * Issue a request to the USD service to create a new subscribe session using the specified + * {@link SubscribeConfig} configuration. The result of the subscribe operation are + * routed to + * the callbacks of {@link SubscribeSessionCallback}. + * + * <p>Note: Maximum number of subscribe sessions are limited by + * {@link Characteristics#getMaxNumberOfSubscribeSessions()}. + * + * @param subscribeConfig The {@link SubscribeConfig} specifying the + * configuration of the requested subscribe session. + * @param executor The Executor on whose thread to execute the callbacks of + * the {@link SubscribeSessionCallback} + * @param subscribeSessionCallback A {@link SubscribeSessionCallback} object to be used for + * session event callback + */ + @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION) + public void subscribe(@NonNull SubscribeConfig subscribeConfig, + @NonNull @CallbackExecutor Executor executor, + @NonNull SubscribeSessionCallback subscribeSessionCallback) { + Objects.requireNonNull(subscribeConfig, "subscribeConfig must not be null"); + Objects.requireNonNull(executor, "executor must not be null"); + Objects.requireNonNull(subscribeSessionCallback, + "subscribeSessionCallback must not be null"); + if (!Environment.isSdkAtLeastB()) { + throw new UnsupportedOperationException(); + } + try { + SubscribeSessionCallbackProxy subscribeSessionCallbackProxy = + new SubscribeSessionCallbackProxy(this, executor, subscribeSessionCallback); + mService.subscribe(subscribeConfig, subscribeSessionCallbackProxy); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } } diff --git a/service/java/com/android/server/wifi/usd/UsdServiceImpl.java b/service/java/com/android/server/wifi/usd/UsdServiceImpl.java index f54f8eb128..5b4ad7b95d 100644 --- a/service/java/com/android/server/wifi/usd/UsdServiceImpl.java +++ b/service/java/com/android/server/wifi/usd/UsdServiceImpl.java @@ -21,9 +21,15 @@ import android.content.Context; import android.net.wifi.IBooleanListener; import android.net.wifi.usd.Characteristics; import android.net.wifi.usd.IAvailabilityCallback; +import android.net.wifi.usd.IPublishSessionCallback; +import android.net.wifi.usd.ISubscribeSessionCallback; import android.net.wifi.usd.IUsdManager; +import android.net.wifi.usd.PublishConfig; import android.net.wifi.usd.PublishSession; +import android.net.wifi.usd.PublishSessionCallback; +import android.net.wifi.usd.SubscribeConfig; import android.net.wifi.usd.SubscribeSession; +import android.net.wifi.usd.SubscribeSessionCallback; import android.net.wifi.usd.UsdManager; import android.os.Binder; import android.os.Bundle; @@ -221,4 +227,32 @@ public class UsdServiceImpl extends IUsdManager.Stub { } Log.i(TAG, "updatePublish: ( sessionId = " + sessionId + " )"); } + + /** + * See {@link UsdManager#publish(PublishConfig, Executor, PublishSessionCallback)} + */ + @Override + public void publish(PublishConfig publishConfig, IPublishSessionCallback callback) { + Objects.requireNonNull(publishConfig, "publishConfig must not be null"); + Objects.requireNonNull(callback, "callback must not be null"); + int uid = getMockableCallingUid(); + if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) { + throw new SecurityException("App not allowed to use USD (uid = " + uid + ")"); + } + Log.i(TAG, "publish " + publishConfig); + } + + /** + * See {@link UsdManager#subscribe(SubscribeConfig, Executor, SubscribeSessionCallback)} + */ + @Override + public void subscribe(SubscribeConfig subscribeConfig, ISubscribeSessionCallback callback) { + Objects.requireNonNull(subscribeConfig, "subscribeConfig must not be null"); + Objects.requireNonNull(callback, "callback must not be null"); + int uid = getMockableCallingUid(); + if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) { + throw new SecurityException("App not allowed to use USD (uid = " + uid + ")"); + } + Log.i(TAG, "subscribe " + subscribeConfig); + } } |