Add option to configure audio session ids for VirtualDevice
Bug: 261698699 Bug: 249777386 Test: atest VirtualDeviceParamsTest VirtualDeviceManagerBasicTest Change-Id: If0906836bdacc067d41fab0844603d8f2b7160e6
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user