Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3099d15e authored by Jan Sebechlebsky's avatar Jan Sebechlebsky
Browse files

Add option to configure audio session ids for VirtualDevice

Bug: 261698699
Bug: 249777386
Test: atest VirtualDeviceParamsTest VirtualDeviceManagerBasicTest
Change-Id: If0906836bdacc067d41fab0844603d8f2b7160e6
parent 0691dd15
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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);
+12 −0
Original line number Diff line number Diff line
@@ -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);
}
+16 −6
Original line number Diff line number Diff line
@@ -269,10 +269,15 @@ 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.
        if (mService == null) {
            return AUDIO_SESSION_ID_GENERATE;
        }
        try {
            return mService.getAudioPlaybackSessionId(deviceId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Returns device-specific audio session id for audio recording.
@@ -287,10 +292,15 @@ 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.
        if (mService == null) {
            return AUDIO_SESSION_ID_GENERATE;
        }
        try {
            return mService.getAudioRecordingSessionId(deviceId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * A virtual device has its own virtual display, audio output, microphone, and camera etc. The
+99 −4
Original line number Diff line number Diff line
@@ -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);
        }
    }
}
+10 −0
Original line number Diff line number Diff line
@@ -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() {
Loading