Merge "Address Audio Java API feedback" into rvc-dev

This commit is contained in:
Jean-Michel Trivi
2020-03-27 14:58:53 +00:00
committed by Android (Google) Code Review
8 changed files with 189 additions and 185 deletions

View File

@@ -24357,7 +24357,7 @@ package android.media {
}
public final class AudioMetadata {
method @NonNull public static android.media.AudioMetadata.Map createMap();
method @NonNull public static android.media.AudioMetadataMap createMap();
}
public static class AudioMetadata.Format {
@@ -24375,16 +24375,16 @@ package android.media {
method @NonNull public Class<T> getValueClass();
}
public static interface AudioMetadata.Map extends android.media.AudioMetadata.ReadMap {
public interface AudioMetadataMap extends android.media.AudioMetadataReadMap {
method @Nullable public <T> T remove(@NonNull android.media.AudioMetadata.Key<T>);
method @Nullable public <T> T set(@NonNull android.media.AudioMetadata.Key<T>, @NonNull T);
}
public static interface AudioMetadata.ReadMap {
public interface AudioMetadataReadMap {
method public <T> boolean containsKey(@NonNull android.media.AudioMetadata.Key<T>);
method @NonNull public android.media.AudioMetadata.Map dup();
method @NonNull public android.media.AudioMetadataMap dup();
method @Nullable public <T> T get(@NonNull android.media.AudioMetadata.Key<T>);
method public int size();
method @IntRange(from=0) public int size();
}
public final class AudioPlaybackCaptureConfiguration {
@@ -24699,7 +24699,7 @@ package android.media {
}
public static interface AudioTrack.OnCodecFormatChangedListener {
method public void onCodecFormatChanged(@NonNull android.media.AudioTrack, @Nullable android.media.AudioMetadata.ReadMap);
method public void onCodecFormatChanged(@NonNull android.media.AudioTrack, @Nullable android.media.AudioMetadataReadMap);
}
public static interface AudioTrack.OnPlaybackPositionUpdateListener {

View File

@@ -4178,11 +4178,11 @@ package android.media {
method @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 public void clearAudioServerStateCallback();
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int dispatchAudioFocusChange(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
method @IntRange(from=0) public int getAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo);
method @IntRange(from=0) public long getAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo);
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List<android.media.audiopolicy.AudioProductStrategy> getAudioProductStrategies();
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List<android.media.audiopolicy.AudioVolumeGroup> getAudioVolumeGroups();
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public java.util.List<android.media.AudioDeviceAttributes> getDevicesForAttributes(@NonNull android.media.AudioAttributes);
method @IntRange(from=0) public int getMaxAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo);
method @IntRange(from=0) public long getMaxAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo);
method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMaxVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMinVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioDeviceAttributes getPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy);
@@ -4197,7 +4197,7 @@ package android.media {
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, @NonNull android.media.AudioAttributes, int, int) throws java.lang.IllegalArgumentException;
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.MODIFY_AUDIO_ROUTING}) public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, @NonNull android.media.AudioAttributes, int, int, android.media.audiopolicy.AudioPolicy) throws java.lang.IllegalArgumentException;
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int requestAudioFocus(@NonNull android.media.AudioFocusRequest, @Nullable android.media.audiopolicy.AudioPolicy);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo, @IntRange(from=0) int);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo, @IntRange(from=0) long);
method public void setAudioServerStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.AudioServerStateCallback);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setFocusRequestResult(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy, @NonNull android.media.AudioDeviceAttributes);
@@ -4272,17 +4272,11 @@ package android.media {
}
public static class AudioTrack.TunerConfiguration {
ctor @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public AudioTrack.TunerConfiguration(@IntRange(from=1) int, @IntRange(from=1) int);
method @IntRange(from=1) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getContentId();
method @IntRange(from=1) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getSyncId();
}
public static class AudioTrack.TunerConfiguration.Builder {
ctor public AudioTrack.TunerConfiguration.Builder();
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioTrack.TunerConfiguration build();
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioTrack.TunerConfiguration.Builder setContentId(@IntRange(from=1) int);
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioTrack.TunerConfiguration.Builder setSyncId(@IntRange(from=1) int);
}
public class HwAudioSource {
method public boolean isPlaying();
method public void start();

View File

@@ -432,7 +432,7 @@ public final class AudioDeviceInfo {
* @return An array of supported encapsulation modes for the device. This
* may be an empty array if no encapsulation modes are supported.
*/
public @NonNull int[] getEncapsulationModes() {
public @NonNull @AudioTrack.EncapsulationMode int[] getEncapsulationModes() {
// Implement a getter in r-dev or r-tv-dev as needed.
return new int[0]; // be careful of returning a copy of any internal data.
}
@@ -451,7 +451,7 @@ public final class AudioDeviceInfo {
* @return An array of supported encapsulation metadata types for the device. This
* may be an empty array if no metadata types are supported.
*/
public @NonNull int[] getEncapsulationMetadataTypes() {
public @NonNull @AudioTrack.EncapsulationMetadataType int[] getEncapsulationMetadataTypes() {
// Implement a getter in r-dev or r-tv-dev as needed.
return new int[0]; // be careful of returning a copy of any internal data.
}

View File

@@ -4769,7 +4769,7 @@ public class AudioManager {
* opened on that device.
*
* @param device an instance of {@link AudioDeviceInfo} returned from {@link getDevices()}.
* @param delayMs delay in milliseconds desired. This should be in range of {@code 0}
* @param delayMillis delay in milliseconds desired. This should be in range of {@code 0}
* to the value returned by {@link #getMaxAdditionalOutputDeviceDelay()}.
* @return true if successful, false if the device does not support output device delay
* or the delay is not in range of {@link #getMaxAdditionalOutputDeviceDelay()}.
@@ -4777,7 +4777,7 @@ public class AudioManager {
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public boolean setAdditionalOutputDeviceDelay(
@NonNull AudioDeviceInfo device, @IntRange(from = 0) int delayMs) {
@NonNull AudioDeviceInfo device, @IntRange(from = 0) long delayMillis) {
Objects.requireNonNull(device);
// Implement the setter in r-dev or r-tv-dev as needed.
return false;
@@ -4793,7 +4793,7 @@ public class AudioManager {
*/
@SystemApi
@IntRange(from = 0)
public int getAdditionalOutputDeviceDelay(@NonNull AudioDeviceInfo device) {
public long getAdditionalOutputDeviceDelay(@NonNull AudioDeviceInfo device) {
Objects.requireNonNull(device);
// Implement the getter in r-dev or r-tv-dev as needed.
return 0;
@@ -4811,7 +4811,7 @@ public class AudioManager {
*/
@SystemApi
@IntRange(from = 0)
public int getMaxAdditionalOutputDeviceDelay(@NonNull AudioDeviceInfo device) {
public long getMaxAdditionalOutputDeviceDelay(@NonNull AudioDeviceInfo device) {
Objects.requireNonNull(device);
// Implement the getter in r-dev or r-tv-dev as needed.
return 0;

View File

@@ -79,96 +79,11 @@ public final class AudioMetadata {
}
/**
* A read only {@code Map} interface of {@link Key} value pairs.
*
* <p>Using a {@link Key} interface, the map looks up the corresponding value.</p>
*/
public interface ReadMap {
/**
* Returns true if the key exists in the map.
*
* @param key interface for requesting the value.
* @param <T> type of value.
* @return true if key exists in the Map.
*/
<T> boolean containsKey(@NonNull Key<T> key);
/**
* Returns a copy of the map.
*
* This is intended for safe conversion between a {@link ReadMap}
* interface and a {@link Map} interface.
* Currently only simple objects are used for key values which
* means a shallow copy is sufficient.
*
* @return a Map copied from the existing map.
*/
@NonNull
Map dup(); // lint checker doesn't like clone().
/**
* Returns the value associated with the key.
*
* @param key interface for requesting the value.
* @param <T> type of value.
* @return returns the value of associated with key or null if it doesn't exist.
*/
@Nullable
<T> T get(@NonNull Key<T> key);
/**
* Returns a {@code Set} of keys associated with the map.
* @hide
*/
@NonNull
Set<Key<?>> keySet();
/**
* Returns the number of elements in the map.
*/
int size();
}
/**
* A writeable {@link Map} interface of {@link Key} value pairs.
* This interface is not guaranteed to be thread-safe
* unless the supplier for the {@code Map} states it as thread safe.
*/
// TODO: Create a wrapper like java.util.Collections.synchronizedMap?
public interface Map extends ReadMap {
/**
* Removes the value associated with the key.
* @param key interface for storing the value.
* @param <T> type of value.
* @return the value of the key, null if it doesn't exist.
*/
@Nullable
<T> T remove(@NonNull Key<T> key);
/**
* Sets a value for the key.
*
* @param key interface for storing the value.
* @param <T> type of value.
* @param value a non-null value of type T.
* @return the previous value associated with key or null if it doesn't exist.
*/
// See automatic Kotlin overloading for Java interoperability.
// https://kotlinlang.org/docs/reference/java-interop.html#operators
// See also Kotlin set for overloaded operator indexing.
// https://kotlinlang.org/docs/reference/operator-overloading.html#indexed
// Also the Kotlin mutable-list set.
// https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-list/set.html
@Nullable
<T> T set(@NonNull Key<T> key, @NonNull T value);
}
/**
* Creates a {@link Map} suitable for adding keys.
* @return an empty {@link Map} instance.
* Creates a {@link AudioMetadataMap} suitable for adding keys.
* @return an empty {@link AudioMetadataMap} instance.
*/
@NonNull
public static Map createMap() {
public static AudioMetadataMap createMap() {
return new BaseMap();
}
@@ -339,7 +254,7 @@ public final class AudioMetadata {
* It is possible to require the keys to be of a certain class
* before allowing a set or get operation.
*/
public static class BaseMap implements Map {
public static class BaseMap implements AudioMetadataMap {
@Override
public <T> boolean containsKey(@NonNull Key<T> key) {
Pair<Key<?>, Object> valuePair = mHashMap.get(pairFromKey(key));
@@ -348,7 +263,7 @@ public final class AudioMetadata {
@Override
@NonNull
public Map dup() {
public AudioMetadataMap dup() {
BaseMap map = new BaseMap();
map.mHashMap.putAll(this.mHashMap);
return map;

View File

@@ -0,0 +1,59 @@
/*
* Copyright (C) 2020 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;
/**
* AudioMetadataMap is a writeable {@code Map}-style
* interface of {@link AudioMetadata.Key} value pairs.
* This interface is not guaranteed to be thread-safe
* unless the underlying implementation for the {@code AudioMetadataMap}
* states it as thread safe.
*
* {@see AudioMetadataReadMap}
*/
// TODO: Create a wrapper like java.util.Collections.synchronizedMap?
public interface AudioMetadataMap extends AudioMetadataReadMap {
/**
* Removes the value associated with the key.
* @param key interface for storing the value.
* @param <T> type of value.
* @return the value of the key, null if it doesn't exist.
*/
@Nullable
<T> T remove(@NonNull AudioMetadata.Key<T> key);
/**
* Sets a value for the key.
*
* @param key interface for storing the value.
* @param <T> type of value.
* @param value a non-null value of type T.
* @return the previous value associated with key or null if it doesn't exist.
*/
// See automatic Kotlin overloading for Java interoperability.
// https://kotlinlang.org/docs/reference/java-interop.html#operators
// See also Kotlin set for overloaded operator indexing.
// https://kotlinlang.org/docs/reference/operator-overloading.html#indexed
// Also the Kotlin mutable-list set.
// https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-list/set.html
@Nullable
<T> T set(@NonNull AudioMetadata.Key<T> key, @NonNull T value);
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright (C) 2020 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.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import java.util.Set;
/**
* A read only {@code Map}-style interface of {@link AudioMetadata.Key} value pairs used
* for {@link AudioMetadata}.
*
* <p>Using a {@link AudioMetadata.Key} interface,
* this map looks up the corresponding value.
* Read-only maps are thread-safe for lookup, but the underlying object
* values may need their own thread protection if mutable.</p>
*
* {@see AudioMetadataMap}
*/
public interface AudioMetadataReadMap {
/**
* Returns true if the key exists in the map.
*
* @param key interface for requesting the value.
* @param <T> type of value.
* @return true if key exists in the Map.
*/
<T> boolean containsKey(@NonNull AudioMetadata.Key<T> key);
/**
* Returns a copy of the map.
*
* This is intended for safe conversion between a {@link AudioMetadataReadMap}
* interface and a {@link AudioMetadataMap} interface.
* Currently only simple objects are used for key values which
* means a shallow copy is sufficient.
*
* @return a Map copied from the existing map.
*/
@NonNull
AudioMetadataMap dup(); // lint checker doesn't like clone().
/**
* Returns the value associated with the key.
*
* @param key interface for requesting the value.
* @param <T> type of value.
* @return returns the value of associated with key or null if it doesn't exist.
*/
@Nullable
<T> T get(@NonNull AudioMetadata.Key<T> key);
/**
* Returns a {@code Set} of keys associated with the map.
* @hide
*/
@NonNull
Set<AudioMetadata.Key<?>> keySet();
/**
* Returns the number of elements in the map.
*/
@IntRange(from = 0)
int size();
}

View File

@@ -918,7 +918,29 @@ public class AudioTrack extends PlayerBase
private final int mContentId;
private final int mSyncId;
private TunerConfiguration(int contentId, int syncId) {
/**
* Constructs a TunerConfiguration instance for use in {@link AudioTrack.Builder}
*
* @param contentId selects the audio stream to use.
* The contentId may be obtained from
* {@link android.media.tv.tuner.filter.Filter#getId()}.
* This is always a positive number.
* @param syncId selects the clock to use for synchronization
* of audio with other streams such as video.
* The syncId may be obtained from
* {@link android.media.tv.tuner.Tuner#getAvSyncHwId()}.
* This is always a positive number.
*/
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public TunerConfiguration(
@IntRange(from = 1) int contentId, @IntRange(from = 1)int syncId) {
if (contentId < 1) {
throw new IllegalArgumentException(
"contentId " + contentId + " must be positive");
}
if (syncId < 1) {
throw new IllegalArgumentException("syncId " + syncId + " must be positive");
}
mContentId = contentId;
mSyncId = syncId;
}
@@ -938,73 +960,6 @@ public class AudioTrack extends PlayerBase
public @IntRange(from = 1) int getSyncId() {
return mSyncId; // The Builder ensures this is > 0.
}
/**
* Builder class for {@link AudioTrack.TunerConfiguration} objects.
*/
public static class Builder {
private int mContentId;
private int mSyncId;
/**
* Sets the contentId from the Tuner filter.
*
* @param contentId selects the audio stream to use.
* The contentId may be obtained from
* {@link android.media.tv.tuner.filter.Filter#getId()}.
* This is always a positive number.
*
* @return the same Builder instance.
*/
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public @NonNull Builder setContentId(@IntRange(from = 1) int contentId) {
if (contentId < 1) {
throw new IllegalArgumentException(
"contentId " + contentId + " must be positive");
}
mContentId = contentId;
return this;
}
/**
* Sets the syncId from the Tuner filter.
*
* @param syncId selects the clock to use for synchronization
* of audio with other streams such as video.
* The syncId may be obtained from
* {@link android.media.tv.tuner.Tuner#getAvSyncHwId()}.
* This is always a positive number.
*
* @return the same Builder instance.
*/
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public @NonNull Builder setSyncId(@IntRange(from = 1) int syncId) {
if (syncId < 1) {
throw new IllegalArgumentException("syncId " + syncId + " must be positive");
}
mSyncId = syncId;
return this;
}
/**
* Builds a {@link AudioTrack.TunerConfiguration} instance initialized with
* the parameters set on this {@code Builder}.
*
* @return a new successfully initialized {@link AudioTrack.TunerConfiguration}.
* @throws UnsupportedOperationException if the parameters set on the
* {@code Builder} are incompatible.
*/
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public @NonNull TunerConfiguration build() {
if (mContentId < 1 || mSyncId < 1) {
throw new UnsupportedOperationException(
"mContentId " + mContentId
+ " mSyncId " + mSyncId
+ " must be set");
}
return new TunerConfiguration(mContentId, mSyncId);
}
}
}
/**
@@ -3673,7 +3628,7 @@ public class AudioTrack extends PlayerBase
// OnCodecFormatChangedListener notifications uses an instance
// of ListenerList to manage its listeners.
private final Utils.ListenerList<AudioMetadata.ReadMap> mCodecFormatChangedListeners =
private final Utils.ListenerList<AudioMetadataReadMap> mCodecFormatChangedListeners =
new Utils.ListenerList();
/**
@@ -3684,13 +3639,13 @@ public class AudioTrack extends PlayerBase
* Called when the compressed codec format changes.
*
* @param audioTrack is the {@code AudioTrack} instance associated with the codec.
* @param info is a {@link AudioMetadata.ReadMap} of values which contains decoded format
* @param info is a {@link AudioMetadataReadMap} of values which contains decoded format
* changes reported by the codec. Not all hardware
* codecs indicate codec format changes. Acceptable keys are taken from
* {@code AudioMetadata.Format.KEY_*} range, with the associated value type.
*/
void onCodecFormatChanged(
@NonNull AudioTrack audioTrack, @Nullable AudioMetadata.ReadMap info);
@NonNull AudioTrack audioTrack, @Nullable AudioMetadataReadMap info);
}
/**
@@ -3708,7 +3663,7 @@ public class AudioTrack extends PlayerBase
mCodecFormatChangedListeners.add(
listener, /* key for removal */
executor,
(int eventCode, AudioMetadata.ReadMap readMap) -> {
(int eventCode, AudioMetadataReadMap readMap) -> {
// eventCode is unused by this implementation.
listener.onCodecFormatChanged(this, readMap);
}
@@ -4067,7 +4022,7 @@ public class AudioTrack extends PlayerBase
ByteBuffer buffer = (ByteBuffer) obj;
buffer.order(ByteOrder.nativeOrder());
buffer.rewind();
AudioMetadata.ReadMap audioMetaData = AudioMetadata.fromByteBuffer(buffer);
AudioMetadataReadMap audioMetaData = AudioMetadata.fromByteBuffer(buffer);
if (audioMetaData == null) {
Log.e(TAG, "Unable to get audio metadata from byte buffer");
return;