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

Commit 8ddef890 authored by Hongwei Wang's avatar Hongwei Wang
Browse files

Adds android.media.HwAudioSource class

The new HwAudioSource (inherits PlayerBase) serves as a player backed by
a hardware audio source device.

Sample usage

```
HwAudioSource player = new HwAudioSource.Builder()
        .setAudioDeviceInfo(deviceInfo)
        .setAudioAttributes(new AudioAttributes.Builder()
                .setUsage(AudioAttributes.USAGE_MEDIA)
                .build())
        .build();
player.start();
```

Bug: 112161027
Test: Launch FM Tuner application
Change-Id: Id1f49c88cbbdb2b9156137ed8920713aa29b2d1c
parent 32981ff4
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -3496,6 +3496,18 @@ package android.media {
    method public android.media.AudioRecord.Builder setSessionId(int) throws java.lang.IllegalArgumentException;
  }
  public class HwAudioSource {
    method public void start();
    method public void stop();
  }
  public static class HwAudioSource.Builder {
    ctor public HwAudioSource.Builder();
    method @NonNull public android.media.HwAudioSource build();
    method @NonNull public android.media.HwAudioSource.Builder setAudioAttributes(@NonNull android.media.AudioAttributes);
    method @NonNull public android.media.HwAudioSource.Builder setAudioDeviceInfo(@NonNull android.media.AudioDeviceInfo);
  }
  public final class MediaRecorder.AudioSource {
    field @RequiresPermission(android.Manifest.permission.CAPTURE_AUDIO_OUTPUT) public static final int ECHO_REFERENCE = 1997; // 0x7cd
    field @RequiresPermission(android.Manifest.permission.CAPTURE_AUDIO_HOTWORD) public static final int HOTWORD = 1999; // 0x7cf
+228 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;

import com.android.internal.util.Preconditions;

/**
 * The HwAudioSource represents the audio playback directly from a source audio device.
 * It currently supports {@link HwAudioSource#start()} and {@link HwAudioSource#stop()} only
 * corresponding to {@link AudioSystem#startAudioSource(AudioPortConfig, AudioAttributes)}
 * and {@link AudioSystem#stopAudioSource(int)}.
 *
 * @hide
 */
@SystemApi
public class HwAudioSource extends PlayerBase {
    private final AudioDeviceInfo mAudioDeviceInfo;
    private final AudioAttributes mAudioAttributes;

    private int mNativeHandle;

    /**
     * Class constructor for a hardware audio source based player.
     *
     * Use the {@link Builder} class to construct a {@link HwAudioSource} instance.
     *
     * @param device {@link AudioDeviceInfo} instance of the source audio device.
     * @param attributes {@link AudioAttributes} instance for this player.
     */
    private HwAudioSource(@NonNull AudioDeviceInfo device, @NonNull AudioAttributes attributes) {
        super(attributes, AudioPlaybackConfiguration.PLAYER_TYPE_HW_SOURCE);
        Preconditions.checkNotNull(device);
        Preconditions.checkNotNull(attributes);
        Preconditions.checkArgument(device.isSource(), "Requires a source device");
        mAudioDeviceInfo = device;
        mAudioAttributes = attributes;
        baseRegisterPlayer();
    }

    /**
     * TODO: sets the gain on {@link #mAudioDeviceInfo}.
     *
     * @param muting if true, the player is to be muted, and the volume values can be ignored
     * @param leftVolume the left volume to use if muting is false
     * @param rightVolume the right volume to use if muting is false
     */
    @Override
    void playerSetVolume(boolean muting, float leftVolume, float rightVolume) {
    }

    /**
     * TODO: applies {@link VolumeShaper} on {@link #mAudioDeviceInfo}.
     *
     * @param configuration a {@code VolumeShaper.Configuration} object
     *        created by {@link VolumeShaper.Configuration.Builder} or
     *        an created from a {@code VolumeShaper} id
     *        by the {@link VolumeShaper.Configuration} constructor.
     * @param operation a {@code VolumeShaper.Operation}.
     * @return
     */
    @Override
    int playerApplyVolumeShaper(
            @NonNull VolumeShaper.Configuration configuration,
            @NonNull VolumeShaper.Operation operation) {
        return 0;
    }

    /**
     * TODO: gets the {@link VolumeShaper} by a given id.
     *
     * @param id the {@code VolumeShaper} id returned from
     *           sending a fully specified {@code VolumeShaper.Configuration}
     *           through {@link #playerApplyVolumeShaper}
     * @return
     */
    @Override
    @Nullable
    VolumeShaper.State playerGetVolumeShaperState(int id) {
        return new VolumeShaper.State(1f, 1f);
    }

    /**
     * TODO: sets the level on {@link #mAudioDeviceInfo}.
     *
     * @param muting
     * @param level
     * @return
     */
    @Override
    int playerSetAuxEffectSendLevel(boolean muting, float level) {
        return AudioSystem.SUCCESS;
    }

    @Override
    void playerStart() {
        start();
    }

    @Override
    void playerPause() {
        // Pause is equivalent to stop for hardware audio source based players.
        stop();
    }

    @Override
    void playerStop() {
        stop();
    }

    /**
     * Starts the playback from {@link AudioDeviceInfo}.
     */
    public void start() {
        baseStart();
        mNativeHandle = AudioSystem.startAudioSource(
                mAudioDeviceInfo.getPort().activeConfig(),
                mAudioAttributes);
    }

    /**
     * Stops the playback from {@link AudioDeviceInfo}.
     */
    public void stop() {
        baseStop();
        if (mNativeHandle > 0) {
            AudioSystem.stopAudioSource(mNativeHandle);
            mNativeHandle = 0;
        }
    }

    /**
     * Builder class for {@link HwAudioSource} objects.
     * Use this class to configure and create a <code>HwAudioSource</code> instance.
     * <p>Here is an example where <code>Builder</code> is used to specify an audio
     * playback directly from a source device as media usage, to be used by a new
     * <code>HwAudioSource</code> instance:
     *
     * <pre class="prettyprint">
     * HwAudioSource player = new HwAudioSource.Builder()
     *              .setAudioAttributes(new AudioAttributes.Builder()
     *                       .setUsage(AudioAttributes.USAGE_MEDIA)
     *                       .build())
     *              .setAudioDeviceInfo(device)
     *              .build()
     * </pre>
     * <p>
     * If the audio attributes are not set with {@link #setAudioAttributes(AudioAttributes)},
     * attributes comprising {@link AudioAttributes#USAGE_MEDIA} will be used.
     */
    public static class Builder {
        private AudioAttributes mAudioAttributes;
        private AudioDeviceInfo mAudioDeviceInfo;

        /**
         * Constructs a new Builder with default values.
         */
        public Builder() {
        }

        /**
         * Sets the {@link AudioAttributes}.
         * @param attributes a non-null {@link AudioAttributes} instance that describes the audio
         *     data to be played.
         * @return the same Builder instance.
         */
        public @NonNull Builder setAudioAttributes(@NonNull AudioAttributes attributes) {
            Preconditions.checkNotNull(attributes);
            mAudioAttributes = attributes;
            return this;
        }

        /**
         * Sets the {@link AudioDeviceInfo}.
         * @param info a non-null {@link AudioDeviceInfo} instance that describes the audio
         *     data come from.
         * @return the same Builder instance.
         */
        public @NonNull Builder setAudioDeviceInfo(@NonNull AudioDeviceInfo info) {
            Preconditions.checkNotNull(info);
            Preconditions.checkArgument(info.isSource());
            mAudioDeviceInfo = info;
            return this;
        }

        /**
         * Builds an {@link HwAudioSource} instance initialized with all the parameters set
         * on this <code>Builder</code>.
         * @return a new successfully initialized {@link HwAudioSource} instance.
         */
        public @NonNull HwAudioSource build() {
            Preconditions.checkNotNull(mAudioDeviceInfo);
            if (mAudioAttributes == null) {
                mAudioAttributes = new AudioAttributes.Builder()
                        .setUsage(AudioAttributes.USAGE_MEDIA)
                        .build();
            }
            return new HwAudioSource(mAudioDeviceInfo, mAudioAttributes);
        }
    }

    /**
     * Eliminate {@link #deprecateStreamTypeForPlayback(int, String, String)} in API list.
     * TODO: remove this pseudo-override function
     * @hide
     */
    public static void deprecateStreamTypeForPlayback(int streamType, String className,
            String opName) throws IllegalArgumentException {
        // Do nothing.
    }
}