diff --git a/api/current.txt b/api/current.txt index 2a0e51ca9d9e7..07dba53884ddb 100644 --- a/api/current.txt +++ b/api/current.txt @@ -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 getValueClass(); } - public static interface AudioMetadata.Map extends android.media.AudioMetadata.ReadMap { + public interface AudioMetadataMap extends android.media.AudioMetadataReadMap { method @Nullable public T remove(@NonNull android.media.AudioMetadata.Key); method @Nullable public T set(@NonNull android.media.AudioMetadata.Key, @NonNull T); } - public static interface AudioMetadata.ReadMap { + public interface AudioMetadataReadMap { method public boolean containsKey(@NonNull android.media.AudioMetadata.Key); - method @NonNull public android.media.AudioMetadata.Map dup(); + method @NonNull public android.media.AudioMetadataMap dup(); method @Nullable public T get(@NonNull android.media.AudioMetadata.Key); - 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 { diff --git a/api/system-current.txt b/api/system-current.txt index 6d5ba34fdf9f0..38c265bd50b3e 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -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 getAudioProductStrategies(); method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List getAudioVolumeGroups(); method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public java.util.List 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(); diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java index 9950f05560d77..db2a1e8b6e7c8 100644 --- a/media/java/android/media/AudioDeviceInfo.java +++ b/media/java/android/media/AudioDeviceInfo.java @@ -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. } diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index fffdd683f22cc..ba8f7e60e268a 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -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; diff --git a/media/java/android/media/AudioMetadata.java b/media/java/android/media/AudioMetadata.java index 1a9517cafdde0..c91ff0d099cf2 100644 --- a/media/java/android/media/AudioMetadata.java +++ b/media/java/android/media/AudioMetadata.java @@ -79,96 +79,11 @@ public final class AudioMetadata { } /** - * A read only {@code Map} interface of {@link Key} value pairs. - * - *

Using a {@link Key} interface, the map looks up the corresponding value.

- */ - public interface ReadMap { - /** - * Returns true if the key exists in the map. - * - * @param key interface for requesting the value. - * @param type of value. - * @return true if key exists in the Map. - */ - boolean containsKey(@NonNull Key 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 type of value. - * @return returns the value of associated with key or null if it doesn't exist. - */ - @Nullable - T get(@NonNull Key key); - - /** - * Returns a {@code Set} of keys associated with the map. - * @hide - */ - @NonNull - Set> 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 type of value. - * @return the value of the key, null if it doesn't exist. - */ - @Nullable - T remove(@NonNull Key key); - - /** - * Sets a value for the key. - * - * @param key interface for storing the value. - * @param 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 set(@NonNull Key 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 boolean containsKey(@NonNull Key key) { Pair, 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; diff --git a/media/java/android/media/AudioMetadataMap.java b/media/java/android/media/AudioMetadataMap.java new file mode 100644 index 0000000000000..196193174754e --- /dev/null +++ b/media/java/android/media/AudioMetadataMap.java @@ -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 type of value. + * @return the value of the key, null if it doesn't exist. + */ + @Nullable + T remove(@NonNull AudioMetadata.Key key); + + /** + * Sets a value for the key. + * + * @param key interface for storing the value. + * @param 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 set(@NonNull AudioMetadata.Key key, @NonNull T value); +} diff --git a/media/java/android/media/AudioMetadataReadMap.java b/media/java/android/media/AudioMetadataReadMap.java new file mode 100644 index 0000000000000..e74242a292d47 --- /dev/null +++ b/media/java/android/media/AudioMetadataReadMap.java @@ -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}. + * + *

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.

+ * + * {@see AudioMetadataMap} + */ +public interface AudioMetadataReadMap { + /** + * Returns true if the key exists in the map. + * + * @param key interface for requesting the value. + * @param type of value. + * @return true if key exists in the Map. + */ + boolean containsKey(@NonNull AudioMetadata.Key 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 type of value. + * @return returns the value of associated with key or null if it doesn't exist. + */ + @Nullable + T get(@NonNull AudioMetadata.Key key); + + /** + * Returns a {@code Set} of keys associated with the map. + * @hide + */ + @NonNull + Set> keySet(); + + /** + * Returns the number of elements in the map. + */ + @IntRange(from = 0) + int size(); +} diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java index d17e42996726a..1d229b80cb2c4 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -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 mCodecFormatChangedListeners = + private final Utils.ListenerList 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;