diff --git a/core/api/current.txt b/core/api/current.txt index 8f08658a76dc9..3ddb374c8a050 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -20181,10 +20181,8 @@ package android.media { method public int getAllowedCapturePolicy(); method public int getContentType(); method public int getFlags(); - method public int getSpatializationBehavior(); method public int getUsage(); method public int getVolumeControlStream(); - method public boolean isContentSpatialized(); method public void writeToParcel(android.os.Parcel, int); field public static final int ALLOW_CAPTURE_BY_ALL = 1; // 0x1 field public static final int ALLOW_CAPTURE_BY_NONE = 3; // 0x3 @@ -20198,8 +20196,6 @@ package android.media { field public static final int FLAG_AUDIBILITY_ENFORCED = 1; // 0x1 field public static final int FLAG_HW_AV_SYNC = 16; // 0x10 field @Deprecated public static final int FLAG_LOW_LATENCY = 256; // 0x100 - field public static final int SPATIALIZATION_BEHAVIOR_AUTO = 0; // 0x0 - field public static final int SPATIALIZATION_BEHAVIOR_NEVER = 1; // 0x1 field public static final int USAGE_ALARM = 4; // 0x4 field public static final int USAGE_ASSISTANCE_ACCESSIBILITY = 11; // 0xb field public static final int USAGE_ASSISTANCE_NAVIGATION_GUIDANCE = 12; // 0xc @@ -20226,9 +20222,7 @@ package android.media { method public android.media.AudioAttributes.Builder setContentType(int); method public android.media.AudioAttributes.Builder setFlags(int); method @NonNull public android.media.AudioAttributes.Builder setHapticChannelsMuted(boolean); - method @NonNull public android.media.AudioAttributes.Builder setIsContentSpatialized(boolean); method public android.media.AudioAttributes.Builder setLegacyStreamType(int); - method @NonNull public android.media.AudioAttributes.Builder setSpatializationBehavior(int); method public android.media.AudioAttributes.Builder setUsage(int); } @@ -20453,7 +20447,6 @@ package android.media { method public String getProperty(String); method public int getRingerMode(); method @Deprecated public int getRouting(int); - method @Nullable public android.media.Spatializer getSpatializer(); method public int getStreamMaxVolume(int); method public int getStreamMinVolume(int); method public int getStreamVolume(int); @@ -23850,17 +23843,6 @@ package android.media { method public void onLoadComplete(android.media.SoundPool, int, int); } - public class Spatializer { - method public void addOnSpatializerEnabledChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.Spatializer.OnSpatializerEnabledChangedListener); - method public boolean canBeSpatialized(@NonNull android.media.AudioAttributes, @NonNull android.media.AudioFormat); - method public boolean isEnabled(); - method public void removeOnSpatializerEnabledChangedListener(@NonNull android.media.Spatializer.OnSpatializerEnabledChangedListener); - } - - public static interface Spatializer.OnSpatializerEnabledChangedListener { - method public void onSpatializerEnabledChanged(boolean); - } - public final class SubtitleData { ctor public SubtitleData(int, long, long, @NonNull byte[]); method @NonNull public byte[] getData(); diff --git a/core/api/system-current.txt b/core/api/system-current.txt index e5008b493cebc..2846b36959581 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -5372,12 +5372,6 @@ package android.media { field public static final android.media.RouteDiscoveryPreference EMPTY; } - public class Spatializer { - method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void addCompatibleAudioDevice(@NonNull android.media.AudioDeviceAttributes); - method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public java.util.List getCompatibleAudioDevices(); - method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void removeCompatibleAudioDevice(@NonNull android.media.AudioDeviceAttributes); - } - } package android.media.audiofx { diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java index c22ab94637364..a031b4cfc9112 100644 --- a/media/java/android/media/AudioAttributes.java +++ b/media/java/android/media/AudioAttributes.java @@ -447,26 +447,13 @@ public final class AudioAttributes implements Parcelable { */ public static final int FLAG_CAPTURE_PRIVATE = 0x1 << 13; - /** - * @hide - * Flag indicating the audio content has been processed to provide a virtual multichannel - * audio experience - */ - public static final int FLAG_CONTENT_SPATIALIZED = 0x1 << 14; - - /** - * @hide - * Flag indicating the audio content is to never be spatialized - */ - public static final int FLAG_NEVER_SPATIALIZE = 0x1 << 15; // Note that even though FLAG_MUTE_HAPTIC is stored as a flag bit, it is not here since // it is known as a boolean value outside of AudioAttributes. private static final int FLAG_ALL = FLAG_AUDIBILITY_ENFORCED | FLAG_SECURE | FLAG_SCO | FLAG_BEACON | FLAG_HW_AV_SYNC | FLAG_HW_HOTWORD | FLAG_BYPASS_INTERRUPTION_POLICY | FLAG_BYPASS_MUTE | FLAG_LOW_LATENCY | FLAG_DEEP_BUFFER | FLAG_NO_MEDIA_PROJECTION - | FLAG_NO_SYSTEM_CAPTURE | FLAG_CAPTURE_PRIVATE | FLAG_CONTENT_SPATIALIZED - | FLAG_NEVER_SPATIALIZE; + | FLAG_NO_SYSTEM_CAPTURE | FLAG_CAPTURE_PRIVATE; private final static int FLAG_ALL_PUBLIC = FLAG_AUDIBILITY_ENFORCED | FLAG_HW_AV_SYNC | FLAG_LOW_LATENCY; /* mask of flags that can be set by SDK and System APIs through the Builder */ @@ -627,49 +614,6 @@ public final class AudioAttributes implements Parcelable { return (mFlags & FLAG_MUTE_HAPTIC) != 0; } - /** - * Return true if the audio content associated with these attributes has already been - * spatialized, that is it has already been processed to offer a binaural or transaural - * immersive audio experience. - * @return {@code true} if the content has been processed - */ - public boolean isContentSpatialized() { - return (mFlags & FLAG_CONTENT_SPATIALIZED) != 0; - } - - /** @hide */ - @IntDef(flag = false, value = { - SPATIALIZATION_BEHAVIOR_AUTO, - SPATIALIZATION_BEHAVIOR_NEVER, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface SpatializationBehavior {}; - - /** - * Constant indicating the audio content associated with these attributes will follow the - * default platform behavior with regards to which content will be spatialized or not. - * @see #getSpatializationBehavior() - * @see Spatializer - */ - public static final int SPATIALIZATION_BEHAVIOR_AUTO = 0; - - /** - * Constant indicating the audio content associated with these attributes should never - * be virtualized. - * @see #getSpatializationBehavior() - * @see Spatializer - */ - public static final int SPATIALIZATION_BEHAVIOR_NEVER = 1; - - /** - * Return the behavior affecting whether spatialization will be used. - * @return the spatialization behavior - */ - public @SpatializationBehavior int getSpatializationBehavior() { - return ((mFlags & FLAG_NEVER_SPATIALIZE) != 0) - ? SPATIALIZATION_BEHAVIOR_NEVER : SPATIALIZATION_BEHAVIOR_AUTO; - } - /** * Return the capture policy. * @return the capture policy set by {@link Builder#setAllowedCapturePolicy(int)} or @@ -713,8 +657,6 @@ public final class AudioAttributes implements Parcelable { private int mSource = MediaRecorder.AudioSource.AUDIO_SOURCE_INVALID; private int mFlags = 0x0; private boolean mMuteHapticChannels = true; - private boolean mIsContentSpatialized = false; - private int mSpatializationBehavior = SPATIALIZATION_BEHAVIOR_AUTO; private HashSet mTags = new HashSet(); private Bundle mBundle; private int mPrivacySensitive = PRIVACY_SENSITIVE_DEFAULT; @@ -745,8 +687,6 @@ public final class AudioAttributes implements Parcelable { mFlags = aa.getAllFlags(); mTags = (HashSet) aa.mTags.clone(); mMuteHapticChannels = aa.areHapticChannelsMuted(); - mIsContentSpatialized = aa.isContentSpatialized(); - mSpatializationBehavior = aa.getSpatializationBehavior(); } /** @@ -779,12 +719,6 @@ public final class AudioAttributes implements Parcelable { if (mMuteHapticChannels) { aa.mFlags |= FLAG_MUTE_HAPTIC; } - if (mIsContentSpatialized) { - aa.mFlags |= FLAG_CONTENT_SPATIALIZED; - } - if (mSpatializationBehavior == SPATIALIZATION_BEHAVIOR_NEVER) { - aa.mFlags |= FLAG_NEVER_SPATIALIZE; - } if (mPrivacySensitive == PRIVACY_SENSITIVE_DEFAULT) { // capturing for camcorder or communication is private by default to @@ -971,35 +905,6 @@ public final class AudioAttributes implements Parcelable { return this; } - /** - * Specifies whether the content has already been processed for spatialization. - * If it has, setting this to true will prevent issues such as double-processing. - * @param isSpatialized - * @return the same Builder instance - */ - public @NonNull Builder setIsContentSpatialized(boolean isSpatialized) { - mIsContentSpatialized = isSpatialized; - return this; - } - - /** - * Sets the behavior affecting whether spatialization will be used. - * @param sb the spatialization behavior - * @return the same Builder instance - * - */ - public @NonNull Builder setSpatializationBehavior(@SpatializationBehavior int sb) { - switch (sb) { - case SPATIALIZATION_BEHAVIOR_NEVER: - case SPATIALIZATION_BEHAVIOR_AUTO: - break; - default: - throw new IllegalArgumentException("Invalid spatialization behavior " + sb); - } - mSpatializationBehavior = sb; - return this; - } - /** * @hide * Replaces flags. @@ -1085,8 +990,6 @@ public final class AudioAttributes implements Parcelable { mContentType = attributes.mContentType; mFlags = attributes.getAllFlags(); mMuteHapticChannels = attributes.areHapticChannelsMuted(); - mIsContentSpatialized = attributes.isContentSpatialized(); - mSpatializationBehavior = attributes.getSpatializationBehavior(); mTags = attributes.mTags; mBundle = attributes.mBundle; mSource = attributes.mSource; diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index a31ad613bf48e..3b9c05bbe64f2 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -805,7 +805,7 @@ public class AudioManager { } @UnsupportedAppUsage - static IAudioService getService() + private static IAudioService getService() { if (sService != null) { return sService; @@ -2438,149 +2438,6 @@ public class AudioManager { return AudioSystem.getOffloadSupport(format, attributes); } - //==================================================================== - // Immersive audio - - /** - * @hide - * Returns the level of support for immersive audio from the {@link Spatializer} if - * available. - * @return the level of immersive audio support through spatialization - * @see Spatializer#getImmersiveAudioLevel() - */ - @Spatializer.ImmersiveAudioLevel int getSpatializerImmersiveAudioLevel() { - final IAudioService service = getService(); - try { - return service.getSpatializerImmersiveAudioLevel(); - } catch (RemoteException e) { - return Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE; - } - } - - /** - * Return a handle to the optional platform's {@link Spatializer} - * @return {@code null} if spatialization is not supported, the {@code Spatializer} instance - * otherwise. - */ - public @Nullable Spatializer getSpatializer() { - if (getSpatializerImmersiveAudioLevel() == Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE) { - return null; - } - return new Spatializer(this); - } - - /** - * @hide - * @see Spatializer#isEnabled() - * @return {@code true} if spatialization is enabled - */ - boolean isSpatializerEnabled() { - final IAudioService service = getService(); - try { - return service.isSpatializerEnabled(); - } catch (RemoteException e) { - Log.e(TAG, "Error querying isSpatializerEnabled, returning false", e); - return false; - } - } - - /** - * @hide - * @see Spatializer#setEnabled(boolean) - * Enable/disable the spatialization wherever supported. - * @param enabled {@code true} to enable - */ - void setSpatializerFeatureEnabled(boolean enabled) { - final IAudioService service = getService(); - try { - service.setSpatializerFeatureEnabled(enabled); - } catch (RemoteException e) { - Log.e(TAG, "Error calling setSpatializerFeatureEnabled", e); - } - } - - /** - * @hide - * @see Spatializer#setEnabledForDevice(boolean, AudioDeviceAttributes) - * @see Spatializer#setEnabled(boolean) - * @param enabled enable/disable for a specific device. - * @param device the device concerned with spatializer functionality. - */ - void setSpatializerEnabledForDevice(boolean enabled, - @NonNull AudioDeviceAttributes device) { - final IAudioService service = getService(); - try { - service.setSpatializerEnabledForDevice(enabled, device); - } catch (RemoteException e) { - Log.e(TAG, "Error calling setSpatializerEnabledForDevice", e); - } - } - - /** - * @hide - * @see Spatializer#canBeSpatialized(AudioAttributes, AudioFormat) - * @param attributes the {@code AudioAttributes} of the content as used for playback - * @param format the {@code AudioFormat} of the content as used for playback - * @return true if the device is capable of spatializing the combination of audio - * format and attributes. - */ - boolean canBeSpatialized( - @NonNull AudioAttributes attributes, @NonNull AudioFormat format) { - final IAudioService service = getService(); - try { - return service.canBeSpatialized(attributes, format); - } catch (RemoteException e) { - Log.e(TAG, "Error querying canBeSpatialized for attr:" + attributes - + " format:" + format + " returning false", e); - return false; - } - } - - /** - * @hide - * @see Spatializer#getCompatibleAudioDevices() - * @return a non-null list of the spatialization-compatible audio devices - */ - @NonNull List getSpatializerCompatibleAudioDevices() { - final IAudioService service = getService(); - try { - return service.getSpatializerCompatibleAudioDevices(); - } catch (RemoteException e) { - Log.e(TAG, "Error querying getSpatializerCompatibleAudioDevices(), " - + " returning empty list", e); - return new ArrayList(0); - } - } - - /** - * @hide - * @see Spatializer#addCompatibleAudioDevice(AudioDeviceAttributes) - * @param ada the audio device compatible with spatialization - */ - void addSpatializerCompatibleAudioDevice(@NonNull AudioDeviceAttributes ada) { - final IAudioService service = getService(); - try { - service.addSpatializerCompatibleAudioDevice(ada); - } catch (RemoteException e) { - Log.e(TAG, "Error calling addSpatializerCompatibleAudioDevice()", e); - } - } - - /** - * @hide - * @see Spatializer#removeCompatibleAudioDevice(AudioDeviceAttributes) - * @param ada the audio device incompatible with spatialization - */ - void removeSpatializerCompatibleAudioDevice(@NonNull AudioDeviceAttributes ada) { - final IAudioService service = getService(); - try { - service.removeSpatializerCompatibleAudioDevice(ada); - } catch (RemoteException e) { - Log.e(TAG, "Error calling removeSpatializerCompatibleAudioDevice()", e); - } - } - - //==================================================================== // Bluetooth SCO control /** diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index d2c70e4a66168..0b35ebed966ae 100755 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -20,7 +20,6 @@ import android.bluetooth.BluetoothDevice; import android.content.ComponentName; import android.media.AudioAttributes; import android.media.AudioDeviceAttributes; -import android.media.AudioFormat; import android.media.AudioFocusInfo; import android.media.AudioPlaybackConfiguration; import android.media.AudioRecordingConfiguration; @@ -35,7 +34,6 @@ import android.media.IPlaybackConfigDispatcher; import android.media.IRecordingConfigDispatcher; import android.media.IRingtonePlayer; import android.media.IStrategyPreferredDevicesDispatcher; -import android.media.ISpatializerCallback; import android.media.IVolumeController; import android.media.IVolumeController; import android.media.PlayerBase; @@ -394,24 +392,4 @@ interface IAudioService { void registerModeDispatcher(IAudioModeDispatcher dispatcher); oneway void unregisterModeDispatcher(IAudioModeDispatcher dispatcher); - - int getSpatializerImmersiveAudioLevel(); - - boolean isSpatializerEnabled(); - - void setSpatializerFeatureEnabled(boolean enabled); - - void setSpatializerEnabledForDevice(boolean enabled, in AudioDeviceAttributes device); - - boolean canBeSpatialized(in AudioAttributes aa, in AudioFormat af); - - void registerSpatializerCallback(in ISpatializerCallback callback); - - void unregisterSpatializerCallback(in ISpatializerCallback callback); - - List getSpatializerCompatibleAudioDevices(); - - void addSpatializerCompatibleAudioDevice(in AudioDeviceAttributes ada); - - void removeSpatializerCompatibleAudioDevice(in AudioDeviceAttributes ada); } diff --git a/media/java/android/media/ISpatializerCallback.aidl b/media/java/android/media/ISpatializerCallback.aidl deleted file mode 100644 index 50c5a6b8338f0..0000000000000 --- a/media/java/android/media/ISpatializerCallback.aidl +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2021 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; - -/** - * AIDL for the AudioService to signal Spatializer state changes. - * - * {@hide} - */ -oneway interface ISpatializerCallback { - - void dispatchSpatializerStateChanged(boolean enabled); - -} diff --git a/media/java/android/media/Spatializer.java b/media/java/android/media/Spatializer.java deleted file mode 100644 index a2267cc51c832..0000000000000 --- a/media/java/android/media/Spatializer.java +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright (C) 2021 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.annotation.CallbackExecutor; -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.RequiresPermission; -import android.annotation.SystemApi; -import android.media.permission.ClearCallingIdentityContext; -import android.media.permission.SafeCloseable; -import android.os.RemoteException; - -import com.android.internal.annotations.GuardedBy; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.Executor; - -/** - * Spatializer provides access to querying capabilities and behavior of sound spatialization - * on the device. - * Sound spatialization simulates sounds originating around the listener as if they were coming - * from virtual speakers placed around the listener.
- * Support for spatialization is optional, use {@link AudioManager#getSpatializer()} to obtain an - * instance of this class if the feature is supported. - * - */ -public class Spatializer { - - private final @NonNull AudioManager mAm; - - private final Object mStateListenerLock = new Object(); - - /** - * List of listeners for state listener and their associated Executor. - * List is lazy-initialized on first registration - */ - @GuardedBy("mStateListenerLock") - private @Nullable ArrayList mStateListeners; - - @GuardedBy("mStateListenerLock") - private SpatializerInfoDispatcherStub mInfoDispatcherStub; - - /** - * @hide - * Constructor with AudioManager acting as proxy to AudioService - * @param am a non-null AudioManager - */ - protected Spatializer(@NonNull AudioManager am) { - mAm = Objects.requireNonNull(am); - } - - /** - * Returns whether spatialization is enabled or not. - * A false value can originate from a number of sources, examples are the user electing to - * disable the feature, or the use of an audio device that is not compatible with multichannel - * audio spatialization (for instance playing audio over a monophonic speaker). - * @return {@code true} if spatialization is enabled - */ - public boolean isEnabled() { - return mAm.isSpatializerEnabled(); - } - - /** @hide */ - @IntDef(flag = false, value = { - SPATIALIZER_IMMERSIVE_LEVEL_NONE, - SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface ImmersiveAudioLevel {}; - - /** - * @hide - * Constant indicating there are no spatialization capabilities supported on this device. - * @see AudioManager#getImmersiveAudioLevel() - */ - public static final int SPATIALIZER_IMMERSIVE_LEVEL_NONE = 0; - - /** - * @hide - * Constant indicating the {@link Spatializer} on this device supports multichannel - * spatialization. - * @see AudioManager#getImmersiveAudioLevel() - */ - public static final int SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL = 1; - - - /** - * @hide - * @param enabled - * @param device - */ - //TODO make as API if needed for UX, remove otherwise - //@SystemApi(client = SystemApi.Client.PRIVILEGED_APPS) - //@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) - public void setEnabledForDevice(boolean enabled, - @NonNull AudioDeviceAttributes device) { - Objects.requireNonNull(device); - mAm.setSpatializerEnabledForDevice(enabled, device); - } - - /** - * @hide - * Enables / disables the spatializer effect - * @param enabled {@code true} for enabling the effect - */ - //TODO make as API if needed for UX, remove otherwise - //@SystemApi(client = SystemApi.Client.PRIVILEGED_APPS) - @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) - public void setEnabled(boolean enabled) { - mAm.setSpatializerFeatureEnabled(enabled); - } - - /** - * An interface to be notified of changes to the state of the spatializer. - */ - public interface OnSpatializerEnabledChangedListener { - /** - * Called when the enabled state of the Spatializer changes - * @param enabled {@code true} if the Spatializer effect is enabled on the device, - * {@code false} otherwise - */ - void onSpatializerEnabledChanged(boolean enabled); - } - - /** - * Returns whether audio of the given {@link AudioFormat}, played with the given - * {@link AudioAttributes} can be spatialized. - * Note that the result reflects the capabilities of the device and may change when - * audio accessories are connected/disconnected (e.g. wired headphones plugged in or not). - * The result is independent from whether spatialization processing is enabled or not. - * @param attributes the {@code AudioAttributes} of the content as used for playback - * @param format the {@code AudioFormat} of the content as used for playback - * @return true if the device is capable of spatializing the combination of audio format and - * attributes. - */ - public boolean canBeSpatialized( - @NonNull AudioAttributes attributes, @NonNull AudioFormat format) { - return mAm.canBeSpatialized( - Objects.requireNonNull(attributes), Objects.requireNonNull(format)); - } - - /** - * Adds a listener to be notified of changes to the enabled state of the - * {@code Spatializer}. - * @see #isEnabled() - * @param executor the {@code Executor} handling the callback - * @param listener the listener to receive enabled state updates - */ - public void addOnSpatializerEnabledChangedListener( - @NonNull @CallbackExecutor Executor executor, - @NonNull OnSpatializerEnabledChangedListener listener) { - Objects.requireNonNull(executor); - Objects.requireNonNull(listener); - synchronized (mStateListenerLock) { - if (hasSpatializerStateListener(listener)) { - throw new IllegalArgumentException( - "Called addOnSpatializerEnabledChangedListener() " - + "on a previously registered listener"); - } - // lazy initialization of the list of strategy-preferred device listener - if (mStateListeners == null) { - mStateListeners = new ArrayList<>(); - } - mStateListeners.add(new StateListenerInfo(listener, executor)); - if (mStateListeners.size() == 1) { - // register binder for callbacks - if (mInfoDispatcherStub == null) { - mInfoDispatcherStub = - new SpatializerInfoDispatcherStub(); - } - try { - mAm.getService().registerSpatializerCallback( - mInfoDispatcherStub); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - } - } - - /** - * Removes a previously added listener for changes to the enabled state of the - * {@code Spatializer}. - * @see #isEnabled() - * @param listener the listener to receive enabled state updates - */ - public void removeOnSpatializerEnabledChangedListener( - @NonNull OnSpatializerEnabledChangedListener listener) { - Objects.requireNonNull(listener); - synchronized (mStateListenerLock) { - if (!removeStateListener(listener)) { - throw new IllegalArgumentException( - "Called removeOnSpatializerEnabledChangedListener() " - + "on an unregistered listener"); - } - if (mStateListeners.size() == 0) { - // unregister binder for callbacks - try { - mAm.getService().unregisterSpatializerCallback(mInfoDispatcherStub); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } finally { - mInfoDispatcherStub = null; - mStateListeners = null; - } - } - } - } - - /** - * @hide - * Returns the list of playback devices that are compatible with the playback of multichannel - * audio through virtualization - * @return a list of devices. An empty list indicates virtualization is not supported. - */ - @SystemApi(client = SystemApi.Client.PRIVILEGED_APPS) - @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) - public @NonNull List getCompatibleAudioDevices() { - return mAm.getSpatializerCompatibleAudioDevices(); - } - - /** - * @hide - * Adds a playback device to the list of devices compatible with the playback of multichannel - * audio through spatialization. - * @see #getCompatibleAudioDevices() - * @param ada the audio device compatible with spatialization - */ - @SystemApi(client = SystemApi.Client.PRIVILEGED_APPS) - @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) - public void addCompatibleAudioDevice(@NonNull AudioDeviceAttributes ada) { - mAm.addSpatializerCompatibleAudioDevice(Objects.requireNonNull(ada)); - } - - /** - * @hide - * Remove a playback device from the list of devices compatible with the playback of - * multichannel audio through spatialization. - * @see #getCompatibleAudioDevices() - * @param ada the audio device incompatible with spatialization - */ - @SystemApi(client = SystemApi.Client.PRIVILEGED_APPS) - @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) - public void removeCompatibleAudioDevice(@NonNull AudioDeviceAttributes ada) { - mAm.removeSpatializerCompatibleAudioDevice(Objects.requireNonNull(ada)); - } - - private final class SpatializerInfoDispatcherStub - extends ISpatializerCallback.Stub { - @Override - public void dispatchSpatializerStateChanged(boolean enabled) { - // make a shallow copy of listeners so callback is not executed under lock - final ArrayList stateListeners; - synchronized (mStateListenerLock) { - if (mStateListeners == null || mStateListeners.size() == 0) { - return; - } - stateListeners = (ArrayList) mStateListeners.clone(); - } - try (SafeCloseable ignored = ClearCallingIdentityContext.create()) { - for (StateListenerInfo info : stateListeners) { - info.mExecutor.execute(() -> - info.mListener.onSpatializerEnabledChanged(enabled)); - } - } - } - } - - private static class StateListenerInfo { - final @NonNull OnSpatializerEnabledChangedListener mListener; - final @NonNull Executor mExecutor; - - StateListenerInfo(@NonNull OnSpatializerEnabledChangedListener listener, - @NonNull Executor exe) { - mListener = listener; - mExecutor = exe; - } - } - - @GuardedBy("mStateListenerLock") - private boolean hasSpatializerStateListener(OnSpatializerEnabledChangedListener listener) { - return getStateListenerInfo(listener) != null; - } - - @GuardedBy("mStateListenerLock") - private @Nullable StateListenerInfo getStateListenerInfo( - OnSpatializerEnabledChangedListener listener) { - if (mStateListeners == null) { - return null; - } - for (StateListenerInfo info : mStateListeners) { - if (info.mListener == listener) { - return info; - } - } - return null; - } - - @GuardedBy("mStateListenerLock") - /** - * @return true if the listener was removed from the list - */ - private boolean removeStateListener(OnSpatializerEnabledChangedListener listener) { - final StateListenerInfo infoToRemove = getStateListenerInfo(listener); - if (infoToRemove != null) { - mStateListeners.remove(infoToRemove); - return true; - } - return false; - } -} diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 346579784a6af..8d9479cc9895c 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -93,13 +93,11 @@ import android.media.ICommunicationDeviceDispatcher; import android.media.IPlaybackConfigDispatcher; import android.media.IRecordingConfigDispatcher; import android.media.IRingtonePlayer; -import android.media.ISpatializerCallback; import android.media.IStrategyPreferredDevicesDispatcher; import android.media.IVolumeController; import android.media.MediaMetrics; import android.media.MediaRecorder.AudioSource; import android.media.PlayerBase; -import android.media.Spatializer; import android.media.VolumePolicy; import android.media.audiofx.AudioEffect; import android.media.audiopolicy.AudioMix; @@ -8226,82 +8224,6 @@ public class AudioService extends IAudioService.Stub return true; } - //========================================================================================== - private final SpatializerHelper mSpatializerHelper = new SpatializerHelper(); - - /** @see AudioManager#getSpatializerImmersiveAudioLevel() */ - public int getSpatializerImmersiveAudioLevel() { - return Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE; - } - - /** @see Spatializer#isEnabled() */ - public boolean isSpatializerEnabled() { - return false; - } - - /** @see Spatializer#canBeSpatialized() */ - public boolean canBeSpatialized( - @NonNull AudioAttributes attributes, @NonNull AudioFormat format) { - Objects.requireNonNull(attributes); - Objects.requireNonNull(format); - return mSpatializerHelper.canBeSpatialized(attributes, format); - } - - /** @see Spatializer.SpatializerInfoDispatcherStub */ - public void registerSpatializerCallback( - @NonNull ISpatializerCallback dispatcher) { - Objects.requireNonNull(dispatcher); - mSpatializerHelper.registerStateCallback(dispatcher); - } - - /** @see Spatializer.SpatializerInfoDispatcherStub */ - public void unregisterSpatializerCallback( - @NonNull ISpatializerCallback dispatcher) { - Objects.requireNonNull(dispatcher); - mSpatializerHelper.unregisterStateCallback(dispatcher); - } - - /** @see Spatializer#getSpatializerCompatibleAudioDevices() */ - public @NonNull List getSpatializerCompatibleAudioDevices() { - enforceModifyAudioRoutingPermission(); - return mSpatializerHelper.getCompatibleAudioDevices(); - } - - /** @see Spatializer#addSpatializerCompatibleAudioDevice(AudioDeviceAttributes) */ - public void addSpatializerCompatibleAudioDevice(@NonNull AudioDeviceAttributes ada) { - enforceModifyAudioRoutingPermission(); - Objects.requireNonNull(ada); - mSpatializerHelper.addCompatibleAudioDevice(ada); - } - - /** @see Spatializer#removeSpatializerCompatibleAudioDevice(AudioDeviceAttributes) */ - public void removeSpatializerCompatibleAudioDevice(@NonNull AudioDeviceAttributes ada) { - enforceModifyAudioRoutingPermission(); - Objects.requireNonNull(ada); - mSpatializerHelper.removeCompatibleAudioDevice(ada); - } - - /** @see AudioManager#setSpatializerFeatureEnabled(boolean) */ - public void setSpatializerFeatureEnabled(boolean enabled) { - if (mContext.checkCallingOrSelfPermission( - android.Manifest.permission.MODIFY_DEFAULT_AUDIO_EFFECTS) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Missing MODIFY_DEFAULT_AUDIO_EFFECTS permission"); - } - mSpatializerHelper.setEnabled(enabled); - } - - /** @see Spatializer#setEnabledForDevice(boolean, AudioDeviceAttributes) - * @see Spatializer#setEnabled(boolean) - */ - public void setSpatializerEnabledForDevice(boolean enabled, - @NonNull AudioDeviceAttributes ada) { - enforceModifyAudioRoutingPermission(); - Objects.requireNonNull(ada); - mSpatializerHelper.setEnabledForDevice(enabled, ada); - } - - //========================================================================================== private boolean readCameraSoundForced() { return SystemProperties.getBoolean("audio.camerasound.force", false) || diff --git a/services/core/java/com/android/server/audio/SpatializerHelper.java b/services/core/java/com/android/server/audio/SpatializerHelper.java deleted file mode 100644 index 1b68f840e2986..0000000000000 --- a/services/core/java/com/android/server/audio/SpatializerHelper.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2021 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 com.android.server.audio; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.media.AudioAttributes; -import android.media.AudioDeviceAttributes; -import android.media.AudioFormat; -import android.media.ISpatializerCallback; -import android.os.RemoteCallbackList; -import android.os.RemoteException; -import android.util.Log; - -import java.util.ArrayList; -import java.util.List; - -/** - * A helper class to manage Spatializer related functionality - */ -public class SpatializerHelper { - - private static final String TAG = "AS.NotificationHelper"; - - //--------------------------------------------------------------- - // audio device compatibility / enabled - - private final ArrayList mCompatibleAudioDevices = new ArrayList<>(0); - private final ArrayList mEnabledAudioDevices = new ArrayList<>(0); - - /** - * @return a shallow copy of the list of compatible audio devices - */ - synchronized @NonNull List getCompatibleAudioDevices() { - return (List) mCompatibleAudioDevices.clone(); - } - - synchronized void addCompatibleAudioDevice(@NonNull AudioDeviceAttributes ada) { - if (!mCompatibleAudioDevices.contains(ada)) { - mCompatibleAudioDevices.add(ada); - } - // by default, adding a compatible device enables it - if (!mEnabledAudioDevices.contains(ada)) { - mEnabledAudioDevices.add(ada); - } - } - - synchronized void removeCompatibleAudioDevice(@NonNull AudioDeviceAttributes ada) { - mCompatibleAudioDevices.remove(ada); - mEnabledAudioDevices.remove(ada); - } - - synchronized void setEnabledForDevice(boolean enabled, @NonNull AudioDeviceAttributes ada) { - if (enabled) { - if (!mEnabledAudioDevices.contains(ada)) { - mEnabledAudioDevices.add(ada); - } - } else { - mEnabledAudioDevices.remove(ada); - } - } - - //------------------------------------------------------ - // enabled state - - // global state of feature - boolean mFeatureEnabled = false; - - synchronized void setEnabled(boolean enabled) { - final boolean oldState = mFeatureEnabled; - mFeatureEnabled = enabled; - if (oldState != enabled) { - dispatchState(); - } - } - - final RemoteCallbackList mStateCallbacks = - new RemoteCallbackList(); - - synchronized void registerStateCallback( - @NonNull ISpatializerCallback callback) { - mStateCallbacks.register(callback); - } - - synchronized void unregisterStateCallback( - @NonNull ISpatializerCallback callback) { - mStateCallbacks.unregister(callback); - } - - private synchronized void dispatchState() { - // TODO check enabled state based on available devices - // (current implementation takes state as-is and dispatches it to listeners - final int nbCallbacks = mStateCallbacks.beginBroadcast(); - for (int i = 0; i < nbCallbacks; i++) { - try { - mStateCallbacks.getBroadcastItem(i) - .dispatchSpatializerStateChanged(mFeatureEnabled); - } catch (RemoteException e) { - Log.e(TAG, "Error in dispatchSpatializerStateChanged", e); - } - } - mStateCallbacks.finishBroadcast(); - } - - //------------------------------------------------------ - // virtualization capabilities - synchronized boolean canBeSpatialized( - @NonNull AudioAttributes attributes, @NonNull AudioFormat format) { - // TODO hook up to spatializer effect for query - return false; - } -}