diff options
author | jiabin <jiabin@google.com> | 2020-08-07 17:27:48 -0700 |
---|---|---|
committer | Eric Laurent <elaurent@google.com> | 2020-12-21 17:01:20 +0100 |
commit | 9bb4798296e85cf308e322bbfab9f07f5ef882cf (patch) | |
tree | ab9d7dc91ed6d5fe45e48f8b49957b9664795b6b /media/java | |
parent | aea04ec44b3f53de079f17c2d32f994f01721c2f (diff) |
Introduce device(s) role for strategy.
Adding interface for set/remove/getDevicesRoleForStrategy. This will be
used for setting device(s) role, such as preferred, for strategy.
Set/remove/getPreferreDeviceForStrategy are reimplemented by calling
the new interfaces.
Test: atest AudioHostTest
Test: atest AudioServiceHostTest
Test: atest AudioServiceTest
Test: atest audiopolicy_tests
Bug: 160352965
Change-Id: I2ba02c6b50af80846a25010ead05c4ae364868de
Merged-In: I2ba02c6b50af80846a25010ead05c4ae364868de
Diffstat (limited to 'media/java')
-rwxr-xr-x | media/java/android/media/AudioManager.java | 173 | ||||
-rw-r--r-- | media/java/android/media/AudioSystem.java | 55 | ||||
-rwxr-xr-x | media/java/android/media/IAudioService.aidl | 14 | ||||
-rw-r--r-- | media/java/android/media/IStrategyPreferredDevicesDispatcher.aidl (renamed from media/java/android/media/IStrategyPreferredDeviceDispatcher.aidl) | 6 |
4 files changed, 191 insertions, 57 deletions
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 107d6565a29e..b33003737ccd 100755 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -75,6 +75,7 @@ import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -1598,11 +1599,25 @@ public class AudioManager { @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setPreferredDeviceForStrategy(@NonNull AudioProductStrategy strategy, @NonNull AudioDeviceAttributes device) { + return setPreferredDevicesForStrategy(strategy, Arrays.asList(device)); + } + + /** + * @hide + * Removes the preferred audio device(s) previously set with + * {@link #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDeviceAttributes)} or + * {@link #setPreferredDevicesForStrategy(AudioProductStrategy, List<AudioDeviceAttributes>)}. + * @param strategy the audio strategy whose routing will be affected + * @return true if the operation was successful, false otherwise (invalid strategy, or no + * device set for example) + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) + public boolean removePreferredDeviceForStrategy(@NonNull AudioProductStrategy strategy) { Objects.requireNonNull(strategy); - Objects.requireNonNull(device); try { final int status = - getService().setPreferredDeviceForStrategy(strategy.getId(), device); + getService().removePreferredDevicesForStrategy(strategy.getId()); return status == AudioSystem.SUCCESS; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -1611,19 +1626,52 @@ public class AudioManager { /** * @hide - * Removes the preferred audio device previously set with - * {@link #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDeviceAttributes)}. + * Return the preferred device for an audio strategy, previously set with + * {@link #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDeviceAttributes)} or + * {@link #setPreferredDevicesForStrategy(AudioProductStrategy, List<AudioDeviceAttributes>)} + * @param strategy the strategy to query + * @return the preferred device for that strategy, if multiple devices are set as preferred + * devices, the first one in the list will be returned. Null will be returned if none was + * ever set or if the strategy is invalid + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) + @Nullable + public AudioDeviceAttributes getPreferredDeviceForStrategy( + @NonNull AudioProductStrategy strategy) { + List<AudioDeviceAttributes> devices = getPreferredDevicesForStrategy(strategy); + return devices.isEmpty() ? null : devices.get(0); + } + + /** + * @hide + * Set the preferred devices for a given strategy, i.e. the audio routing to be used by + * this audio strategy. Note that the devices may not be available at the time the preferred + * devices is set, but it will be used once made available. + * <p>Use {@link #removePreferredDeviceForStrategy(AudioProductStrategy)} to cancel setting + * this preference for this strategy.</p> + * Note that the list of devices is not a list ranked by preference, but a list of one or more + * devices used simultaneously to output the same audio signal. * @param strategy the audio strategy whose routing will be affected - * @return true if the operation was successful, false otherwise (invalid strategy, or no - * device set for example) + * @param devices a non-empty list of the audio devices to route to when available + * @return true if the operation was successful, false otherwise */ @SystemApi @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) - public boolean removePreferredDeviceForStrategy(@NonNull AudioProductStrategy strategy) { + public boolean setPreferredDevicesForStrategy(@NonNull AudioProductStrategy strategy, + @NonNull List<AudioDeviceAttributes> devices) { Objects.requireNonNull(strategy); + Objects.requireNonNull(devices); + if (devices.isEmpty()) { + throw new IllegalArgumentException( + "Tried to set preferred devices for strategy with a empty list"); + } + for (AudioDeviceAttributes device : devices) { + Objects.requireNonNull(device); + } try { final int status = - getService().removePreferredDeviceForStrategy(strategy.getId()); + getService().setPreferredDevicesForStrategy(strategy.getId(), devices); return status == AudioSystem.SUCCESS; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -1632,19 +1680,21 @@ public class AudioManager { /** * @hide - * Return the preferred device for an audio strategy, previously set with + * Return the preferred devices for an audio strategy, previously set with * {@link #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDeviceAttributes)} + * {@link #setPreferredDevicesForStrategy(AudioProductStrategy, List<AudioDeviceAttributes>)} * @param strategy the strategy to query * @return the preferred device for that strategy, or null if none was ever set or if the * strategy is invalid */ @SystemApi @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) - public @Nullable AudioDeviceAttributes getPreferredDeviceForStrategy( + @NonNull + public List<AudioDeviceAttributes> getPreferredDevicesForStrategy( @NonNull AudioProductStrategy strategy) { Objects.requireNonNull(strategy); try { - return getService().getPreferredDeviceForStrategy(strategy.getId()); + return getService().getPreferredDevicesForStrategy(strategy.getId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1656,6 +1706,7 @@ public class AudioManager { * strategy. * <p>Note that this listener will only be invoked whenever * {@link #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDeviceAttributes)} or + * {@link #setPreferredDevicesForStrategy(AudioProductStrategy, List<AudioDeviceAttributes>)} * {@link #removePreferredDeviceForStrategy(AudioProductStrategy)} causes a change in * preferred device. It will not be invoked directly after registration with * {@link #addOnPreferredDeviceForStrategyChangedListener(Executor, OnPreferredDeviceForStrategyChangedListener)} @@ -1663,8 +1714,10 @@ public class AudioManager { * @see #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDeviceAttributes) * @see #removePreferredDeviceForStrategy(AudioProductStrategy) * @see #getPreferredDeviceForStrategy(AudioProductStrategy) + * @deprecated use #OnPreferredDevicesForStrategyChangedListener */ @SystemApi + @Deprecated public interface OnPreferredDeviceForStrategyChangedListener { /** * Called on the listener to indicate that the preferred audio device for the given @@ -1679,23 +1732,87 @@ public class AudioManager { /** * @hide + * Interface to be notified of changes in the preferred audio devices set for a given audio + * strategy. + * <p>Note that this listener will only be invoked whenever + * {@link #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDeviceAttributes)} or + * {@link #setPreferredDevicesForStrategy(AudioProductStrategy, List<AudioDeviceAttributes>)} + * {@link #removePreferredDeviceForStrategy(AudioProductStrategy)} causes a change in + * preferred device(s). It will not be invoked directly after registration with + * {@link #addOnPreferredDevicesForStrategyChangedListener( + * Executor, OnPreferredDevicesForStrategyChangedListener)} + * to indicate which strategies had preferred devices at the time of registration.</p> + * @see #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDeviceAttributes) + * @see #setPreferredDevicesForStrategy(AudioProductStrategy, List) + * @see #removePreferredDeviceForStrategy(AudioProductStrategy) + * @see #getPreferredDeviceForStrategy(AudioProductStrategy) + * @see #getPreferredDevicesForStrategy(AudioProductStrategy) + */ + @SystemApi + public interface OnPreferredDevicesForStrategyChangedListener { + /** + * Called on the listener to indicate that the preferred audio devices for the given + * strategy has changed. + * @param strategy the {@link AudioProductStrategy} whose preferred device changed + * @param devices a list of newly set preferred audio devices + */ + void onPreferredDevicesForStrategyChanged(@NonNull AudioProductStrategy strategy, + @NonNull List<AudioDeviceAttributes> devices); + } + + /** + * @hide * Adds a listener for being notified of changes to the strategy-preferred audio device. * @param executor * @param listener * @throws SecurityException if the caller doesn't hold the required permission + * @deprecated use {@link #addOnPreferredDevicesForStrategyChangedListener( + * Executor, AudioManager.OnPreferredDevicesForStrategyChangedListener)} instead */ @SystemApi @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) + @Deprecated public void addOnPreferredDeviceForStrategyChangedListener( @NonNull @CallbackExecutor Executor executor, @NonNull OnPreferredDeviceForStrategyChangedListener listener) throws SecurityException { + // No-op, the method is deprecated. + } + + /** + * @hide + * Removes a previously added listener of changes to the strategy-preferred audio device. + * @param listener + * @deprecated use {@link #removeOnPreferredDevicesForStrategyChangedListener( + * AudioManager.OnPreferredDevicesForStrategyChangedListener)} instead + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) + @Deprecated + public void removeOnPreferredDeviceForStrategyChangedListener( + @NonNull OnPreferredDeviceForStrategyChangedListener listener) { + // No-op, the method is deprecated. + } + + /** + * @hide + * Adds a listener for being notified of changes to the strategy-preferred audio device. + * @param executor + * @param listener + * @throws SecurityException if the caller doesn't hold the required permission + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) + public void addOnPreferredDevicesForStrategyChangedListener( + @NonNull @CallbackExecutor Executor executor, + @NonNull OnPreferredDevicesForStrategyChangedListener listener) + throws SecurityException { Objects.requireNonNull(executor); Objects.requireNonNull(listener); synchronized (mPrefDevListenerLock) { if (hasPrefDevListener(listener)) { throw new IllegalArgumentException( - "attempt to call addOnPreferredDeviceForStrategyChangedListener() " + "attempt to call addOnPreferredDevicesForStrategyChangedListener() " + "on a previously registered listener"); } // lazy initialization of the list of strategy-preferred device listener @@ -1707,10 +1824,10 @@ public class AudioManager { if (oldCbCount == 0 && mPrefDevListeners.size() > 0) { // register binder for callbacks if (mPrefDevDispatcherStub == null) { - mPrefDevDispatcherStub = new StrategyPreferredDeviceDispatcherStub(); + mPrefDevDispatcherStub = new StrategyPreferredDevicesDispatcherStub(); } try { - getService().registerStrategyPreferredDeviceDispatcher(mPrefDevDispatcherStub); + getService().registerStrategyPreferredDevicesDispatcher(mPrefDevDispatcherStub); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1725,8 +1842,8 @@ public class AudioManager { */ @SystemApi @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) - public void removeOnPreferredDeviceForStrategyChangedListener( - @NonNull OnPreferredDeviceForStrategyChangedListener listener) { + public void removeOnPreferredDevicesForStrategyChangedListener( + @NonNull OnPreferredDevicesForStrategyChangedListener listener) { Objects.requireNonNull(listener); synchronized (mPrefDevListenerLock) { if (!removePrefDevListener(listener)) { @@ -1737,7 +1854,7 @@ public class AudioManager { if (mPrefDevListeners.size() == 0) { // unregister binder for callbacks try { - getService().unregisterStrategyPreferredDeviceDispatcher( + getService().unregisterStrategyPreferredDevicesDispatcher( mPrefDevDispatcherStub); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -1759,23 +1876,23 @@ public class AudioManager { private @Nullable ArrayList<PrefDevListenerInfo> mPrefDevListeners; private static class PrefDevListenerInfo { - final @NonNull OnPreferredDeviceForStrategyChangedListener mListener; + final @NonNull OnPreferredDevicesForStrategyChangedListener mListener; final @NonNull Executor mExecutor; - PrefDevListenerInfo(OnPreferredDeviceForStrategyChangedListener listener, Executor exe) { + PrefDevListenerInfo(OnPreferredDevicesForStrategyChangedListener listener, Executor exe) { mListener = listener; mExecutor = exe; } } @GuardedBy("mPrefDevListenerLock") - private StrategyPreferredDeviceDispatcherStub mPrefDevDispatcherStub; + private StrategyPreferredDevicesDispatcherStub mPrefDevDispatcherStub; - private final class StrategyPreferredDeviceDispatcherStub - extends IStrategyPreferredDeviceDispatcher.Stub { + private final class StrategyPreferredDevicesDispatcherStub + extends IStrategyPreferredDevicesDispatcher.Stub { @Override - public void dispatchPrefDeviceChanged(int strategyId, - @Nullable AudioDeviceAttributes device) { + public void dispatchPrefDevicesChanged(int strategyId, + @NonNull List<AudioDeviceAttributes> devices) { // make a shallow copy of listeners so callback is not executed under lock final ArrayList<PrefDevListenerInfo> prefDevListeners; synchronized (mPrefDevListenerLock) { @@ -1790,7 +1907,7 @@ public class AudioManager { try { for (PrefDevListenerInfo info : prefDevListeners) { info.mExecutor.execute(() -> - info.mListener.onPreferredDeviceForStrategyChanged(strategy, device)); + info.mListener.onPreferredDevicesForStrategyChanged(strategy, devices)); } } finally { Binder.restoreCallingIdentity(ident); @@ -1800,7 +1917,7 @@ public class AudioManager { @GuardedBy("mPrefDevListenerLock") private @Nullable PrefDevListenerInfo getPrefDevListenerInfo( - OnPreferredDeviceForStrategyChangedListener listener) { + OnPreferredDevicesForStrategyChangedListener listener) { if (mPrefDevListeners == null) { return null; } @@ -1813,7 +1930,7 @@ public class AudioManager { } @GuardedBy("mPrefDevListenerLock") - private boolean hasPrefDevListener(OnPreferredDeviceForStrategyChangedListener listener) { + private boolean hasPrefDevListener(OnPreferredDevicesForStrategyChangedListener listener) { return getPrefDevListenerInfo(listener) != null; } @@ -1821,7 +1938,7 @@ public class AudioManager { /** * @return true if the listener was removed from the list */ - private boolean removePrefDevListener(OnPreferredDeviceForStrategyChangedListener listener) { + private boolean removePrefDevListener(OnPreferredDevicesForStrategyChangedListener listener) { final PrefDevListenerInfo infoToRemove = getPrefDevListenerInfo(listener); if (infoToRemove != null) { mPrefDevListeners.remove(infoToRemove); diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index f1eb53dda5b9..159048548ce8 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -33,6 +33,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; @@ -1371,6 +1372,11 @@ public class AudioSystem /** @hide */ public static final int FOR_VIBRATE_RINGING = 7; private static final int NUM_FORCE_USE = 8; + // Device role in audio policy + public static final int DEVICE_ROLE_NONE = 0; + public static final int DEVICE_ROLE_PREFERRED = 1; + public static final int DEVICE_ROLE_DISABLED = 2; + /** @hide */ public static String forceUseUsageToString(int usage) { switch (usage) { @@ -1691,47 +1697,58 @@ public class AudioSystem /** * @hide - * Sets the preferred device to use for a given audio strategy in the audio policy engine + * Set device as role for product strategy. * @param strategy the id of the strategy to configure - * @param device the device type and address to route to when available + * @param role the role of the devices + * @param devices the list of devices to be set as role for the given strategy * @return {@link #SUCCESS} if successfully set */ - public static int setPreferredDeviceForStrategy( - int strategy, @NonNull AudioDeviceAttributes device) { - return setPreferredDeviceForStrategy(strategy, - AudioDeviceInfo.convertDeviceTypeToInternalDevice(device.getType()), - device.getAddress()); + public static int setDevicesRoleForStrategy( + int strategy, int role, @NonNull List<AudioDeviceAttributes> devices) { + if (devices.isEmpty()) { + return BAD_VALUE; + } + int[] types = new int[devices.size()]; + String[] addresses = new String[devices.size()]; + for (int i = 0; i < devices.size(); ++i) { + types[i] = AudioDeviceInfo.convertDeviceTypeToInternalDevice(devices.get(i).getType()); + addresses[i] = devices.get(i).getAddress(); + } + return setDevicesRoleForStrategy(strategy, role, types, addresses); } + /** * @hide - * Set device routing per product strategy. + * Set device as role for product strategy. * @param strategy the id of the strategy to configure - * @param deviceType the native device type, NOT AudioDeviceInfo types - * @param deviceAddress the address of the device + * @param role the role of the devices + * @param types all device types + * @param addresses all device addresses * @return {@link #SUCCESS} if successfully set */ - private static native int setPreferredDeviceForStrategy( - int strategy, int deviceType, String deviceAddress); + private static native int setDevicesRoleForStrategy( + int strategy, int role, @NonNull int[] types, @NonNull String[] addresses); /** * @hide - * Remove preferred routing for the strategy + * Remove devices as role for the strategy * @param strategy the id of the strategy to configure + * @param role the role of the devices * @return {@link #SUCCESS} if successfully removed */ - public static native int removePreferredDeviceForStrategy(int strategy); + public static native int removeDevicesRoleForStrategy(int strategy, int role); /** * @hide - * Query previously set preferred device for a strategy + * Query previously set devices as role for a strategy * @param strategy the id of the strategy to query for - * @param device an array of size 1 that will contain the preferred device, or null if - * none was set + * @param role the role of the devices + * @param devices a list that will contain the devices of role * @return {@link #SUCCESS} if there is a preferred device and it was successfully retrieved * and written to the array */ - public static native int getPreferredDeviceForStrategy(int strategy, - AudioDeviceAttributes[] device); + public static native int getDevicesForRoleAndStrategy( + int strategy, int role, @NonNull List<AudioDeviceAttributes> devices); // Items shared with audio service diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index 78806eb9e547..bc2839ea214d 100755 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -29,7 +29,7 @@ import android.media.IAudioServerStateDispatcher; import android.media.IPlaybackConfigDispatcher; import android.media.IRecordingConfigDispatcher; import android.media.IRingtonePlayer; -import android.media.IStrategyPreferredDeviceDispatcher; +import android.media.IStrategyPreferredDevicesDispatcher; import android.media.IVolumeController; import android.media.IVolumeController; import android.media.PlayerBase; @@ -279,11 +279,11 @@ interface IAudioService { boolean isCallScreeningModeSupported(); - int setPreferredDeviceForStrategy(in int strategy, in AudioDeviceAttributes device); + int setPreferredDevicesForStrategy(in int strategy, in List<AudioDeviceAttributes> device); - int removePreferredDeviceForStrategy(in int strategy); + int removePreferredDevicesForStrategy(in int strategy); - AudioDeviceAttributes getPreferredDeviceForStrategy(in int strategy); + List<AudioDeviceAttributes> getPreferredDevicesForStrategy(in int strategy); List<AudioDeviceAttributes> getDevicesForAttributes(in AudioAttributes attributes); @@ -291,10 +291,10 @@ interface IAudioService { int getAllowedCapturePolicy(); - void registerStrategyPreferredDeviceDispatcher(IStrategyPreferredDeviceDispatcher dispatcher); + void registerStrategyPreferredDevicesDispatcher(IStrategyPreferredDevicesDispatcher dispatcher); - oneway void unregisterStrategyPreferredDeviceDispatcher( - IStrategyPreferredDeviceDispatcher dispatcher); + oneway void unregisterStrategyPreferredDevicesDispatcher( + IStrategyPreferredDevicesDispatcher dispatcher); oneway void setRttEnabled(in boolean rttEnabled); diff --git a/media/java/android/media/IStrategyPreferredDeviceDispatcher.aidl b/media/java/android/media/IStrategyPreferredDevicesDispatcher.aidl index b1f99e6b729e..db674c36a5c9 100644 --- a/media/java/android/media/IStrategyPreferredDeviceDispatcher.aidl +++ b/media/java/android/media/IStrategyPreferredDevicesDispatcher.aidl @@ -19,12 +19,12 @@ package android.media; import android.media.AudioDeviceAttributes; /** - * AIDL for AudioService to signal audio strategy-preferred device updates. + * AIDL for AudioService to signal audio strategy-preferred devices updates. * * {@hide} */ -oneway interface IStrategyPreferredDeviceDispatcher { +oneway interface IStrategyPreferredDevicesDispatcher { - void dispatchPrefDeviceChanged(int strategyId, in AudioDeviceAttributes device); + void dispatchPrefDevicesChanged(int strategyId, in List<AudioDeviceAttributes> devices); } |