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

Commit 0ffb6c5e authored by Paul Wang's avatar Paul Wang Committed by Android (Google) Code Review
Browse files

Merge "Add listener API to subscribe for routing change per AudioAttributes"

parents 3f2da60d ebadb69b
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -6607,6 +6607,7 @@ package android.media {
  public class AudioManager {
    method @Deprecated public int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes);
    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void addAssistantServicesUids(@NonNull int[]);
    method @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_AUDIO_ROUTING, "android.permission.QUERY_AUDIO_STATE"}) public void addOnDevicesForAttributesChangedListener(@NonNull android.media.AudioAttributes, @NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.OnDevicesForAttributesChangedListener);
    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void addOnNonDefaultDevicesForStrategyChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.OnNonDefaultDevicesForStrategyChangedListener) throws java.lang.SecurityException;
    method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void addOnPreferredDeviceForStrategyChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.OnPreferredDeviceForStrategyChangedListener) throws java.lang.SecurityException;
    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void addOnPreferredDevicesForCapturePresetChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.OnPreferredDevicesForCapturePresetChangedListener) throws java.lang.SecurityException;
@@ -6647,6 +6648,7 @@ package android.media {
    method public void registerVolumeGroupCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.VolumeGroupCallback);
    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void removeAssistantServicesUids(@NonNull int[]);
    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean removeDeviceAsNonDefaultForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy, @NonNull android.media.AudioDeviceAttributes);
    method @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_AUDIO_ROUTING, "android.permission.QUERY_AUDIO_STATE"}) public void removeOnDevicesForAttributesChangedListener(@NonNull android.media.AudioManager.OnDevicesForAttributesChangedListener);
    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void removeOnNonDefaultDevicesForStrategyChangedListener(@NonNull android.media.AudioManager.OnNonDefaultDevicesForStrategyChangedListener);
    method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void removeOnPreferredDeviceForStrategyChangedListener(@NonNull android.media.AudioManager.OnPreferredDeviceForStrategyChangedListener);
    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void removeOnPreferredDevicesForCapturePresetChangedListener(@NonNull android.media.AudioManager.OnPreferredDevicesForCapturePresetChangedListener);
@@ -6704,6 +6706,10 @@ package android.media {
    field public static final int EVENT_TIMEOUT = 2; // 0x2
  }
  public static interface AudioManager.OnDevicesForAttributesChangedListener {
    method public void onDevicesForAttributesChanged(@NonNull android.media.AudioAttributes, @NonNull java.util.List<android.media.AudioDeviceAttributes>);
  }
  public static interface AudioManager.OnNonDefaultDevicesForStrategyChangedListener {
    method public void onNonDefaultDevicesForStrategyChanged(@NonNull android.media.audiopolicy.AudioProductStrategy, @NonNull java.util.List<android.media.AudioDeviceAttributes>);
  }
+111 −0
Original line number Diff line number Diff line
@@ -5855,6 +5855,117 @@ public class AudioManager {
        }
    }

    // Each listener corresponds to a unique callback stub because each listener can subscribe to
    // different AudioAttributes.
    private final ConcurrentHashMap<OnDevicesForAttributesChangedListener,
            IDevicesForAttributesCallbackStub> mDevicesForAttributesListenerToStub =
                    new ConcurrentHashMap<>();

    private static final class IDevicesForAttributesCallbackStub
            extends IDevicesForAttributesCallback.Stub {
        ListenerInfo<OnDevicesForAttributesChangedListener> mInfo;

        IDevicesForAttributesCallbackStub(@NonNull OnDevicesForAttributesChangedListener listener,
                @NonNull Executor executor) {
            mInfo = new ListenerInfo<>(listener, executor);
        }

        public void register(boolean register, AudioAttributes attributes) {
            try {
                if (register) {
                    getService().addOnDevicesForAttributesChangedListener(attributes, this);
                } else {
                    getService().removeOnDevicesForAttributesChangedListener(this);
                }
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

        @Override
        public void onDevicesForAttributesChanged(AudioAttributes attributes, boolean forVolume,
                List<AudioDeviceAttributes> devices) {
            // forVolume is ignored. The case where it is `true` is not handled.
            mInfo.mExecutor.execute(() ->
                    mInfo.mListener.onDevicesForAttributesChanged(
                            attributes, devices));
        }
    }

    /**
     * @hide
     * Interface to be notified of when routing changes for the registered audio attributes.
     */
    @SystemApi
    public interface OnDevicesForAttributesChangedListener {
        /**
         * Called on the listener to indicate that the audio devices for the given audio
         * attributes have changed.
         * @param attributes the {@link AudioAttributes} whose routing changed
         * @param devices a list of newly routed audio devices
         */
        void onDevicesForAttributesChanged(@NonNull AudioAttributes attributes,
                @NonNull List<AudioDeviceAttributes> devices);
    }

    /**
     * @hide
     * Adds a listener for being notified of routing changes for the given {@link AudioAttributes}.
     * @param attributes the {@link AudioAttributes} to listen for routing changes
     * @param executor
     * @param listener
     */
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.MODIFY_AUDIO_ROUTING,
            android.Manifest.permission.QUERY_AUDIO_STATE
    })
    public void addOnDevicesForAttributesChangedListener(@NonNull AudioAttributes attributes,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull OnDevicesForAttributesChangedListener listener) {
        Objects.requireNonNull(attributes);
        Objects.requireNonNull(executor);
        Objects.requireNonNull(listener);

        synchronized (mDevicesForAttributesListenerToStub) {
            IDevicesForAttributesCallbackStub callbackStub =
                    mDevicesForAttributesListenerToStub.get(listener);

            if (callbackStub == null) {
                callbackStub = new IDevicesForAttributesCallbackStub(listener, executor);
                mDevicesForAttributesListenerToStub.put(listener, callbackStub);
            }

            callbackStub.register(true, attributes);
        }
    }

    /**
     * @hide
     * Removes a previously registered listener for being notified of routing changes for the given
     * {@link AudioAttributes}.
     * @param listener
     */
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.MODIFY_AUDIO_ROUTING,
            android.Manifest.permission.QUERY_AUDIO_STATE
    })
    public void removeOnDevicesForAttributesChangedListener(
            @NonNull OnDevicesForAttributesChangedListener listener) {
        Objects.requireNonNull(listener);

        synchronized (mDevicesForAttributesListenerToStub) {
            IDevicesForAttributesCallbackStub callbackStub =
                    mDevicesForAttributesListenerToStub.get(listener);
            if (callbackStub != null) {
                callbackStub.register(false, null /* attributes */);
            }

            mDevicesForAttributesListenerToStub.remove(listener);
        }
    }

    /**
     * Get the audio devices that would be used for the routing of the given audio attributes.
     * These are the devices anticipated to play sound from an {@link AudioTrack} created with
+7 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import android.media.IAudioServerStateDispatcher;
import android.media.ICapturePresetDevicesRoleDispatcher;
import android.media.ICommunicationDeviceDispatcher;
import android.media.IDeviceVolumeBehaviorDispatcher;
import android.media.IDevicesForAttributesCallback;
import android.media.IMuteAwaitConnectionCallback;
import android.media.IPlaybackConfigDispatcher;
import android.media.IPreferredMixerAttributesDispatcher;
@@ -356,6 +357,12 @@ interface IAudioService {

    List<AudioDeviceAttributes> getDevicesForAttributesUnprotected(in AudioAttributes attributes);

    void addOnDevicesForAttributesChangedListener(in AudioAttributes attributes,
            in IDevicesForAttributesCallback callback);

    oneway void removeOnDevicesForAttributesChangedListener(
            in IDevicesForAttributesCallback callback);

    int setAllowedCapturePolicy(in int capturePolicy);

    int getAllowedCapturePolicy();
+33 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.media;

import android.media.AudioAttributes;
import android.media.AudioDeviceAttributes;

/**
 * AIDL for AudioService to signal updates of audio devices routing for attributes.
 *
 * {@hide}
 */
oneway interface IDevicesForAttributesCallback {

    void onDevicesForAttributesChanged(in AudioAttributes attributes, boolean forVolume,
            in List<AudioDeviceAttributes> devices);

}
+20 −0
Original line number Diff line number Diff line
@@ -106,6 +106,7 @@ import android.media.IAudioService;
import android.media.ICapturePresetDevicesRoleDispatcher;
import android.media.ICommunicationDeviceDispatcher;
import android.media.IDeviceVolumeBehaviorDispatcher;
import android.media.IDevicesForAttributesCallback;
import android.media.IMuteAwaitConnectionCallback;
import android.media.IPlaybackConfigDispatcher;
import android.media.IPreferredMixerAttributesDispatcher;
@@ -3124,6 +3125,25 @@ public class AudioService extends IAudioService.Stub
        return mAudioSystem.getDevicesForAttributes(attributes, forVolume);
    }
    /**
     * @see AudioManager#addOnDevicesForAttributesChangedListener(
     *      AudioAttributes, Executor, OnDevicesForAttributesChangedListener)
     */
    public void addOnDevicesForAttributesChangedListener(AudioAttributes attributes,
            IDevicesForAttributesCallback callback) {
        mAudioSystem.addOnDevicesForAttributesChangedListener(
                attributes, false /* forVolume */, callback);
    }
    /**
     * @see AudioManager#removeOnDevicesForAttributesChangedListener(
     *      OnDevicesForAttributesChangedListener)
     */
    public void removeOnDevicesForAttributesChangedListener(
            IDevicesForAttributesCallback callback) {
        mAudioSystem.removeOnDevicesForAttributesChangedListener(callback);
    }
    // pre-condition: event.getKeyCode() is one of KeyEvent.KEYCODE_VOLUME_UP,
    //                                   KeyEvent.KEYCODE_VOLUME_DOWN, KeyEvent.KEYCODE_VOLUME_MUTE
    public void handleVolumeKey(@NonNull KeyEvent event, boolean isOnTv,
Loading