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

Commit 69d2fce6 authored by Jean-Michel Trivi's avatar Jean-Michel Trivi Committed by Automerger Merge Worker
Browse files

Merge "New APIs for immersive audio" into sc-v2-dev am: da474d3b am: 23597d34

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15391151

Change-Id: Idcdce446c13a88f510e1eba7800038d086047cab
parents 9eeb41f0 23597d34
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -20203,8 +20203,10 @@ 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
@@ -20218,6 +20220,8 @@ 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
@@ -20244,7 +20248,9 @@ 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);
  }
@@ -20469,6 +20475,7 @@ 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);
@@ -23865,6 +23872,17 @@ 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();
+6 −0
Original line number Diff line number Diff line
@@ -5410,6 +5410,12 @@ 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<android.media.AudioDeviceAttributes> getCompatibleAudioDevices();
    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void removeCompatibleAudioDevice(@NonNull android.media.AudioDeviceAttributes);
  }
}
package android.media.audiofx {
+98 −1
Original line number Diff line number Diff line
@@ -459,13 +459,26 @@ 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_NO_SYSTEM_CAPTURE | FLAG_CAPTURE_PRIVATE | FLAG_CONTENT_SPATIALIZED
            | FLAG_NEVER_SPATIALIZE;
    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 */
@@ -626,6 +639,49 @@ 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
@@ -669,6 +725,8 @@ 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<String> mTags = new HashSet<String>();
        private Bundle mBundle;
        private int mPrivacySensitive = PRIVACY_SENSITIVE_DEFAULT;
@@ -699,6 +757,8 @@ public final class AudioAttributes implements Parcelable {
            mFlags = aa.getAllFlags();
            mTags = (HashSet<String>) aa.mTags.clone();
            mMuteHapticChannels = aa.areHapticChannelsMuted();
            mIsContentSpatialized = aa.isContentSpatialized();
            mSpatializationBehavior = aa.getSpatializationBehavior();
        }

        /**
@@ -731,6 +791,12 @@ 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
@@ -917,6 +983,35 @@ 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.
@@ -1002,6 +1097,8 @@ 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;
+144 −1
Original line number Diff line number Diff line
@@ -817,7 +817,7 @@ public class AudioManager {
    }

    @UnsupportedAppUsage
    private static IAudioService getService()
    static IAudioService getService()
    {
        if (sService != null) {
            return sService;
@@ -2452,6 +2452,149 @@ 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<AudioDeviceAttributes> 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<AudioDeviceAttributes>(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
    /**
+22 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ 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;
@@ -34,6 +35,7 @@ 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;
@@ -396,4 +398,24 @@ 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<AudioDeviceAttributes> getSpatializerCompatibleAudioDevices();

    void addSpatializerCompatibleAudioDevice(in AudioDeviceAttributes ada);

    void removeSpatializerCompatibleAudioDevice(in AudioDeviceAttributes ada);
}
Loading