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

Commit 2fdf339d authored by Robert Wu's avatar Robert Wu Committed by Android (Google) Code Review
Browse files

Merge "Change Java APIs to use multiple routed devices" into main

parents 0e3a4591 b5565599
Loading
Loading
Loading
Loading
+17 −9
Original line number Diff line number Diff line
@@ -584,14 +584,23 @@ static jboolean android_media_AudioRecord_setInputDevice(
    return lpRecorder->setInputDevice(device_id) == NO_ERROR;
}

static jint android_media_AudioRecord_getRoutedDeviceId(
                JNIEnv *env,  jobject thiz) {

static jintArray android_media_AudioRecord_getRoutedDeviceIds(JNIEnv *env, jobject thiz) {
    sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
    if (lpRecorder == 0) {
        return 0;
    if (lpRecorder == NULL) {
        return NULL;
    }
    DeviceIdVector deviceIds = lpRecorder->getRoutedDeviceIds();
    jintArray result;
    result = env->NewIntArray(deviceIds.size());
    if (result == NULL) {
        return NULL;
    }
    jint *values = env->GetIntArrayElements(result, 0);
    for (unsigned int i = 0; i < deviceIds.size(); i++) {
        values[i++] = static_cast<jint>(deviceIds[i]);
    }
    return (jint)lpRecorder->getRoutedDeviceId();
    env->ReleaseIntArrayElements(result, values, 0);
    return result;
}

// Enable and Disable Callback methods are synchronized on the Java side
@@ -821,8 +830,7 @@ static const JNINativeMethod gMethods[] = {
        // name,               signature,  funcPtr
        {"native_start", "(II)I", (void *)android_media_AudioRecord_start},
        {"native_stop", "()V", (void *)android_media_AudioRecord_stop},
        {"native_setup",
         "(Ljava/lang/Object;Ljava/lang/Object;[IIIII[ILandroid/os/Parcel;JII)I",
        {"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;[IIIII[ILandroid/os/Parcel;JII)I",
         (void *)android_media_AudioRecord_setup},
        {"native_finalize", "()V", (void *)android_media_AudioRecord_finalize},
        {"native_release", "()V", (void *)android_media_AudioRecord_release},
@@ -846,7 +854,7 @@ static const JNINativeMethod gMethods[] = {
        {"native_getMetrics", "()Landroid/os/PersistableBundle;",
         (void *)android_media_AudioRecord_native_getMetrics},
        {"native_setInputDevice", "(I)Z", (void *)android_media_AudioRecord_setInputDevice},
        {"native_getRoutedDeviceId", "()I", (void *)android_media_AudioRecord_getRoutedDeviceId},
        {"native_getRoutedDeviceIds", "()[I", (void *)android_media_AudioRecord_getRoutedDeviceIds},
        {"native_enableDeviceCallback", "()V",
         (void *)android_media_AudioRecord_enableDeviceCallback},
        {"native_disableDeviceCallback", "()V",
+15 −7
Original line number Diff line number Diff line
@@ -1190,15 +1190,23 @@ static jboolean android_media_AudioTrack_setOutputDevice(
    }
    return lpTrack->setOutputDevice(device_id) == NO_ERROR;
}

static jint android_media_AudioTrack_getRoutedDeviceId(
                JNIEnv *env,  jobject thiz) {

static jintArray android_media_AudioTrack_getRoutedDeviceIds(JNIEnv *env, jobject thiz) {
    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
    if (lpTrack == NULL) {
        return 0;
        return NULL;
    }
    DeviceIdVector deviceIds = lpTrack->getRoutedDeviceIds();
    jintArray result;
    result = env->NewIntArray(deviceIds.size());
    if (result == NULL) {
        return NULL;
    }
    jint *values = env->GetIntArrayElements(result, 0);
    for (unsigned int i = 0; i < deviceIds.size(); i++) {
        values[i++] = static_cast<jint>(deviceIds[i]);
    }
    return (jint)lpTrack->getRoutedDeviceId();
    env->ReleaseIntArrayElements(result, values, 0);
    return result;
}

static void android_media_AudioTrack_enableDeviceCallback(
@@ -1503,7 +1511,7 @@ static const JNINativeMethod gMethods[] = {
         (void *)android_media_AudioTrack_setAuxEffectSendLevel},
        {"native_attachAuxEffect", "(I)I", (void *)android_media_AudioTrack_attachAuxEffect},
        {"native_setOutputDevice", "(I)Z", (void *)android_media_AudioTrack_setOutputDevice},
        {"native_getRoutedDeviceId", "()I", (void *)android_media_AudioTrack_getRoutedDeviceId},
        {"native_getRoutedDeviceIds", "()[I", (void *)android_media_AudioTrack_getRoutedDeviceIds},
        {"native_enableDeviceCallback", "()V",
         (void *)android_media_AudioTrack_enableDeviceCallback},
        {"native_disableDeviceCallback", "()V",
+7 −8
Original line number Diff line number Diff line
@@ -61,21 +61,20 @@ JNIDeviceCallback::~JNIDeviceCallback()
}

void JNIDeviceCallback::onAudioDeviceUpdate(audio_io_handle_t audioIo,
                                            audio_port_handle_t deviceId)
{
                                            const DeviceIdVector& deviceIds) {
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    if (env == NULL) {
        return;
    }

    ALOGV("%s audioIo %d deviceId %d", __FUNCTION__, audioIo, deviceId);
    env->CallStaticVoidMethod(mClass,
                              mPostEventFromNative,
                              mObject,
                              AUDIO_NATIVE_EVENT_ROUTING_CHANGE, deviceId, 0, NULL);
    ALOGV("%s audioIo %d deviceIds %s", __FUNCTION__, audioIo, toString(deviceIds).c_str());
    // Java should query the new device ids once it gets the event.
    // TODO(b/378505346): Pass the deviceIds to Java to avoid race conditions.
    env->CallStaticVoidMethod(mClass, mPostEventFromNative, mObject,
                              AUDIO_NATIVE_EVENT_ROUTING_CHANGE, 0 /*arg1*/, 0 /*arg2*/,
                              NULL /*obj*/);
    if (env->ExceptionCheck()) {
        ALOGW("An exception occurred while notifying an event.");
        env->ExceptionClear();
    }
}
+1 −2
Original line number Diff line number Diff line
@@ -31,8 +31,7 @@ public:
    JNIDeviceCallback(JNIEnv* env, jobject thiz, jobject weak_thiz, jmethodID postEventFromNative);
    ~JNIDeviceCallback();

    virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo,
                                     audio_port_handle_t deviceId);
    virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo, const DeviceIdVector& deviceIds);

private:
    void sendEvent(int event);
+41 −26
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

@@ -59,6 +60,8 @@ public final class AudioPlaybackConfiguration implements Parcelable {
    public static final int PLAYER_UPID_INVALID = -1;
    /** @hide */
    public static final int PLAYER_DEVICEID_INVALID = 0;
    /** @hide */
    public static final int[] PLAYER_DEVICEIDS_INVALID = new int[0];

    // information about the implementation
    /**
@@ -335,7 +338,7 @@ public final class AudioPlaybackConfiguration implements Parcelable {
    private final Object mUpdateablePropLock = new Object();

    @GuardedBy("mUpdateablePropLock")
    private int mDeviceId;
    private @NonNull int[] mDeviceIds = AudioPlaybackConfiguration.PLAYER_DEVICEIDS_INVALID;
    @GuardedBy("mUpdateablePropLock")
    private int mSessionId;
    @GuardedBy("mUpdateablePropLock")
@@ -364,7 +367,7 @@ public final class AudioPlaybackConfiguration implements Parcelable {
        mClientUid = uid;
        mClientPid = pid;
        mMutedState = 0;
        mDeviceId = PLAYER_DEVICEID_INVALID;
        mDeviceIds = AudioPlaybackConfiguration.PLAYER_DEVICEIDS_INVALID;
        mPlayerState = PLAYER_STATE_IDLE;
        mPlayerAttr = pic.mAttributes;
        if ((sPlayerDeathMonitor != null) && (pic.mIPlayer != null)) {
@@ -388,10 +391,11 @@ public final class AudioPlaybackConfiguration implements Parcelable {
    }

    // sets the fields that are updateable and require synchronization
    private void setUpdateableFields(int deviceId, int sessionId, int mutedState, FormatInfo format)
    private void setUpdateableFields(int[] deviceIds, int sessionId, int mutedState,
            FormatInfo format)
    {
        synchronized (mUpdateablePropLock) {
            mDeviceId = deviceId;
            mDeviceIds = deviceIds;
            mSessionId = sessionId;
            mMutedState = mutedState;
            mFormatInfo = format;
@@ -427,7 +431,7 @@ public final class AudioPlaybackConfiguration implements Parcelable {
        anonymCopy.mClientPid = PLAYER_UPID_INVALID;
        anonymCopy.mIPlayerShell = null;
        anonymCopy.setUpdateableFields(
                /*deviceId*/ PLAYER_DEVICEID_INVALID,
                /*deviceIds*/ new int[0],
                /*sessionId*/ AudioSystem.AUDIO_SESSION_ALLOCATE,
                /*mutedState*/ 0,
                FormatInfo.DEFAULT);
@@ -471,14 +475,14 @@ public final class AudioPlaybackConfiguration implements Parcelable {
    @Deprecated
    @FlaggedApi(FLAG_ROUTED_DEVICE_IDS)
    public @Nullable AudioDeviceInfo getAudioDeviceInfo() {
        final int deviceId;
        final int[] deviceIds;
        synchronized (mUpdateablePropLock) {
            deviceId = mDeviceId;
            deviceIds = mDeviceIds;
        }
        if (deviceId == PLAYER_DEVICEID_INVALID) {
        if (deviceIds.length == 0) {
            return null;
        }
        return AudioManager.getDeviceForPortId(deviceId, AudioManager.GET_DEVICES_OUTPUTS);
        return AudioManager.getDeviceForPortId(deviceIds[0], AudioManager.GET_DEVICES_OUTPUTS);
    }

    /**
@@ -491,10 +495,18 @@ public final class AudioPlaybackConfiguration implements Parcelable {
    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
    public @NonNull List<AudioDeviceInfo> getAudioDeviceInfos() {
        List<AudioDeviceInfo> audioDeviceInfos = new ArrayList<AudioDeviceInfo>();
        AudioDeviceInfo audioDeviceInfo = getAudioDeviceInfo();
        final int[] deviceIds;
        synchronized (mUpdateablePropLock) {
            deviceIds = mDeviceIds;
        }

        for (int i = 0; i < deviceIds.length; i++) {
            AudioDeviceInfo audioDeviceInfo = AudioManager.getDeviceForPortId(deviceIds[i],
                    AudioManager.GET_DEVICES_OUTPUTS);
            if (audioDeviceInfo != null) {
                audioDeviceInfos.add(audioDeviceInfo);
            }
        }
        return audioDeviceInfos;
    }

@@ -701,15 +713,15 @@ public final class AudioPlaybackConfiguration implements Parcelable {
     * @hide
     * Handle a player state change
     * @param event
     * @param deviceId active device id or {@Code PLAYER_DEVICEID_INVALID}
     * <br>Note device id is valid for {@code PLAYER_UPDATE_DEVICE_ID} or
     * <br>{@code PLAYER_STATE_STARTED} events, as the device id will be reset to none when
     * <br>pausing or stopping playback. It will be set to active device when playback starts or
     * @param deviceIds an array of device ids. This can be empty.
     * <br>Note device ids are non-empty for {@code PLAYER_UPDATE_DEVICE_ID} or
     * <br>{@code PLAYER_STATE_STARTED} events, as the device ids will be emptied when pausing
     * <br>or stopping playback. It will be set to active devices when playback starts or
     * <br>it will be changed when PLAYER_UPDATE_DEVICE_ID is sent. The latter can happen if the
     * <br>device changes in the middle of playback.
     * <br>devices change in the middle of playback.
     * @return true if the state changed, false otherwise
     */
    public boolean handleStateEvent(int event, int deviceId) {
    public boolean handleStateEvent(int event, int[] deviceIds) {
        boolean changed = false;
        synchronized (mUpdateablePropLock) {

@@ -720,8 +732,8 @@ public final class AudioPlaybackConfiguration implements Parcelable {
            }

            if (event == PLAYER_STATE_STARTED || event == PLAYER_UPDATE_DEVICE_ID) {
                changed = changed || (mDeviceId != deviceId);
                mDeviceId = deviceId;
                changed = changed || !Arrays.equals(mDeviceIds, deviceIds);
                mDeviceIds = deviceIds;
            }

            if (changed && (event == PLAYER_STATE_RELEASED) && (mIPlayerShell != null)) {
@@ -801,8 +813,8 @@ public final class AudioPlaybackConfiguration implements Parcelable {
    @Override
    public int hashCode() {
        synchronized (mUpdateablePropLock) {
            return Objects.hash(mPlayerIId, mDeviceId, mMutedState, mPlayerType, mClientUid,
                    mClientPid, mSessionId);
            return Objects.hash(mPlayerIId, Arrays.toString(mDeviceIds), mMutedState, mPlayerType,
                    mClientUid, mClientPid, mSessionId);
        }
    }

@@ -815,7 +827,7 @@ public final class AudioPlaybackConfiguration implements Parcelable {
    public void writeToParcel(Parcel dest, int flags) {
        synchronized (mUpdateablePropLock) {
            dest.writeInt(mPlayerIId);
            dest.writeInt(mDeviceId);
            dest.writeIntArray(mDeviceIds);
            dest.writeInt(mMutedState);
            dest.writeInt(mPlayerType);
            dest.writeInt(mClientUid);
@@ -834,7 +846,10 @@ public final class AudioPlaybackConfiguration implements Parcelable {

    private AudioPlaybackConfiguration(Parcel in) {
        mPlayerIId = in.readInt();
        mDeviceId = in.readInt();
        mDeviceIds = new int[in.readInt()];
        for (int i = 0; i < mDeviceIds.length; i++) {
            mDeviceIds[i] = in.readInt();
        }
        mMutedState = in.readInt();
        mPlayerType = in.readInt();
        mClientUid = in.readInt();
@@ -855,7 +870,7 @@ public final class AudioPlaybackConfiguration implements Parcelable {
        AudioPlaybackConfiguration that = (AudioPlaybackConfiguration) o;

        return ((mPlayerIId == that.mPlayerIId)
                && (mDeviceId == that.mDeviceId)
                && Arrays.equals(mDeviceIds, that.mDeviceIds)
                && (mMutedState == that.mMutedState)
                && (mPlayerType == that.mPlayerType)
                && (mClientUid == that.mClientUid)
@@ -868,7 +883,7 @@ public final class AudioPlaybackConfiguration implements Parcelable {
        StringBuilder apcToString = new StringBuilder();
        synchronized (mUpdateablePropLock) {
            apcToString.append("AudioPlaybackConfiguration piid:").append(mPlayerIId).append(
                    " deviceId:").append(mDeviceId).append(" type:").append(
                    " deviceIds:").append(Arrays.toString(mDeviceIds)).append(" type:").append(
                    toLogFriendlyPlayerType(mPlayerType)).append(" u/pid:").append(
                    mClientUid).append(
                    "/").append(mClientPid).append(" state:").append(
Loading