diff --git a/api/current.txt b/api/current.txt index 85428ab4046c1..732c500806237 100644 --- a/api/current.txt +++ b/api/current.txt @@ -19857,8 +19857,8 @@ package android.media { public class AudioRecord implements android.media.AudioRouting { ctor public AudioRecord(int, int, int, int, int) throws java.lang.IllegalArgumentException; + method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); method public deprecated void addOnRoutingChangedListener(android.media.AudioRecord.OnRoutingChangedListener, android.os.Handler); - method public void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); method public int getAudioFormat(); method public int getAudioSessionId(); method public int getAudioSource(); @@ -19883,8 +19883,8 @@ package android.media { method public int read(java.nio.ByteBuffer, int); method public int read(java.nio.ByteBuffer, int, int); method public void release(); + method public void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener); method public deprecated void removeOnRoutingChangedListener(android.media.AudioRecord.OnRoutingChangedListener); - method public void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener); method public int setNotificationMarkerPosition(int); method public int setPositionNotificationPeriod(int); method public boolean setPreferredDevice(android.media.AudioDeviceInfo); @@ -19918,8 +19918,9 @@ package android.media { method public abstract void onPeriodicNotification(android.media.AudioRecord); } - public static abstract interface AudioRecord.OnRoutingChangedListener { + public static abstract deprecated interface AudioRecord.OnRoutingChangedListener implements android.media.AudioRouting.OnRoutingChangedListener { method public abstract void onRoutingChanged(android.media.AudioRecord); + method public default void onRoutingChanged(android.media.AudioRouting); } public final class AudioRecordingConfiguration implements android.os.Parcelable { @@ -19934,10 +19935,10 @@ package android.media { } public abstract interface AudioRouting { - method public abstract void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); + method public abstract void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); method public abstract android.media.AudioDeviceInfo getPreferredDevice(); method public abstract android.media.AudioDeviceInfo getRoutedDevice(); - method public abstract void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener); + method public abstract void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener); method public abstract boolean setPreferredDevice(android.media.AudioDeviceInfo); } @@ -19957,8 +19958,8 @@ package android.media { ctor public AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException; ctor public AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException; ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException; + method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); method public deprecated void addOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener, android.os.Handler); - method public void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); method public int attachAuxEffect(int); method public void flush(); method public int getAudioFormat(); @@ -19990,8 +19991,8 @@ package android.media { method public void play() throws java.lang.IllegalStateException; method public void release(); method public int reloadStaticData(); + method public void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener); method public deprecated void removeOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener); - method public void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener); method public int setAuxEffectSendLevel(float); method public int setBufferSizeInFrames(int); method public int setLoopPoints(int, int, int); @@ -20045,8 +20046,9 @@ package android.media { method public abstract void onPeriodicNotification(android.media.AudioTrack); } - public static abstract deprecated interface AudioTrack.OnRoutingChangedListener { - method public abstract deprecated void onRoutingChanged(android.media.AudioTrack); + public static abstract deprecated interface AudioTrack.OnRoutingChangedListener implements android.media.AudioRouting.OnRoutingChangedListener { + method public abstract void onRoutingChanged(android.media.AudioTrack); + method public default void onRoutingChanged(android.media.AudioRouting); } public class CamcorderProfile { diff --git a/api/system-current.txt b/api/system-current.txt index d2125a3507ef0..56b2f581bb82a 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -21336,8 +21336,8 @@ package android.media { public class AudioRecord implements android.media.AudioRouting { ctor public AudioRecord(int, int, int, int, int) throws java.lang.IllegalArgumentException; ctor public AudioRecord(android.media.AudioAttributes, android.media.AudioFormat, int, int) throws java.lang.IllegalArgumentException; + method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); method public deprecated void addOnRoutingChangedListener(android.media.AudioRecord.OnRoutingChangedListener, android.os.Handler); - method public void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); method public int getAudioFormat(); method public int getAudioSessionId(); method public int getAudioSource(); @@ -21362,8 +21362,8 @@ package android.media { method public int read(java.nio.ByteBuffer, int); method public int read(java.nio.ByteBuffer, int, int); method public void release(); + method public void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener); method public deprecated void removeOnRoutingChangedListener(android.media.AudioRecord.OnRoutingChangedListener); - method public void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener); method public int setNotificationMarkerPosition(int); method public int setPositionNotificationPeriod(int); method public boolean setPreferredDevice(android.media.AudioDeviceInfo); @@ -21399,8 +21399,9 @@ package android.media { method public abstract void onPeriodicNotification(android.media.AudioRecord); } - public static abstract interface AudioRecord.OnRoutingChangedListener { + public static abstract deprecated interface AudioRecord.OnRoutingChangedListener implements android.media.AudioRouting.OnRoutingChangedListener { method public abstract void onRoutingChanged(android.media.AudioRecord); + method public default void onRoutingChanged(android.media.AudioRouting); } public final class AudioRecordingConfiguration implements android.os.Parcelable { @@ -21415,10 +21416,10 @@ package android.media { } public abstract interface AudioRouting { - method public abstract void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); + method public abstract void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); method public abstract android.media.AudioDeviceInfo getPreferredDevice(); method public abstract android.media.AudioDeviceInfo getRoutedDevice(); - method public abstract void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener); + method public abstract void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener); method public abstract boolean setPreferredDevice(android.media.AudioDeviceInfo); } @@ -21438,8 +21439,8 @@ package android.media { ctor public AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException; ctor public AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException; ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException; + method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); method public deprecated void addOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener, android.os.Handler); - method public void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); method public int attachAuxEffect(int); method public void flush(); method public int getAudioFormat(); @@ -21471,8 +21472,8 @@ package android.media { method public void play() throws java.lang.IllegalStateException; method public void release(); method public int reloadStaticData(); + method public void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener); method public deprecated void removeOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener); - method public void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener); method public int setAuxEffectSendLevel(float); method public int setBufferSizeInFrames(int); method public int setLoopPoints(int, int, int); @@ -21526,8 +21527,9 @@ package android.media { method public abstract void onPeriodicNotification(android.media.AudioTrack); } - public static abstract deprecated interface AudioTrack.OnRoutingChangedListener { - method public abstract deprecated void onRoutingChanged(android.media.AudioTrack); + public static abstract deprecated interface AudioTrack.OnRoutingChangedListener implements android.media.AudioRouting.OnRoutingChangedListener { + method public abstract void onRoutingChanged(android.media.AudioTrack); + method public default void onRoutingChanged(android.media.AudioRouting); } public class CamcorderProfile { diff --git a/api/test-current.txt b/api/test-current.txt index f6ea9c0b2f101..e837cd06aa352 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -19923,8 +19923,8 @@ package android.media { public class AudioRecord implements android.media.AudioRouting { ctor public AudioRecord(int, int, int, int, int) throws java.lang.IllegalArgumentException; + method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); method public deprecated void addOnRoutingChangedListener(android.media.AudioRecord.OnRoutingChangedListener, android.os.Handler); - method public void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); method public int getAudioFormat(); method public int getAudioSessionId(); method public int getAudioSource(); @@ -19949,8 +19949,8 @@ package android.media { method public int read(java.nio.ByteBuffer, int); method public int read(java.nio.ByteBuffer, int, int); method public void release(); + method public void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener); method public deprecated void removeOnRoutingChangedListener(android.media.AudioRecord.OnRoutingChangedListener); - method public void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener); method public int setNotificationMarkerPosition(int); method public int setPositionNotificationPeriod(int); method public boolean setPreferredDevice(android.media.AudioDeviceInfo); @@ -19984,8 +19984,9 @@ package android.media { method public abstract void onPeriodicNotification(android.media.AudioRecord); } - public static abstract interface AudioRecord.OnRoutingChangedListener { + public static abstract deprecated interface AudioRecord.OnRoutingChangedListener implements android.media.AudioRouting.OnRoutingChangedListener { method public abstract void onRoutingChanged(android.media.AudioRecord); + method public default void onRoutingChanged(android.media.AudioRouting); } public final class AudioRecordingConfiguration implements android.os.Parcelable { @@ -20000,10 +20001,10 @@ package android.media { } public abstract interface AudioRouting { - method public abstract void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); + method public abstract void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); method public abstract android.media.AudioDeviceInfo getPreferredDevice(); method public abstract android.media.AudioDeviceInfo getRoutedDevice(); - method public abstract void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener); + method public abstract void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener); method public abstract boolean setPreferredDevice(android.media.AudioDeviceInfo); } @@ -20023,8 +20024,8 @@ package android.media { ctor public AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException; ctor public AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException; ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException; + method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); method public deprecated void addOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener, android.os.Handler); - method public void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); method public int attachAuxEffect(int); method public void flush(); method public int getAudioFormat(); @@ -20056,8 +20057,8 @@ package android.media { method public void play() throws java.lang.IllegalStateException; method public void release(); method public int reloadStaticData(); + method public void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener); method public deprecated void removeOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener); - method public void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener); method public int setAuxEffectSendLevel(float); method public int setBufferSizeInFrames(int); method public int setLoopPoints(int, int, int); @@ -20111,8 +20112,9 @@ package android.media { method public abstract void onPeriodicNotification(android.media.AudioTrack); } - public static abstract deprecated interface AudioTrack.OnRoutingChangedListener { - method public abstract deprecated void onRoutingChanged(android.media.AudioTrack); + public static abstract deprecated interface AudioTrack.OnRoutingChangedListener implements android.media.AudioRouting.OnRoutingChangedListener { + method public abstract void onRoutingChanged(android.media.AudioTrack); + method public default void onRoutingChanged(android.media.AudioRouting); } public class CamcorderProfile { diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java index ca306cc7127cd..a5550ec7248bf 100644 --- a/media/java/android/media/AudioRecord.java +++ b/media/java/android/media/AudioRecord.java @@ -37,6 +37,8 @@ import android.os.ServiceManager; import android.util.ArrayMap; import android.util.Log; +import com.android.internal.annotations.GuardedBy; + /** * The AudioRecord class manages the audio resources for Java applications * to record audio from the audio input hardware of the platform. This is @@ -1320,6 +1322,7 @@ public class AudioRecord implements AudioRouting * Note: The query is only valid if the AudioRecord is currently recording. If it is not, * getRoutedDevice() will return null. */ + @Override public AudioDeviceInfo getRoutedDevice() { int deviceId = native_getRoutedDeviceId(); if (deviceId == 0) { @@ -1338,8 +1341,8 @@ public class AudioRecord implements AudioRouting /* * Call BEFORE adding a routing callback handler. */ - private void testEnableNativeRoutingCallbacks() { - if (mRoutingChangeListeners.size() == 0 && mNewRoutingChangeListeners.size() == 0) { + private void testEnableNativeRoutingCallbacksLocked() { + if (mRoutingChangeListeners.size() == 0) { native_enableDeviceCallback(); } } @@ -1347,24 +1350,23 @@ public class AudioRecord implements AudioRouting /* * Call AFTER removing a routing callback handler. */ - private void testDisableNativeRoutingCallbacks() { - if (mRoutingChangeListeners.size() == 0 && mNewRoutingChangeListeners.size() == 0) { + private void testDisableNativeRoutingCallbacksLocked() { + if (mRoutingChangeListeners.size() == 0) { native_disableDeviceCallback(); } } //-------------------------------------------------------------------------- - // >= "N" (Re)Routing Info + // (Re)Routing Info //-------------------- /** * The list of AudioRouting.OnRoutingChangedListener interfaces added (with - * {@link AudioRecord#addOnRoutingListener(AudioRouting.OnRoutingChangedListener, - * android.os.Handler)} - * by an app to receive (re)routing notifications. + * {@link AudioRecord#addOnRoutingChangedListener} by an app to receive + * (re)routing notifications. */ - private ArrayMap - mNewRoutingChangeListeners = - new ArrayMap(); + @GuardedBy("mRoutingChangeListeners") + private ArrayMap mRoutingChangeListeners = new ArrayMap<>(); /** * Adds an {@link AudioRouting.OnRoutingChangedListener} to receive notifications of @@ -1375,14 +1377,15 @@ public class AudioRecord implements AudioRouting * the callback. If null, the {@link Handler} associated with the main * {@link Looper} will be used. */ - public void addOnRoutingListener(AudioRouting.OnRoutingChangedListener listener, + @Override + public void addOnRoutingChangedListener(AudioRouting.OnRoutingChangedListener listener, android.os.Handler handler) { - if (listener != null && !mNewRoutingChangeListeners.containsKey(listener)) { - synchronized (mNewRoutingChangeListeners) { - testEnableNativeRoutingCallbacks(); - mNewRoutingChangeListeners.put( - listener, new NativeNewRoutingEventHandlerDelegate(this, listener, - handler != null ? handler : new Handler(mInitializationLooper))); + synchronized (mRoutingChangeListeners) { + if (listener != null && !mRoutingChangeListeners.containsKey(listener)) { + testEnableNativeRoutingCallbacksLocked(); + mRoutingChangeListeners.put( + listener, new NativeRoutingEventHandlerDelegate(this, listener, + handler != null ? handler : new Handler(mInitializationLooper))); } } } @@ -1393,39 +1396,42 @@ public class AudioRecord implements AudioRouting * @param listener The previously added {@link AudioRouting.OnRoutingChangedListener} interface * to remove. */ - public void removeOnRoutingListener(AudioRouting.OnRoutingChangedListener listener) { - synchronized (mNewRoutingChangeListeners) { - if (mNewRoutingChangeListeners.containsKey(listener)) { - mNewRoutingChangeListeners.remove(listener); - testDisableNativeRoutingCallbacks(); + @Override + public void removeOnRoutingChangedListener(AudioRouting.OnRoutingChangedListener listener) { + synchronized (mRoutingChangeListeners) { + if (mRoutingChangeListeners.containsKey(listener)) { + mRoutingChangeListeners.remove(listener); + testDisableNativeRoutingCallbacksLocked(); } } } //-------------------------------------------------------------------------- - // Marshmallow (Re)Routing Info + // (Re)Routing Info //-------------------- /** - * Defines the interface by which applications can receive notifications of routing - * changes for the associated {@link AudioRecord}. + * Defines the interface by which applications can receive notifications of + * routing changes for the associated {@link AudioRecord}. + * + * @deprecated users should switch to the general purpose + * {@link AudioRouting.OnRoutingChangedListener} class instead. */ - public interface OnRoutingChangedListener { + @Deprecated + public interface OnRoutingChangedListener extends AudioRouting.OnRoutingChangedListener { /** - * Called when the routing of an AudioRecord changes from either and explicit or - * policy rerouting. Use {@link #getRoutedDevice()} to retrieve the newly routed-from - * device. + * Called when the routing of an AudioRecord changes from either and + * explicit or policy rerouting. Use {@link #getRoutedDevice()} to + * retrieve the newly routed-from device. */ public void onRoutingChanged(AudioRecord audioRecord); - } - /** - * The list of AudioRecord.OnRoutingChangedListener interface added (with - * {@link AudioRecord#addOnRoutingChangedListener(OnRoutingChangedListener,android.os.Handler)} - * by an app to receive (re)routing notifications. - */ - private ArrayMap - mRoutingChangeListeners = - new ArrayMap(); + @Override + default public void onRoutingChanged(AudioRouting router) { + if (router instanceof AudioRecord) { + onRoutingChanged((AudioRecord) router); + } + } + } /** * Adds an {@link OnRoutingChangedListener} to receive notifications of routing changes @@ -1435,88 +1441,28 @@ public class AudioRecord implements AudioRouting * @param handler Specifies the {@link Handler} object for the thread on which to execute * the callback. If null, the {@link Handler} associated with the main * {@link Looper} will be used. + * @deprecated users should switch to the general purpose + * {@link AudioRouting.OnRoutingChangedListener} class instead. */ @Deprecated public void addOnRoutingChangedListener(OnRoutingChangedListener listener, android.os.Handler handler) { - if (listener != null && !mRoutingChangeListeners.containsKey(listener)) { - synchronized (mRoutingChangeListeners) { - testEnableNativeRoutingCallbacks(); - mRoutingChangeListeners.put( - listener, new NativeRoutingEventHandlerDelegate(this, listener, - handler != null ? handler : new Handler(mInitializationLooper))); - } - } + addOnRoutingChangedListener((AudioRouting.OnRoutingChangedListener) listener, handler); } /** * Removes an {@link OnRoutingChangedListener} which has been previously added * to receive rerouting notifications. * @param listener The previously added {@link OnRoutingChangedListener} interface to remove. + * @deprecated users should switch to the general purpose + * {@link AudioRouting.OnRoutingChangedListener} class instead. */ @Deprecated public void removeOnRoutingChangedListener(OnRoutingChangedListener listener) { - synchronized (mRoutingChangeListeners) { - if (mRoutingChangeListeners.containsKey(listener)) { - mRoutingChangeListeners.remove(listener); - testDisableNativeRoutingCallbacks(); - } - } + removeOnRoutingChangedListener((AudioRouting.OnRoutingChangedListener) listener); } /** - * >= "N" Routing - * Helper class to handle the forwarding of native events to the appropriate listener - * (potentially) handled in a different thread - */ - private class NativeNewRoutingEventHandlerDelegate { - private final Handler mHandler; - - NativeNewRoutingEventHandlerDelegate(final AudioRecord record, - final AudioRouting.OnRoutingChangedListener listener, - Handler handler) { - // find the looper for our new event handler - Looper looper; - if (handler != null) { - looper = handler.getLooper(); - } else { - // no given handler, use the looper the AudioRecord was created in - looper = mInitializationLooper; - } - - // construct the event handler with this looper - if (looper != null) { - // implement the event handler delegate - mHandler = new Handler(looper) { - @Override - public void handleMessage(Message msg) { - if (record == null) { - return; - } - switch(msg.what) { - case AudioSystem.NATIVE_EVENT_ROUTING_CHANGE: - if (listener != null) { - listener.onRoutingChanged(record); - } - break; - default: - loge("Unknown native event type: " + msg.what); - break; - } - } - }; - } else { - mHandler = null; - } - } - - Handler getHandler() { - return mHandler; - } - } - - /** - * Marshmallow Routing * Helper class to handle the forwarding of native events to the appropriate listener * (potentially) handled in a different thread */ @@ -1524,7 +1470,7 @@ public class AudioRecord implements AudioRouting private final Handler mHandler; NativeRoutingEventHandlerDelegate(final AudioRecord record, - final OnRoutingChangedListener listener, + final AudioRouting.OnRoutingChangedListener listener, Handler handler) { // find the looper for our new event handler Looper looper; @@ -1571,26 +1517,12 @@ public class AudioRecord implements AudioRouting */ private void broadcastRoutingChange() { AudioManager.resetAudioPortGeneration(); - // Marshmallow Routing - Collection values; synchronized (mRoutingChangeListeners) { - values = mRoutingChangeListeners.values(); - } - for(NativeRoutingEventHandlerDelegate delegate : values) { - Handler handler = delegate.getHandler(); - if (handler != null) { - handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE); - } - } - // >= "N" Routing - Collection newValues; - synchronized (mNewRoutingChangeListeners) { - newValues = mNewRoutingChangeListeners.values(); - } - for(NativeNewRoutingEventHandlerDelegate delegate : newValues) { - Handler handler = delegate.getHandler(); - if (handler != null) { - handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE); + for (NativeRoutingEventHandlerDelegate delegate : mRoutingChangeListeners.values()) { + Handler handler = delegate.getHandler(); + if (handler != null) { + handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE); + } } } } @@ -1623,6 +1555,7 @@ public class AudioRecord implements AudioRouting * @return true if successful, false if the specified {@link AudioDeviceInfo} is non-null and * does not correspond to a valid audio input device. */ + @Override public boolean setPreferredDevice(AudioDeviceInfo deviceInfo) { // Do some validation.... if (deviceInfo != null && !deviceInfo.isSource()) { @@ -1643,6 +1576,7 @@ public class AudioRecord implements AudioRouting * Returns the selected input specified by {@link #setPreferredDevice}. Note that this * is not guarenteed to correspond to the actual device being used for recording. */ + @Override public AudioDeviceInfo getPreferredDevice() { synchronized (this) { return mPreferredDevice; @@ -1683,7 +1617,6 @@ public class AudioRecord implements AudioRouting * (potentially) handled in a different thread */ private class NativeEventHandler extends Handler { - private final AudioRecord mAudioRecord; NativeEventHandler(AudioRecord recorder, Looper looper) { @@ -1714,8 +1647,7 @@ public class AudioRecord implements AudioRouting break; } } - }; - + } //--------------------------------------------------------- // Java methods called from the native side diff --git a/media/java/android/media/AudioRouting.java b/media/java/android/media/AudioRouting.java index 41f92d49e39f4..26fa631ac6ac7 100644 --- a/media/java/android/media/AudioRouting.java +++ b/media/java/android/media/AudioRouting.java @@ -57,7 +57,7 @@ public interface AudioRouting { * the callback. If null, the {@link Handler} associated with the main * {@link Looper} will be used. */ - public void addOnRoutingListener(OnRoutingChangedListener listener, + public void addOnRoutingChangedListener(OnRoutingChangedListener listener, Handler handler); /** @@ -66,7 +66,7 @@ public interface AudioRouting { * @param listener The previously added {@link AudioRouting.OnRoutingChangedListener} interface * to remove. */ - public void removeOnRoutingListener(OnRoutingChangedListener listener); + public void removeOnRoutingChangedListener(OnRoutingChangedListener listener); /** * Defines the interface by which applications can receive notifications of routing diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java index 621129d63f9c5..9d360db384c8c 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -40,6 +40,7 @@ import android.os.ServiceManager; import android.util.ArrayMap; import android.util.Log; +import com.android.internal.annotations.GuardedBy; import com.android.internal.app.IAppOpsService; /** @@ -1489,6 +1490,7 @@ public class AudioTrack implements AudioRouting * @deprecated Applications should use {@link #setVolume} instead, as it * more gracefully scales down to mono, and up to multi-channel content beyond stereo. */ + @Deprecated public int setStereoVolume(float leftGain, float rightGain) { if (isRestricted()) { return SUCCESS; @@ -2397,6 +2399,7 @@ public class AudioTrack implements AudioRouting * @return true if succesful, false if the specified {@link AudioDeviceInfo} is non-null and * does not correspond to a valid audio output device. */ + @Override public boolean setPreferredDevice(AudioDeviceInfo deviceInfo) { // Do some validation.... if (deviceInfo != null && !deviceInfo.isSink()) { @@ -2416,6 +2419,7 @@ public class AudioTrack implements AudioRouting * Returns the selected output specified by {@link #setPreferredDevice}. Note that this * is not guaranteed to correspond to the actual device being used for playback. */ + @Override public AudioDeviceInfo getPreferredDevice() { synchronized (this) { return mPreferredDevice; @@ -2427,6 +2431,7 @@ public class AudioTrack implements AudioRouting * Note: The query is only valid if the AudioTrack is currently playing. If it is not, * getRoutedDevice() will return null. */ + @Override public AudioDeviceInfo getRoutedDevice() { int deviceId = native_getRoutedDeviceId(); if (deviceId == 0) { @@ -2445,8 +2450,8 @@ public class AudioTrack implements AudioRouting /* * Call BEFORE adding a routing callback handler. */ - private void testEnableNativeRoutingCallbacks() { - if (mRoutingChangeListeners.size() == 0 && mNewRoutingChangeListeners.size() == 0) { + private void testEnableNativeRoutingCallbacksLocked() { + if (mRoutingChangeListeners.size() == 0) { native_enableDeviceCallback(); } } @@ -2454,24 +2459,23 @@ public class AudioTrack implements AudioRouting /* * Call AFTER removing a routing callback handler. */ - private void testDisableNativeRoutingCallbacks() { - if (mRoutingChangeListeners.size() == 0 && mNewRoutingChangeListeners.size() == 0) { + private void testDisableNativeRoutingCallbacksLocked() { + if (mRoutingChangeListeners.size() == 0) { native_disableDeviceCallback(); } } //-------------------------------------------------------------------------- - // >= "N" (Re)Routing Info + // (Re)Routing Info //-------------------- /** * The list of AudioRouting.OnRoutingChangedListener interfaces added (with - * {@link AudioTrack#addOnRoutingListener(AudioRouting.OnRoutingChangedListener, - * android.os.Handler)} - * by an app to receive (re)routing notifications. + * {@link AudioRecord#addOnRoutingChangedListener} by an app to receive + * (re)routing notifications. */ - private ArrayMap - mNewRoutingChangeListeners = - new ArrayMap(); + @GuardedBy("mRoutingChangeListeners") + private ArrayMap mRoutingChangeListeners = new ArrayMap<>(); /** * Adds an {@link AudioRouting.OnRoutingChangedListener} to receive notifications of routing @@ -2482,14 +2486,15 @@ public class AudioTrack implements AudioRouting * the callback. If null, the {@link Handler} associated with the main * {@link Looper} will be used. */ - public void addOnRoutingListener(AudioRouting.OnRoutingChangedListener listener, + @Override + public void addOnRoutingChangedListener(AudioRouting.OnRoutingChangedListener listener, Handler handler) { - if (listener != null && !mNewRoutingChangeListeners.containsKey(listener)) { - synchronized (mNewRoutingChangeListeners) { - testEnableNativeRoutingCallbacks(); - mNewRoutingChangeListeners.put( - listener, new NativeNewRoutingEventHandlerDelegate(this, listener, - handler != null ? handler : new Handler(mInitializationLooper))); + synchronized (mRoutingChangeListeners) { + if (listener != null && !mRoutingChangeListeners.containsKey(listener)) { + testEnableNativeRoutingCallbacksLocked(); + mRoutingChangeListeners.put( + listener, new NativeRoutingEventHandlerDelegate(this, listener, + handler != null ? handler : new Handler(mInitializationLooper))); } } } @@ -2500,39 +2505,42 @@ public class AudioTrack implements AudioRouting * @param listener The previously added {@link AudioRouting.OnRoutingChangedListener} interface * to remove. */ - public void removeOnRoutingListener(AudioRouting.OnRoutingChangedListener listener) { - if (mNewRoutingChangeListeners.containsKey(listener)) { - mNewRoutingChangeListeners.remove(listener); + @Override + public void removeOnRoutingChangedListener(AudioRouting.OnRoutingChangedListener listener) { + synchronized (mRoutingChangeListeners) { + if (mRoutingChangeListeners.containsKey(listener)) { + mRoutingChangeListeners.remove(listener); + } + testDisableNativeRoutingCallbacksLocked(); } - testDisableNativeRoutingCallbacks(); } //-------------------------------------------------------------------------- - // Marshmallow (Re)Routing Info + // (Re)Routing Info //-------------------- /** - * Defines the interface by which applications can receive notifications of routing - * changes for the associated {@link AudioTrack}. + * Defines the interface by which applications can receive notifications of + * routing changes for the associated {@link AudioTrack}. + * + * @deprecated users should switch to the general purpose + * {@link AudioRouting.OnRoutingChangedListener} class instead. */ @Deprecated - public interface OnRoutingChangedListener { + public interface OnRoutingChangedListener extends AudioRouting.OnRoutingChangedListener { /** - * Called when the routing of an AudioTrack changes from either and explicit or - * policy rerouting. Use {@link #getRoutedDevice()} to retrieve the newly routed-to - * device. + * Called when the routing of an AudioTrack changes from either and + * explicit or policy rerouting. Use {@link #getRoutedDevice()} to + * retrieve the newly routed-to device. */ - @Deprecated public void onRoutingChanged(AudioTrack audioTrack); - } - /** - * The list of AudioTrack.OnRoutingChangedListener interfaces added (with - * {@link AudioTrack#addOnRoutingChangedListener(OnRoutingChangedListener, android.os.Handler)} - * by an app to receive (re)routing notifications. - */ - private ArrayMap - mRoutingChangeListeners = - new ArrayMap(); + @Override + default public void onRoutingChanged(AudioRouting router) { + if (router instanceof AudioTrack) { + onRoutingChanged((AudioTrack) router); + } + } + } /** * Adds an {@link OnRoutingChangedListener} to receive notifications of routing changes @@ -2542,33 +2550,25 @@ public class AudioTrack implements AudioRouting * @param handler Specifies the {@link Handler} object for the thread on which to execute * the callback. If null, the {@link Handler} associated with the main * {@link Looper} will be used. + * @deprecated users should switch to the general purpose + * {@link AudioRouting.OnRoutingChangedListener} class instead. */ @Deprecated public void addOnRoutingChangedListener(OnRoutingChangedListener listener, android.os.Handler handler) { - if (listener != null && !mRoutingChangeListeners.containsKey(listener)) { - synchronized (mRoutingChangeListeners) { - testEnableNativeRoutingCallbacks(); - mRoutingChangeListeners.put( - listener, new NativeRoutingEventHandlerDelegate(this, listener, - handler != null ? handler : new Handler(mInitializationLooper))); - } - } + addOnRoutingChangedListener((AudioRouting.OnRoutingChangedListener) listener, handler); } /** * Removes an {@link OnRoutingChangedListener} which has been previously added * to receive rerouting notifications. * @param listener The previously added {@link OnRoutingChangedListener} interface to remove. + * @deprecated users should switch to the general purpose + * {@link AudioRouting.OnRoutingChangedListener} class instead. */ @Deprecated public void removeOnRoutingChangedListener(OnRoutingChangedListener listener) { - synchronized (mRoutingChangeListeners) { - if (mRoutingChangeListeners.containsKey(listener)) { - mRoutingChangeListeners.remove(listener); - } - testDisableNativeRoutingCallbacks(); - } + removeOnRoutingChangedListener((AudioRouting.OnRoutingChangedListener) listener); } /** @@ -2576,27 +2576,12 @@ public class AudioTrack implements AudioRouting */ private void broadcastRoutingChange() { AudioManager.resetAudioPortGeneration(); - - // Marshmallow Routing - Collection values; synchronized (mRoutingChangeListeners) { - values = mRoutingChangeListeners.values(); - } - for(NativeRoutingEventHandlerDelegate delegate : values) { - Handler handler = delegate.getHandler(); - if (handler != null) { - handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE); - } - } - // >= "N" Routing - Collection newValues; - synchronized (mNewRoutingChangeListeners) { - newValues = mNewRoutingChangeListeners.values(); - } - for(NativeNewRoutingEventHandlerDelegate delegate : newValues) { - Handler handler = delegate.getHandler(); - if (handler != null) { - handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE); + for (NativeRoutingEventHandlerDelegate delegate : mRoutingChangeListeners.values()) { + Handler handler = delegate.getHandler(); + if (handler != null) { + handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE); + } } } } @@ -2681,7 +2666,6 @@ public class AudioTrack implements AudioRouting } /** - * Marshmallow Routing API. * Helper class to handle the forwarding of native events to the appropriate listener * (potentially) handled in a different thread */ @@ -2689,57 +2673,6 @@ public class AudioTrack implements AudioRouting private final Handler mHandler; NativeRoutingEventHandlerDelegate(final AudioTrack track, - final OnRoutingChangedListener listener, - Handler handler) { - // find the looper for our new event handler - Looper looper; - if (handler != null) { - looper = handler.getLooper(); - } else { - // no given handler, use the looper the AudioTrack was created in - looper = mInitializationLooper; - } - - // construct the event handler with this looper - if (looper != null) { - // implement the event handler delegate - mHandler = new Handler(looper) { - @Override - public void handleMessage(Message msg) { - if (track == null) { - return; - } - switch(msg.what) { - case AudioSystem.NATIVE_EVENT_ROUTING_CHANGE: - if (listener != null) { - listener.onRoutingChanged(track); - } - break; - default: - loge("Unknown native event type: " + msg.what); - break; - } - } - }; - } else { - mHandler = null; - } - } - - Handler getHandler() { - return mHandler; - } - } - - /** - * Marshmallow Routing API. - * Helper class to handle the forwarding of native events to the appropriate listener - * (potentially) handled in a different thread - */ - private class NativeNewRoutingEventHandlerDelegate { - private final Handler mHandler; - - NativeNewRoutingEventHandlerDelegate(final AudioTrack track, final AudioRouting.OnRoutingChangedListener listener, Handler handler) { // find the looper for our new event handler