Merge "Add option to configure audio session ids for VirtualDevice"

This commit is contained in:
Ján Sebechlebský
2022-12-20 09:32:06 +00:00
committed by Android (Google) Code Review
7 changed files with 167 additions and 10 deletions

View File

@@ -3023,6 +3023,8 @@ package android.companion.virtual {
method public int describeContents();
method @NonNull public java.util.Set<android.content.ComponentName> getAllowedActivities();
method @NonNull public java.util.Set<android.content.ComponentName> getAllowedCrossTaskNavigations();
method public int getAudioPlaybackSessionId();
method public int getAudioRecordingSessionId();
method @NonNull public java.util.Set<android.content.ComponentName> getBlockedActivities();
method @NonNull public java.util.Set<android.content.ComponentName> getBlockedCrossTaskNavigations();
method public int getDefaultActivityPolicy();
@@ -3054,6 +3056,8 @@ package android.companion.virtual {
method @NonNull public android.companion.virtual.VirtualDeviceParams build();
method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setAllowedActivities(@NonNull java.util.Set<android.content.ComponentName>);
method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setAllowedCrossTaskNavigations(@NonNull java.util.Set<android.content.ComponentName>);
method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setAudioPlaybackSessionId(int);
method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setAudioRecordingSessionId(int);
method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setBlockedActivities(@NonNull java.util.Set<android.content.ComponentName>);
method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setBlockedCrossTaskNavigations(@NonNull java.util.Set<android.content.ComponentName>);
method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setDefaultRecentsPolicy(int);

View File

@@ -72,4 +72,16 @@ interface IVirtualDeviceManager {
int createVirtualDisplay(in VirtualDisplayConfig virtualDisplayConfig,
in IVirtualDisplayCallback callback, in IVirtualDevice virtualDevice,
String packageName);
/**
* Returns device-specific session id for playback, or AUDIO_SESSION_ID_GENERATE
* if there's none.
*/
int getAudioPlaybackSessionId(int deviceId);
/**
* Returns device-specific session id for recording, or AUDIO_SESSION_ID_GENERATE
* if there's none.
*/
int getAudioRecordingSessionId(int deviceId);
}

View File

@@ -269,9 +269,14 @@ public final class VirtualDeviceManager {
* @hide
*/
public int getAudioPlaybackSessionId(int deviceId) {
//TODO - Return session id rerouted to VirtualAudioDevice if the VirtualAudioDevice
//is configured to operate in context-aware mode.
return AUDIO_SESSION_ID_GENERATE;
if (mService == null) {
return AUDIO_SESSION_ID_GENERATE;
}
try {
return mService.getAudioPlaybackSessionId(deviceId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
@@ -287,9 +292,14 @@ public final class VirtualDeviceManager {
* @hide
*/
public int getAudioRecordingSessionId(int deviceId) {
//TODO - Return session id corresponding to VirtualAudioDevice injection if the
// VirtualAudioDevice is configured to operate in context-aware mode.
return AUDIO_SESSION_ID_GENERATE;
if (mService == null) {
return AUDIO_SESSION_ID_GENERATE;
}
try {
return mService.getAudioRecordingSessionId(deviceId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**

View File

@@ -17,6 +17,7 @@
package android.companion.virtual;
import static android.Manifest.permission.ADD_ALWAYS_UNLOCKED_DISPLAY;
import static android.media.AudioManager.AUDIO_SESSION_ID_GENERATE;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -191,6 +192,8 @@ public final class VirtualDeviceParams implements Parcelable {
@NonNull private final List<VirtualSensorConfig> mVirtualSensorConfigs;
@RecentsPolicy
private final int mDefaultRecentsPolicy;
private final int mAudioPlaybackSessionId;
private final int mAudioRecordingSessionId;
private VirtualDeviceParams(
@LockState int lockState,
@@ -204,7 +207,9 @@ public final class VirtualDeviceParams implements Parcelable {
@Nullable String name,
@NonNull SparseIntArray devicePolicies,
@NonNull List<VirtualSensorConfig> virtualSensorConfigs,
@RecentsPolicy int defaultRecentsPolicy) {
@RecentsPolicy int defaultRecentsPolicy,
int audioPlaybackSessionId,
int audioRecordingSessionId) {
mLockState = lockState;
mUsersWithMatchingAccounts =
new ArraySet<>(Objects.requireNonNull(usersWithMatchingAccounts));
@@ -220,6 +225,9 @@ public final class VirtualDeviceParams implements Parcelable {
mDevicePolicies = Objects.requireNonNull(devicePolicies);
mVirtualSensorConfigs = Objects.requireNonNull(virtualSensorConfigs);
mDefaultRecentsPolicy = defaultRecentsPolicy;
mAudioPlaybackSessionId = audioPlaybackSessionId;
mAudioRecordingSessionId = audioRecordingSessionId;
}
@SuppressWarnings("unchecked")
@@ -237,6 +245,8 @@ public final class VirtualDeviceParams implements Parcelable {
mVirtualSensorConfigs = new ArrayList<>();
parcel.readTypedList(mVirtualSensorConfigs, VirtualSensorConfig.CREATOR);
mDefaultRecentsPolicy = parcel.readInt();
mAudioPlaybackSessionId = parcel.readInt();
mAudioRecordingSessionId = parcel.readInt();
}
/**
@@ -371,6 +381,24 @@ public final class VirtualDeviceParams implements Parcelable {
return mDefaultRecentsPolicy;
}
/**
* Returns device-specific audio session id for playback.
*
* @see Builder#setAudioPlaybackSessionId(int)
*/
public int getAudioPlaybackSessionId() {
return mAudioPlaybackSessionId;
}
/**
* Returns device-specific audio session id for recording.
*
* @see Builder#setAudioRecordingSessionId(int)
*/
public int getAudioRecordingSessionId() {
return mAudioRecordingSessionId;
}
@Override
public int describeContents() {
return 0;
@@ -390,6 +418,8 @@ public final class VirtualDeviceParams implements Parcelable {
dest.writeSparseIntArray(mDevicePolicies);
dest.writeTypedList(mVirtualSensorConfigs);
dest.writeInt(mDefaultRecentsPolicy);
dest.writeInt(mAudioPlaybackSessionId);
dest.writeInt(mAudioRecordingSessionId);
}
@Override
@@ -422,7 +452,9 @@ public final class VirtualDeviceParams implements Parcelable {
&& Objects.equals(mBlockedActivities, that.mBlockedActivities)
&& mDefaultActivityPolicy == that.mDefaultActivityPolicy
&& Objects.equals(mName, that.mName)
&& mDefaultRecentsPolicy == that.mDefaultRecentsPolicy;
&& mDefaultRecentsPolicy == that.mDefaultRecentsPolicy
&& mAudioPlaybackSessionId == that.mAudioPlaybackSessionId
&& mAudioRecordingSessionId == that.mAudioRecordingSessionId;
}
@Override
@@ -431,7 +463,7 @@ public final class VirtualDeviceParams implements Parcelable {
mLockState, mUsersWithMatchingAccounts, mAllowedCrossTaskNavigations,
mBlockedCrossTaskNavigations, mDefaultNavigationPolicy, mAllowedActivities,
mBlockedActivities, mDefaultActivityPolicy, mName, mDevicePolicies,
mDefaultRecentsPolicy);
mDefaultRecentsPolicy, mAudioPlaybackSessionId, mAudioRecordingSessionId);
for (int i = 0; i < mDevicePolicies.size(); i++) {
hashCode = 31 * hashCode + mDevicePolicies.keyAt(i);
hashCode = 31 * hashCode + mDevicePolicies.valueAt(i);
@@ -454,6 +486,8 @@ public final class VirtualDeviceParams implements Parcelable {
+ " mName=" + mName
+ " mDevicePolicies=" + mDevicePolicies
+ " mDefaultRecentsPolicy=" + mDefaultRecentsPolicy
+ " mAudioPlaybackSessionId=" + mAudioPlaybackSessionId
+ " mAudioRecordingSessionId=" + mAudioRecordingSessionId
+ ")";
}
@@ -490,6 +524,8 @@ public final class VirtualDeviceParams implements Parcelable {
@NonNull private SparseIntArray mDevicePolicies = new SparseIntArray();
@NonNull private List<VirtualSensorConfig> mVirtualSensorConfigs = new ArrayList<>();
private int mDefaultRecentsPolicy;
private int mAudioPlaybackSessionId = AUDIO_SESSION_ID_GENERATE;
private int mAudioRecordingSessionId = AUDIO_SESSION_ID_GENERATE;
/**
* Sets the lock state of the device. The permission {@code ADD_ALWAYS_UNLOCKED_DISPLAY}
@@ -705,6 +741,54 @@ public final class VirtualDeviceParams implements Parcelable {
return this;
}
/**
* Sets audio playback session id specific for this virtual device.
*
* <p>Audio players constructed within context associated with this virtual device
* will be automatically assigned provided session id.
*
* <p>Requires {@link #DEVICE_POLICY_CUSTOM} to be set for {@link #POLICY_TYPE_AUDIO},
* otherwise {@link #build()} method will throw {@link IllegalArgumentException} if
* the playback session id is set to value other than
* {@link android.media.AudioManager.AUDIO_SESSION_ID_GENERATE}.
*
* @param playbackSessionId requested device-specific audio session id for playback
* @see android.media.AudioManager.generateAudioSessionId()
* @see android.media.AudioTrack.Builder.setContext(Context)
*/
@NonNull
public Builder setAudioPlaybackSessionId(int playbackSessionId) {
if (playbackSessionId != AUDIO_SESSION_ID_GENERATE || playbackSessionId < 0) {
throw new IllegalArgumentException("Invalid playback audio session id");
}
mAudioPlaybackSessionId = playbackSessionId;
return this;
}
/**
* Sets audio recording session id specific for this virtual device.
*
* <p>{@link android.media.AudioRecord} constructed within context associated with this
* virtual device will be automatically assigned provided session id.
*
* <p>Requires {@link #DEVICE_POLICY_CUSTOM} to be set for {@link #POLICY_TYPE_AUDIO},
* otherwise {@link #build()} method will throw {@link IllegalArgumentException} if
* the recording session id is set to value other than
* {@link android.media.AudioManager.AUDIO_SESSION_ID_GENERATE}.
*
* @param recordingSessionId requested device-specific audio session id for playback
* @see android.media.AudioManager.generateAudioSessionId()
* @see android.media.AudioRecord.Builder.setContext(Context)
*/
@NonNull
public Builder setAudioRecordingSessionId(int recordingSessionId) {
if (recordingSessionId != AUDIO_SESSION_ID_GENERATE || recordingSessionId < 0) {
throw new IllegalArgumentException("Invalid recording audio session id");
}
mAudioRecordingSessionId = recordingSessionId;
return this;
}
/**
* Builds the {@link VirtualDeviceParams} instance.
*
@@ -721,6 +805,15 @@ public final class VirtualDeviceParams implements Parcelable {
"DEVICE_POLICY_CUSTOM for POLICY_TYPE_SENSORS is required for creating "
+ "virtual sensors.");
}
if ((mAudioPlaybackSessionId != AUDIO_SESSION_ID_GENERATE
|| mAudioRecordingSessionId != AUDIO_SESSION_ID_GENERATE)
&& mDevicePolicies.get(POLICY_TYPE_AUDIO, DEVICE_POLICY_DEFAULT)
!= DEVICE_POLICY_CUSTOM) {
throw new IllegalArgumentException("DEVICE_POLICY_CUSTOM for POLICY_TYPE_AUDIO is "
+ "required for configuration of device-specific audio session ids.");
}
SparseArray<Set<String>> sensorNameByType = new SparseArray();
for (int i = 0; i < mVirtualSensorConfigs.size(); ++i) {
VirtualSensorConfig config = mVirtualSensorConfigs.get(i);
@@ -744,7 +837,9 @@ public final class VirtualDeviceParams implements Parcelable {
mName,
mDevicePolicies,
mVirtualSensorConfigs,
mDefaultRecentsPolicy);
mDefaultRecentsPolicy,
mAudioPlaybackSessionId,
mAudioRecordingSessionId);
}
}
}

View File

@@ -253,6 +253,16 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
return mParams.getDevicePolicy(policyType);
}
/** Returns device-specific audio session id for playback. */
public int getAudioPlaybackSessionId() {
return mParams.getAudioPlaybackSessionId();
}
/** Returns device-specific audio session id for recording. */
public int getAudioRecordingSessionId() {
return mParams.getAudioRecordingSessionId();
}
/** Returns the unique device ID of this device. */
@Override // Binder call
public int getDeviceId() {

View File

@@ -16,6 +16,8 @@
package com.android.server.companion.virtual;
import static android.media.AudioManager.AUDIO_SESSION_ID_GENERATE;
import static com.android.server.wm.ActivityInterceptorCallback.VIRTUAL_DEVICE_SERVICE_ORDERED_ID;
import android.annotation.NonNull;
@@ -388,6 +390,24 @@ public class VirtualDeviceManagerService extends SystemService {
return VirtualDeviceManager.DEVICE_ID_DEFAULT;
}
@Override // Binder call
public int getAudioPlaybackSessionId(int deviceId) {
synchronized (mVirtualDeviceManagerLock) {
VirtualDeviceImpl virtualDevice = mVirtualDevices.get(deviceId);
return virtualDevice != null
? virtualDevice.getAudioPlaybackSessionId() : AUDIO_SESSION_ID_GENERATE;
}
}
@Override // Binder call
public int getAudioRecordingSessionId(int deviceId) {
synchronized (mVirtualDeviceManagerLock) {
VirtualDeviceImpl virtualDevice = mVirtualDevices.get(deviceId);
return virtualDevice != null
? virtualDevice.getAudioRecordingSessionId() : AUDIO_SESSION_ID_GENERATE;
}
}
@Nullable
private AssociationInfo getAssociationInfo(String packageName, int associationId) {
final int callingUserId = getCallingUserHandle().getIdentifier();

View File

@@ -41,6 +41,8 @@ public class VirtualDeviceParamsTest {
private static final String SENSOR_NAME = "VirtualSensorName";
private static final String SENSOR_VENDOR = "VirtualSensorVendor";
private static final int PLAYBACK_SESSION_ID = 42;
private static final int RECORDING_SESSION_ID = 77;
@Test
public void parcelable_shouldRecreateSuccessfully() {
@@ -49,6 +51,8 @@ public class VirtualDeviceParamsTest {
.setUsersWithMatchingAccounts(Set.of(UserHandle.of(123), UserHandle.of(456)))
.setDevicePolicy(POLICY_TYPE_SENSORS, DEVICE_POLICY_CUSTOM)
.setDevicePolicy(POLICY_TYPE_AUDIO, DEVICE_POLICY_CUSTOM)
.setAudioPlaybackSessionId(PLAYBACK_SESSION_ID)
.setAudioRecordingSessionId(RECORDING_SESSION_ID)
.addVirtualSensorConfig(
new VirtualSensorConfig.Builder(TYPE_ACCELEROMETER, SENSOR_NAME)
.setVendor(SENSOR_VENDOR)
@@ -65,6 +69,8 @@ public class VirtualDeviceParamsTest {
.containsExactly(UserHandle.of(123), UserHandle.of(456));
assertThat(params.getDevicePolicy(POLICY_TYPE_SENSORS)).isEqualTo(DEVICE_POLICY_CUSTOM);
assertThat(params.getDevicePolicy(POLICY_TYPE_AUDIO)).isEqualTo(DEVICE_POLICY_CUSTOM);
assertThat(params.getAudioPlaybackSessionId()).isEqualTo(PLAYBACK_SESSION_ID);
assertThat(params.getAudioRecordingSessionId()).isEqualTo(RECORDING_SESSION_ID);
List<VirtualSensorConfig> sensorConfigs = params.getVirtualSensorConfigs();
assertThat(sensorConfigs).hasSize(1);