Added audio policy api to do route based on user.
Added new API to audio policy to route audio output streams based on
Android user id. The routing remains similar to uid rules, with only
using USERID_EXCLUDE_USERID to decide on the user id base routing.
Application uid and stream usage routing remain the same with the added
difference that user id will be taken in to consideration if available.
Bug: 139365417
Test: atest
com.google.android.gts.audio.AudioHostTest#testUserIdDeviceAffinity
Test: atest AudioPlaybackCaptureTest
Change-Id: Ib817eb8ae19ed7dea8451e8a8584a20b9b6f5042
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index ce8b33c..ce38414 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -97,6 +97,8 @@
IS_HAPTIC_PLAYBACK_SUPPORTED,
SET_UID_DEVICE_AFFINITY,
REMOVE_UID_DEVICE_AFFINITY,
+ SET_USERID_DEVICE_AFFINITY,
+ REMOVE_USERID_DEVICE_AFFINITY,
GET_OFFLOAD_FORMATS_A2DP,
LIST_AUDIO_PRODUCT_STRATEGIES,
GET_STRATEGY_FOR_ATTRIBUTES,
@@ -1197,6 +1199,52 @@
return status;
}
+ virtual status_t setUserIdDeviceAffinities(int userId,
+ const Vector<AudioDeviceTypeAddr>& devices)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+
+ data.writeInt32((int32_t) userId);
+ size_t size = devices.size();
+ size_t sizePosition = data.dataPosition();
+ data.writeInt32((int32_t) size);
+ size_t finalSize = size;
+ for (size_t i = 0; i < size; i++) {
+ size_t position = data.dataPosition();
+ if (devices[i].writeToParcel(&data) != NO_ERROR) {
+ data.setDataPosition(position);
+ finalSize--;
+ }
+ }
+ if (size != finalSize) {
+ size_t position = data.dataPosition();
+ data.setDataPosition(sizePosition);
+ data.writeInt32(finalSize);
+ data.setDataPosition(position);
+ }
+
+ status_t status = remote()->transact(SET_USERID_DEVICE_AFFINITY, data, &reply);
+ if (status == NO_ERROR) {
+ status = (status_t)reply.readInt32();
+ }
+ return status;
+ }
+
+ virtual status_t removeUserIdDeviceAffinities(int userId) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+
+ data.writeInt32((int32_t) userId);
+
+ status_t status =
+ remote()->transact(REMOVE_USERID_DEVICE_AFFINITY, data, &reply);
+ if (status == NO_ERROR) {
+ status = (status_t) reply.readInt32();
+ }
+ return status;
+ }
+
virtual status_t listAudioProductStrategies(AudioProductStrategyVector &strategies)
{
Parcel data, reply;
@@ -1457,6 +1505,8 @@
case SET_A11Y_SERVICES_UIDS:
case SET_UID_DEVICE_AFFINITY:
case REMOVE_UID_DEVICE_AFFINITY:
+ case SET_USERID_DEVICE_AFFINITY:
+ case REMOVE_USERID_DEVICE_AFFINITY:
case GET_OFFLOAD_FORMATS_A2DP:
case LIST_AUDIO_VOLUME_GROUPS:
case GET_VOLUME_GROUP_FOR_ATTRIBUTES:
@@ -2379,6 +2429,30 @@
return NO_ERROR;
}
+ case SET_USERID_DEVICE_AFFINITY: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ const int userId = (int) data.readInt32();
+ Vector<AudioDeviceTypeAddr> devices;
+ size_t size = (size_t)data.readInt32();
+ for (size_t i = 0; i < size; i++) {
+ AudioDeviceTypeAddr device;
+ if (device.readFromParcel((Parcel*)&data) == NO_ERROR) {
+ devices.add(device);
+ }
+ }
+ status_t status = setUserIdDeviceAffinities(userId, devices);
+ reply->writeInt32(status);
+ return NO_ERROR;
+ }
+
+ case REMOVE_USERID_DEVICE_AFFINITY: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ const int userId = (int) data.readInt32();
+ status_t status = removeUserIdDeviceAffinities(userId);
+ reply->writeInt32(status);
+ return NO_ERROR;
+ }
+
case LIST_AUDIO_PRODUCT_STRATEGIES: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
AudioProductStrategyVector strategies;