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

Commit 8a60f436 authored by Oscar Azucena's avatar Oscar Azucena
Browse files

Added update device info playback configuration

Added update routed device information to playback configuration. Added
reporting mechanism to audio service, AudioBase uses that to report
audio devices changes to playback activity monitor.

Bug: 156790437
Test: play audio see audio configuration changes
Change-Id: I859d33a4a7b5c02bdde574fcd45234150316f3a6
parent 81b11c39
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -19906,6 +19906,7 @@ package android.media {
  public final class AudioPlaybackConfiguration implements android.os.Parcelable {
    method public int describeContents();
    method public android.media.AudioAttributes getAudioAttributes();
    method @Nullable public android.media.AudioDeviceInfo getAudioDevice();
    method public void writeToParcel(android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.media.AudioPlaybackConfiguration> CREATOR;
  }
+59 −6
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.media.AudioAttributes.ALLOW_CAPTURE_BY_NONE;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Binder;
import android.os.IBinder;
@@ -47,6 +48,8 @@ public final class AudioPlaybackConfiguration implements Parcelable {
    public static final int PLAYER_PIID_INVALID = -1;
    /** @hide */
    public static final int PLAYER_UPID_INVALID = -1;
    /** @hide */
    public static final int PLAYER_DEVICEID_INVALID = 0;

    // information about the implementation
    /**
@@ -158,6 +161,11 @@ public final class AudioPlaybackConfiguration implements Parcelable {
     */
    @SystemApi
    public static final int PLAYER_STATE_STOPPED = 4;
    /**
     * @hide
     * The state used to update device id, does not actually change the state of the player
     */
    public static final int PLAYER_UPDATE_DEVICE_ID = 5;

    /** @hide */
    @IntDef({
@@ -166,7 +174,8 @@ public final class AudioPlaybackConfiguration implements Parcelable {
        PLAYER_STATE_IDLE,
        PLAYER_STATE_STARTED,
        PLAYER_STATE_PAUSED,
        PLAYER_STATE_STOPPED
        PLAYER_STATE_STOPPED,
        PLAYER_UPDATE_DEVICE_ID
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface PlayerState {}
@@ -184,6 +193,8 @@ public final class AudioPlaybackConfiguration implements Parcelable {
    private int mPlayerState;
    private AudioAttributes mPlayerAttr; // never null

    private int mDeviceId;

    /**
     * Never use without initializing parameters afterwards
     */
@@ -201,6 +212,7 @@ public final class AudioPlaybackConfiguration implements Parcelable {
        mPlayerType = pic.mPlayerType;
        mClientUid = uid;
        mClientPid = pid;
        mDeviceId = PLAYER_DEVICEID_INVALID;
        mPlayerState = PLAYER_STATE_IDLE;
        mPlayerAttr = pic.mAttributes;
        if ((sPlayerDeathMonitor != null) && (pic.mIPlayer != null)) {
@@ -241,6 +253,7 @@ public final class AudioPlaybackConfiguration implements Parcelable {
                        in.mPlayerAttr.getAllowedCapturePolicy() == ALLOW_CAPTURE_BY_ALL
                        ? ALLOW_CAPTURE_BY_ALL : ALLOW_CAPTURE_BY_NONE)
                .build();
        anonymCopy.mDeviceId = in.mDeviceId;
        // anonymized data
        anonymCopy.mPlayerType = PLAYER_TYPE_UNKNOWN;
        anonymCopy.mClientUid = PLAYER_UPID_INVALID;
@@ -277,6 +290,25 @@ public final class AudioPlaybackConfiguration implements Parcelable {
        return mClientPid;
    }

    /**
     * Returns information about the {@link AudioDeviceInfo} used for this playback.
     * @return the audio playback device or null if the device is not available at the time of query
     */
    public @Nullable AudioDeviceInfo getAudioDevice() {
        if (mDeviceId == PLAYER_DEVICEID_INVALID) {
            return null;
        }
        // TODO(175802592): change this to AudioManager.getDeviceForPortId() when available
        AudioDeviceInfo[] devices =
                AudioManager.getDevicesStatic(AudioManager.GET_DEVICES_OUTPUTS);
        for (int i = 0; i < devices.length; i++) {
            if (devices[i].getId() == mDeviceId) {
                return devices[i];
            }
        }
        return null;
    }

    /**
     * @hide
     * Return the type of player linked to this configuration.
@@ -359,13 +391,29 @@ 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
     * <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.
     * @return true if the state changed, false otherwise
     */
    public boolean handleStateEvent(int event) {
        final boolean changed;
    public boolean handleStateEvent(int event, int deviceId) {
        boolean changed = false;
        synchronized (this) {

            // Do not update if it is only device id update
            if (event != PLAYER_UPDATE_DEVICE_ID) {
                changed = (mPlayerState != event);
                mPlayerState = event;
            }

            if (event == PLAYER_STATE_STARTED || event == PLAYER_UPDATE_DEVICE_ID) {
                changed = changed || (mDeviceId != deviceId);
                mDeviceId = deviceId;
            }

            if (changed && (event == PLAYER_STATE_RELEASED) && (mIPlayerShell != null)) {
                mIPlayerShell.release();
                mIPlayerShell = null;
@@ -436,7 +484,7 @@ public final class AudioPlaybackConfiguration implements Parcelable {

    @Override
    public int hashCode() {
        return Objects.hash(mPlayerIId, mPlayerType, mClientUid, mClientPid);
        return Objects.hash(mPlayerIId, mDeviceId, mPlayerType, mClientUid, mClientPid);
    }

    @Override
@@ -447,6 +495,7 @@ public final class AudioPlaybackConfiguration implements Parcelable {
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mPlayerIId);
        dest.writeInt(mDeviceId);
        dest.writeInt(mPlayerType);
        dest.writeInt(mClientUid);
        dest.writeInt(mClientPid);
@@ -461,6 +510,7 @@ public final class AudioPlaybackConfiguration implements Parcelable {

    private AudioPlaybackConfiguration(Parcel in) {
        mPlayerIId = in.readInt();
        mDeviceId = in.readInt();
        mPlayerType = in.readInt();
        mClientUid = in.readInt();
        mClientPid = in.readInt();
@@ -478,6 +528,7 @@ public final class AudioPlaybackConfiguration implements Parcelable {
        AudioPlaybackConfiguration that = (AudioPlaybackConfiguration) o;

        return ((mPlayerIId == that.mPlayerIId)
                && (mDeviceId == that.mDeviceId)
                && (mPlayerType == that.mPlayerType)
                && (mClientUid == that.mClientUid)
                && (mClientPid == that.mClientPid));
@@ -486,6 +537,7 @@ public final class AudioPlaybackConfiguration implements Parcelable {
    @Override
    public String toString() {
        return "AudioPlaybackConfiguration piid:" + mPlayerIId
                + " deviceId:" + mDeviceId
                + " type:" + toLogFriendlyPlayerType(mPlayerType)
                + " u/pid:" + mClientUid + "/" + mClientPid
                + " state:" + toLogFriendlyPlayerState(mPlayerState)
@@ -571,6 +623,7 @@ public final class AudioPlaybackConfiguration implements Parcelable {
            case PLAYER_STATE_STARTED: return "started";
            case PLAYER_STATE_PAUSED: return "paused";
            case PLAYER_STATE_STOPPED: return "stopped";
            case PLAYER_UPDATE_DEVICE_ID: return "device";
            default:
                return "unknown player state - FIXME";
        }
+24 −3
Original line number Diff line number Diff line
@@ -1824,6 +1824,7 @@ public class AudioTrack extends PlayerBase

    @Override
    protected void finalize() {
        tryToDisableNativeRoutingCallback();
        baseRelease();
        native_finalize();
    }
@@ -2717,9 +2718,15 @@ public class AudioTrack extends PlayerBase
    }

    private void startImpl() {
        synchronized (mRoutingChangeListeners) {
            if (!mEnableSelfRoutingMonitor) {
                testEnableNativeRoutingCallbacksLocked();
                mEnableSelfRoutingMonitor = true;
            }
        }
        synchronized(mPlayStateLock) {
            baseStart();
            native_start();
            baseStart(native_getRoutedDeviceId());
            if (mPlayState == PLAYSTATE_PAUSED_STOPPING) {
                mPlayState = PLAYSTATE_STOPPING;
            } else {
@@ -2757,6 +2764,7 @@ public class AudioTrack extends PlayerBase
                mPlayStateLock.notify();
            }
        }
        tryToDisableNativeRoutingCallback();
    }

    /**
@@ -3496,12 +3504,21 @@ public class AudioTrack extends PlayerBase
        return null;
    }

    private void tryToDisableNativeRoutingCallback() {
        synchronized (mRoutingChangeListeners) {
            if (mEnableSelfRoutingMonitor) {
                mEnableSelfRoutingMonitor = false;
                testDisableNativeRoutingCallbacksLocked();
            }
        }
    }

    /*
     * Call BEFORE adding a routing callback handler.
     */
    @GuardedBy("mRoutingChangeListeners")
    private void testEnableNativeRoutingCallbacksLocked() {
        if (mRoutingChangeListeners.size() == 0) {
        if (mRoutingChangeListeners.size() == 0 && !mEnableSelfRoutingMonitor) {
            native_enableDeviceCallback();
        }
    }
@@ -3511,7 +3528,7 @@ public class AudioTrack extends PlayerBase
     */
    @GuardedBy("mRoutingChangeListeners")
    private void testDisableNativeRoutingCallbacksLocked() {
        if (mRoutingChangeListeners.size() == 0) {
        if (mRoutingChangeListeners.size() == 0 && !mEnableSelfRoutingMonitor) {
            native_disableDeviceCallback();
        }
    }
@@ -3528,6 +3545,9 @@ public class AudioTrack extends PlayerBase
    private ArrayMap<AudioRouting.OnRoutingChangedListener,
            NativeRoutingEventHandlerDelegate> mRoutingChangeListeners = new ArrayMap<>();

    @GuardedBy("mRoutingChangeListeners")
    private boolean mEnableSelfRoutingMonitor;

   /**
    * Adds an {@link AudioRouting.OnRoutingChangedListener} to receive notifications of routing
    * changes on this AudioTrack.
@@ -3627,6 +3647,7 @@ public class AudioTrack extends PlayerBase
     */
    private void broadcastRoutingChange() {
        AudioManager.resetAudioPortGeneration();
        baseUpdateDeviceId(getRoutedDevice());
        synchronized (mRoutingChangeListeners) {
            for (NativeRoutingEventHandlerDelegate delegate : mRoutingChangeListeners.values()) {
                delegate.notifyClient();
+25 −1
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ import android.annotation.SystemApi;

import com.android.internal.util.Preconditions;

import java.util.ArrayList;

/**
 * The HwAudioSource represents the audio playback directly from a source audio device.
 * It currently supports {@link HwAudioSource#start()} and {@link HwAudioSource#stop()} only
@@ -130,10 +132,32 @@ public class HwAudioSource extends PlayerBase {
     */
    public void start() {
        Preconditions.checkState(!isPlaying(), "HwAudioSource is currently playing");
        baseStart();
        mNativeHandle = AudioSystem.startAudioSource(
                mAudioDeviceInfo.getPort().activeConfig(),
                mAudioAttributes);
        // FIXME: b/174876389 clean up device id reporting
        baseStart(getDeviceId());
    }

    private int getDeviceId() {
        ArrayList<AudioPatch> patches = new ArrayList<AudioPatch>();
        if (AudioManager.listAudioPatches(patches) != AudioManager.SUCCESS) {
            return 0;
        }

        for (int i = 0; i < patches.size(); i++) {
            AudioPatch patch = patches.get(i);
            AudioPortConfig[] sources = patch.sources();
            AudioPortConfig[] sinks = patch.sinks();
            if ((sources != null) && (sources.length > 0)) {
                for (int c = 0;  c < sources.length; c++) {
                    if (sources[c].port().id() == mAudioDeviceInfo.getId()) {
                        return sinks[c].port().id();
                    }
                }
            }
        }
        return 0;
    }

    /**
+1 −1
Original line number Diff line number Diff line
@@ -62,7 +62,7 @@ interface IAudioService {

    oneway void playerAttributes(in int piid, in AudioAttributes attr);

    oneway void playerEvent(in int piid, in int event);
    oneway void playerEvent(in int piid, in int event, in int deviceId);

    oneway void releasePlayer(in int piid);

Loading