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

Commit 7da0e982 authored by Andy Hung's avatar Andy Hung
Browse files

VolumeShaper: Remove PlayerProxy constructor

Use of the VolumeShaper through PlayerProxy requires system ids,
which is different enough from PlayerBase that we don't allow
direct construction.

Test: Ducking
Bug: 31015569
Change-Id: Ia98ec5396047ae39e78237bb7e485d07f2eb1efd
parent 7548ad9e
Loading
Loading
Loading
Loading
+22 −53
Original line number Diff line number Diff line
@@ -38,8 +38,6 @@ public final class VolumeShaper {
    /* member variables */
    private int mId;
    private final WeakReference<PlayerBase> mWeakPlayerBase;
    private final WeakReference<PlayerProxy> mWeakPlayerProxy;
    private PlayerProxy mPlayerProxy;

    /**
     * Constructs a {@code VolumeShaper} from a {@link VolumeShaper.Configuration} and an
@@ -66,35 +64,6 @@ public final class VolumeShaper {
    /* package */ VolumeShaper(
            @NonNull Configuration configuration, @NonNull PlayerBase playerBase) {
        mWeakPlayerBase = new WeakReference<PlayerBase>(playerBase);
        mPlayerProxy = null;
        mWeakPlayerProxy = null;
        mId = applyPlayer(configuration, new Operation.Builder().defer().build());
    }

    /**
     * @hide
     * Constructs a {@code VolumeShaper} from a {@link VolumeShaper.Configuration} and a
     * {@code PlayerProxy} object.  The PlayerProxy object requires that the configuration
     * be set with a system VolumeShaper id (this is a reserved value).
     *
     * @param configuration
     * @param playerProxy
     */
    public VolumeShaper(
            @NonNull Configuration configuration,
            @NonNull PlayerProxy playerProxy,
            boolean keepReference) {
        if (configuration.getId() < 0) {
            throw new IllegalArgumentException("playerProxy configuration id must be specified");
        }
        if (keepReference) {
            mPlayerProxy = playerProxy;
            mWeakPlayerProxy = null;
        } else {
            mWeakPlayerProxy = new WeakReference<PlayerProxy>(playerProxy);
            mPlayerProxy = null;
        }
        mWeakPlayerBase = null;
        mId = applyPlayer(configuration, new Operation.Builder().defer().build());
    }

@@ -155,10 +124,6 @@ public final class VolumeShaper {
        if (mWeakPlayerBase != null) {
            mWeakPlayerBase.clear();
        }
        if (mWeakPlayerProxy != null) {
            mWeakPlayerProxy.clear();
        }
        mPlayerProxy = null;
    }

    @Override
@@ -177,20 +142,7 @@ public final class VolumeShaper {
            @NonNull VolumeShaper.Configuration configuration,
            @NonNull VolumeShaper.Operation operation) {
        final int id;
        if (mPlayerProxy != null || mWeakPlayerProxy != null) {
            // The PlayerProxy accepts only one way transactions so
            // the Configuration must have an id set to one of the system
            // ids (a positive value less than 16).
            PlayerProxy player = mWeakPlayerProxy != null ? mWeakPlayerProxy.get() : mPlayerProxy;
            if (player == null) {
                throw new IllegalStateException("player deallocated");
            }
            id = configuration.getId();
            if (id < 0) {
                throw new IllegalArgumentException("proxy requires configuration with id");
            }
            player.applyVolumeShaper(configuration, operation);
        } else if (mWeakPlayerBase != null) {
        if (mWeakPlayerBase != null) {
            PlayerBase player = mWeakPlayerBase.get();
            if (player == null) {
                throw new IllegalStateException("player deallocated");
@@ -220,9 +172,7 @@ public final class VolumeShaper {
     */
    private @NonNull VolumeShaper.State getStatePlayer(int id) {
        final VolumeShaper.State state;
        if (mPlayerProxy != null || mWeakPlayerProxy != null) {
            throw new IllegalStateException("getStatePlayer not permitted through proxy");
        } else if (mWeakPlayerBase != null) {
        if (mWeakPlayerBase != null) {
            PlayerBase player = mWeakPlayerBase.get();
            if (player == null) {
                throw new IllegalStateException("player deallocated");
@@ -510,6 +460,7 @@ public final class VolumeShaper {
        };

        /**
         * @hide
         * Constructs a volume shaper from an id.
         *
         * This is an opaque handle for controlling a {@code VolumeShaper} that has
@@ -522,7 +473,7 @@ public final class VolumeShaper {
         * @param id
         * @throws IllegalArgumentException if id is negative.
         */
        private Configuration(int id) {
        public Configuration(int id) {
            if (id < 0) {
                throw new IllegalArgumentException("negative id " + id);
            }
@@ -1039,6 +990,13 @@ public final class VolumeShaper {
         */
        private static final int FLAG_DEFER = 1 << 3;

        /**
         * Use the id specified in the configuration, creating
         * VolumeShaper as needed; the configuration should be
         * TYPE_SCALE.
         */
        private static final int FLAG_CREATE_IF_NEEDED = 1 << 4;

        private static final int FLAG_PUBLIC_ALL = FLAG_REVERSE | FLAG_TERMINATE;

        private final int mFlags;
@@ -1174,6 +1132,17 @@ public final class VolumeShaper {
                return this;
            }

            /**
             * Use the id specified in the configuration, creating
             * VolumeShaper as needed; the configuration should be
             * TYPE_SCALE.
             * @return the same Builder instance.
             */
            public @NonNull Builder createIfNeeded() {
                mFlags |= FLAG_CREATE_IF_NEEDED;
                return this;
            }

            /**
             * Sets the operation flag.  Do not call this directly but one of the
             * other builder methods.
+33 −36
Original line number Diff line number Diff line
@@ -51,14 +51,36 @@ public final class PlaybackActivityMonitor
    private final static boolean DEBUG = false;
    private final static int VOLUME_SHAPER_SYSTEM_DUCK_ID = 1;

    private ArrayList<PlayMonitorClient> mClients = new ArrayList<PlayMonitorClient>();
    private final VolumeShaper.Configuration DUCK_VSHAPE =
            new VolumeShaper.Configuration.Builder()
                .setId(VOLUME_SHAPER_SYSTEM_DUCK_ID)
                .setCurve(new float[] { 0.f, 1.f } /* times */,
                    new float[] { 1.f, 0.2f } /* volumes */)
                .setOptionFlags(VolumeShaper.Configuration.OPTION_FLAG_CLOCK_TIME)
                .setDurationMs(MediaFocusControl.getFocusRampTimeMs(
                    AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
                    new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION)
                            .build()))
                .build();
    private final VolumeShaper.Configuration DUCK_ID =
            new VolumeShaper.Configuration(VOLUME_SHAPER_SYSTEM_DUCK_ID);
    private final VolumeShaper.Operation PLAY_CREATE_IF_NEEDED =
            new VolumeShaper.Operation.Builder(VolumeShaper.Operation.PLAY)
                    .createIfNeeded()
                    .build();
    private final VolumeShaper.Operation TERMINATE =
            new VolumeShaper.Operation.Builder()
                    .terminate()
                    .build();

    private final ArrayList<PlayMonitorClient> mClients = new ArrayList<PlayMonitorClient>();
    // a public client is one that needs an anonymized version of the playback configurations, we
    // keep track of whether there is at least one to know when we need to create the list of
    // playback configurations that do not contain uid/pid/package name information.
    private boolean mHasPublicClients = false;

    private final Object mPlayerLock = new Object();
    private HashMap<Integer, AudioPlaybackConfiguration> mPlayers =
    private final HashMap<Integer, AudioPlaybackConfiguration> mPlayers =
            new HashMap<Integer, AudioPlaybackConfiguration>();

    PlaybackActivityMonitor() {
@@ -130,12 +152,10 @@ public final class PlaybackActivityMonitor
        synchronized(mPlayerLock) {
            final AudioPlaybackConfiguration apc = mPlayers.get(new Integer(piid));
            if (checkConfigurationCaller(piid, apc, binderUid)) {
                apc.getPlayerProxy().applyVolumeShaper(
                        DUCK_ID,
                        TERMINATE);
                mPlayers.remove(new Integer(piid));
                final VolumeShaper vs = mDuckVolumeShapers.get(new Integer(piid));
                if (vs != null) {
                    vs.release();
                    mDuckVolumeShapers.remove(new Integer(piid));
                }
            } else {
                Log.e(TAG, "Error releasing player " + piid);
            }
@@ -252,20 +272,6 @@ public final class PlaybackActivityMonitor
    private final ArrayList<Integer> mDuckedPlayers = new ArrayList<Integer>();
    private final ArrayList<Integer> mMutedPlayers = new ArrayList<Integer>();

    private final VolumeShaper.Configuration DUCK_VSHAPE =
            new VolumeShaper.Configuration.Builder()
                .setId(VOLUME_SHAPER_SYSTEM_DUCK_ID)
                .setCurve(new float[] { 0.f, 1.f } /* times */,
                    new float[] { 1.f, 0.2f } /* volumes */)
                .setDurationMs(MediaFocusControl.getFocusRampTimeMs(
                    AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
                    new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION)
                            .build()))
                .build();

    private final HashMap<Integer, VolumeShaper> mDuckVolumeShapers =
            new HashMap<Integer, VolumeShaper>();

    @Override
    public boolean duckPlayers(FocusRequester winner, FocusRequester loser) {
        if (DEBUG) {
@@ -302,17 +308,9 @@ public final class PlaybackActivityMonitor
                    } else {
                        try {
                            if (DEBUG) { Log.v(TAG, "ducking player " + piid); }
                            final VolumeShaper ducker;
                            if (mDuckVolumeShapers.containsKey(new Integer(piid))) {
                                ducker = mDuckVolumeShapers.get(new Integer(piid));
                            } else {
                                ducker = new VolumeShaper(
                            apc.getPlayerProxy().applyVolumeShaper(
                                    DUCK_VSHAPE,
                                        apc.getPlayerProxy(),
                                        true /* keepReference */);
                                mDuckVolumeShapers.put(new Integer(piid), ducker);
                            }
                            ducker.apply(VolumeShaper.Operation.PLAY); // duck
                                    PLAY_CREATE_IF_NEEDED);
                            mDuckedPlayers.add(piid);
                        } catch (Exception e) {
                            Log.e(TAG, "Error ducking player " + piid, e);
@@ -341,10 +339,9 @@ public final class PlaybackActivityMonitor
                    try {
                        if (DEBUG) { Log.v(TAG, "unducking player" + piid); }
                        mDuckedPlayers.remove(new Integer(piid));
                        if (mDuckVolumeShapers.containsKey(new Integer(piid))) {
                            final VolumeShaper ducker = mDuckVolumeShapers.get(new Integer(piid));
                            ducker.apply(VolumeShaper.Operation.REVERSE); // unduck
                        }
                        apc.getPlayerProxy().applyVolumeShaper(
                                DUCK_ID,
                                VolumeShaper.Operation.REVERSE);
                    } catch (Exception e) {
                        Log.e(TAG, "Error unducking player " + piid, e);
                    }