Loading api/current.txt +23 −8 Original line number Original line Diff line number Diff line Loading @@ -19402,9 +19402,10 @@ package android.media { method public abstract void onAudioFocusChange(int); method public abstract void onAudioFocusChange(int); } } public class AudioRecord { public class AudioRecord implements android.media.AudioRouting { ctor public AudioRecord(int, int, int, int, int) throws java.lang.IllegalArgumentException; ctor public AudioRecord(int, int, int, int, int) throws java.lang.IllegalArgumentException; method public void addOnRoutingChangedListener(android.media.AudioRecord.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 getAudioFormat(); method public int getAudioSessionId(); method public int getAudioSessionId(); method public int getAudioSource(); method public int getAudioSource(); Loading @@ -19428,7 +19429,8 @@ package android.media { method public int read(java.nio.ByteBuffer, int); method public int read(java.nio.ByteBuffer, int); method public int read(java.nio.ByteBuffer, int, int); method public int read(java.nio.ByteBuffer, int, int); method public void release(); method public void release(); method public void removeOnRoutingChangedListener(android.media.AudioRecord.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 setNotificationMarkerPosition(int); method public int setPositionNotificationPeriod(int); method public int setPositionNotificationPeriod(int); method public boolean setPreferredDevice(android.media.AudioDeviceInfo); method public boolean setPreferredDevice(android.media.AudioDeviceInfo); Loading Loading @@ -19466,17 +19468,29 @@ package android.media { method public abstract void onRoutingChanged(android.media.AudioRecord); method public abstract void onRoutingChanged(android.media.AudioRecord); } } public abstract interface AudioRouting { method public abstract void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); method public abstract android.media.AudioDeviceInfo getPreferredDevice(); method public abstract void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener); method public abstract boolean setPreferredDevice(android.media.AudioDeviceInfo); } public static abstract interface AudioRouting.OnRoutingChangedListener { method public abstract void onRoutingChanged(android.media.AudioRouting); } public final class AudioTimestamp { public final class AudioTimestamp { ctor public AudioTimestamp(); ctor public AudioTimestamp(); field public long framePosition; field public long framePosition; field public long nanoTime; field public long nanoTime; } } public class AudioTrack { public class AudioTrack implements android.media.AudioRouting { ctor public AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException; 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(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; ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException; method public void addOnRoutingChangedListener(android.media.AudioTrack.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 int attachAuxEffect(int); method public void flush(); method public void flush(); method public int getAudioFormat(); method public int getAudioFormat(); Loading Loading @@ -19506,7 +19520,8 @@ package android.media { method public void play() throws java.lang.IllegalStateException; method public void play() throws java.lang.IllegalStateException; method public void release(); method public void release(); method public int reloadStaticData(); method public int reloadStaticData(); method public void removeOnRoutingChangedListener(android.media.AudioTrack.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 setAuxEffectSendLevel(float); method public int setLoopPoints(int, int, int); method public int setLoopPoints(int, int, int); method public int setNotificationMarkerPosition(int); method public int setNotificationMarkerPosition(int); Loading Loading @@ -19559,8 +19574,8 @@ package android.media { method public abstract void onPeriodicNotification(android.media.AudioTrack); method public abstract void onPeriodicNotification(android.media.AudioTrack); } } public static abstract interface AudioTrack.OnRoutingChangedListener { public static abstract deprecated interface AudioTrack.OnRoutingChangedListener { method public abstract void onRoutingChanged(android.media.AudioTrack); method public abstract deprecated void onRoutingChanged(android.media.AudioTrack); } } public class CamcorderProfile { public class CamcorderProfile { api/system-current.txt +23 −8 Original line number Original line Diff line number Diff line Loading @@ -20706,10 +20706,11 @@ package android.media { method public abstract void onAudioFocusChange(int); method public abstract void onAudioFocusChange(int); } } public class AudioRecord { public class AudioRecord implements android.media.AudioRouting { ctor public AudioRecord(int, int, int, int, int) throws java.lang.IllegalArgumentException; 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; ctor public AudioRecord(android.media.AudioAttributes, android.media.AudioFormat, int, int) throws java.lang.IllegalArgumentException; method public void addOnRoutingChangedListener(android.media.AudioRecord.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 getAudioFormat(); method public int getAudioSessionId(); method public int getAudioSessionId(); method public int getAudioSource(); method public int getAudioSource(); Loading @@ -20733,7 +20734,8 @@ package android.media { method public int read(java.nio.ByteBuffer, int); method public int read(java.nio.ByteBuffer, int); method public int read(java.nio.ByteBuffer, int, int); method public int read(java.nio.ByteBuffer, int, int); method public void release(); method public void release(); method public void removeOnRoutingChangedListener(android.media.AudioRecord.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 setNotificationMarkerPosition(int); method public int setPositionNotificationPeriod(int); method public int setPositionNotificationPeriod(int); method public boolean setPreferredDevice(android.media.AudioDeviceInfo); method public boolean setPreferredDevice(android.media.AudioDeviceInfo); Loading Loading @@ -20773,17 +20775,29 @@ package android.media { method public abstract void onRoutingChanged(android.media.AudioRecord); method public abstract void onRoutingChanged(android.media.AudioRecord); } } public abstract interface AudioRouting { method public abstract void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); method public abstract android.media.AudioDeviceInfo getPreferredDevice(); method public abstract void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener); method public abstract boolean setPreferredDevice(android.media.AudioDeviceInfo); } public static abstract interface AudioRouting.OnRoutingChangedListener { method public abstract void onRoutingChanged(android.media.AudioRouting); } public final class AudioTimestamp { public final class AudioTimestamp { ctor public AudioTimestamp(); ctor public AudioTimestamp(); field public long framePosition; field public long framePosition; field public long nanoTime; field public long nanoTime; } } public class AudioTrack { public class AudioTrack implements android.media.AudioRouting { ctor public AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException; 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(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; ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException; method public void addOnRoutingChangedListener(android.media.AudioTrack.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 int attachAuxEffect(int); method public void flush(); method public void flush(); method public int getAudioFormat(); method public int getAudioFormat(); Loading Loading @@ -20813,7 +20827,8 @@ package android.media { method public void play() throws java.lang.IllegalStateException; method public void play() throws java.lang.IllegalStateException; method public void release(); method public void release(); method public int reloadStaticData(); method public int reloadStaticData(); method public void removeOnRoutingChangedListener(android.media.AudioTrack.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 setAuxEffectSendLevel(float); method public int setLoopPoints(int, int, int); method public int setLoopPoints(int, int, int); method public int setNotificationMarkerPosition(int); method public int setNotificationMarkerPosition(int); Loading Loading @@ -20866,8 +20881,8 @@ package android.media { method public abstract void onPeriodicNotification(android.media.AudioTrack); method public abstract void onPeriodicNotification(android.media.AudioTrack); } } public static abstract interface AudioTrack.OnRoutingChangedListener { public static abstract deprecated interface AudioTrack.OnRoutingChangedListener { method public abstract void onRoutingChanged(android.media.AudioTrack); method public abstract deprecated void onRoutingChanged(android.media.AudioTrack); } } public class CamcorderProfile { public class CamcorderProfile { api/test-current.txt +23 −8 Original line number Original line Diff line number Diff line Loading @@ -19410,9 +19410,10 @@ package android.media { method public abstract void onAudioFocusChange(int); method public abstract void onAudioFocusChange(int); } } public class AudioRecord { public class AudioRecord implements android.media.AudioRouting { ctor public AudioRecord(int, int, int, int, int) throws java.lang.IllegalArgumentException; ctor public AudioRecord(int, int, int, int, int) throws java.lang.IllegalArgumentException; method public void addOnRoutingChangedListener(android.media.AudioRecord.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 getAudioFormat(); method public int getAudioSessionId(); method public int getAudioSessionId(); method public int getAudioSource(); method public int getAudioSource(); Loading @@ -19436,7 +19437,8 @@ package android.media { method public int read(java.nio.ByteBuffer, int); method public int read(java.nio.ByteBuffer, int); method public int read(java.nio.ByteBuffer, int, int); method public int read(java.nio.ByteBuffer, int, int); method public void release(); method public void release(); method public void removeOnRoutingChangedListener(android.media.AudioRecord.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 setNotificationMarkerPosition(int); method public int setPositionNotificationPeriod(int); method public int setPositionNotificationPeriod(int); method public boolean setPreferredDevice(android.media.AudioDeviceInfo); method public boolean setPreferredDevice(android.media.AudioDeviceInfo); Loading Loading @@ -19474,17 +19476,29 @@ package android.media { method public abstract void onRoutingChanged(android.media.AudioRecord); method public abstract void onRoutingChanged(android.media.AudioRecord); } } public abstract interface AudioRouting { method public abstract void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); method public abstract android.media.AudioDeviceInfo getPreferredDevice(); method public abstract void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener); method public abstract boolean setPreferredDevice(android.media.AudioDeviceInfo); } public static abstract interface AudioRouting.OnRoutingChangedListener { method public abstract void onRoutingChanged(android.media.AudioRouting); } public final class AudioTimestamp { public final class AudioTimestamp { ctor public AudioTimestamp(); ctor public AudioTimestamp(); field public long framePosition; field public long framePosition; field public long nanoTime; field public long nanoTime; } } public class AudioTrack { public class AudioTrack implements android.media.AudioRouting { ctor public AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException; 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(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; ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException; method public void addOnRoutingChangedListener(android.media.AudioTrack.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 int attachAuxEffect(int); method public void flush(); method public void flush(); method public int getAudioFormat(); method public int getAudioFormat(); Loading Loading @@ -19514,7 +19528,8 @@ package android.media { method public void play() throws java.lang.IllegalStateException; method public void play() throws java.lang.IllegalStateException; method public void release(); method public void release(); method public int reloadStaticData(); method public int reloadStaticData(); method public void removeOnRoutingChangedListener(android.media.AudioTrack.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 setAuxEffectSendLevel(float); method public int setLoopPoints(int, int, int); method public int setLoopPoints(int, int, int); method public int setNotificationMarkerPosition(int); method public int setNotificationMarkerPosition(int); Loading Loading @@ -19567,8 +19582,8 @@ package android.media { method public abstract void onPeriodicNotification(android.media.AudioTrack); method public abstract void onPeriodicNotification(android.media.AudioTrack); } } public static abstract interface AudioTrack.OnRoutingChangedListener { public static abstract deprecated interface AudioTrack.OnRoutingChangedListener { method public abstract void onRoutingChanged(android.media.AudioTrack); method public abstract deprecated void onRoutingChanged(android.media.AudioTrack); } } public class CamcorderProfile { public class CamcorderProfile { media/java/android/media/AudioRecord.java +169 −26 Original line number Original line Diff line number Diff line Loading @@ -51,7 +51,7 @@ import android.util.Log; * been read yet. Data should be read from the audio hardware in chunks of sizes inferior to * been read yet. Data should be read from the audio hardware in chunks of sizes inferior to * the total recording buffer size. * the total recording buffer size. */ */ public class AudioRecord public class AudioRecord implements AudioRouting { { //--------------------------------------------------------- //--------------------------------------------------------- // Constants // Constants Loading Loading @@ -391,6 +391,20 @@ public class AudioRecord mState = STATE_INITIALIZED; mState = STATE_INITIALIZED; } } /** * A constructor which explicitly connects a Native (C++) AudioRecord. For use by * the AudioRecordRoutingProxy subclass. * @param nativeRecordInJavaObj A C/C++ pointer to a native AudioRecord * (associated with an OpenSL ES recorder). */ /*package*/ AudioRecord(long nativeRecordInJavaObj) { mNativeRecorderInJavaObj = nativeRecordInJavaObj; // other initialization here... mState = STATE_INITIALIZED; } /** /** * Builder class for {@link AudioRecord} objects. * Builder class for {@link AudioRecord} objects. * Use this class to configure and create an <code>AudioRecord</code> instance. By setting the * Use this class to configure and create an <code>AudioRecord</code> instance. By setting the Loading Loading @@ -1221,23 +1235,6 @@ public class AudioRecord return native_set_marker_pos(markerInFrames); return native_set_marker_pos(markerInFrames); } } //-------------------------------------------------------------------------- // (Re)Routing Info //-------------------- /** * Defines the interface by which applications can receive notifications of routing * changes for the associated {@link AudioRecord}. */ public interface 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. */ public void onRoutingChanged(AudioRecord audioRecord); } /** /** * Returns an {@link AudioDeviceInfo} identifying the current routing of this AudioRecord. * Returns an {@link AudioDeviceInfo} identifying the current routing of this AudioRecord. * Note: The query is only valid if the AudioRecord is currently recording. If it is not, * Note: The query is only valid if the AudioRecord is currently recording. If it is not, Loading @@ -1258,6 +1255,89 @@ public class AudioRecord return null; return null; } } /* * Call BEFORE adding a routing callback handler. */ private void testEnableNativeRoutingCallbacks() { if (mRoutingChangeListeners.size() == 0 && mNewRoutingChangeListeners.size() == 0) { native_enableDeviceCallback(); } } /* * Call AFTER removing a routing callback handler. */ private void testDisableNativeRoutingCallbacks() { if (mRoutingChangeListeners.size() == 0 && mNewRoutingChangeListeners.size() == 0) { native_disableDeviceCallback(); } } //-------------------------------------------------------------------------- // >= "N" (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. */ private ArrayMap<AudioRouting.OnRoutingChangedListener, NativeNewRoutingEventHandlerDelegate> mNewRoutingChangeListeners = new ArrayMap<AudioRouting.OnRoutingChangedListener, NativeNewRoutingEventHandlerDelegate>(); /** * Adds an {@link AudioRouting.OnRoutingChangedListener} to receive notifications of * routing changes on this AudioRecord. * @param listener The {@link AudioRouting.OnRoutingChangedListener} interface to receive * notifications of rerouting events. * @param handler Specifies the {@link Handler} object for the thread on which to execute * the callback. If <code>null</code>, the {@link Handler} associated with the main * {@link Looper} will be used. */ public void addOnRoutingListener(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))); } } } /** * Removes an {@link AudioRouting.OnRoutingChangedListener} which has been previously added * to receive rerouting notifications. * @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(); } } } //-------------------------------------------------------------------------- // Marshmallow (Re)Routing Info //-------------------- /** * Defines the interface by which applications can receive notifications of routing * changes for the associated {@link AudioRecord}. */ public interface 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. */ public void onRoutingChanged(AudioRecord audioRecord); } /** /** * The list of AudioRecord.OnRoutingChangedListener interface added (with * The list of AudioRecord.OnRoutingChangedListener interface added (with * {@link AudioRecord#addOnRoutingChangedListener(OnRoutingChangedListener,android.os.Handler)} * {@link AudioRecord#addOnRoutingChangedListener(OnRoutingChangedListener,android.os.Handler)} Loading @@ -1276,13 +1356,12 @@ public class AudioRecord * the callback. If <code>null</code>, the {@link Handler} associated with the main * the callback. If <code>null</code>, the {@link Handler} associated with the main * {@link Looper} will be used. * {@link Looper} will be used. */ */ @Deprecated public void addOnRoutingChangedListener(OnRoutingChangedListener listener, public void addOnRoutingChangedListener(OnRoutingChangedListener listener, android.os.Handler handler) { android.os.Handler handler) { if (listener != null && !mRoutingChangeListeners.containsKey(listener)) { if (listener != null && !mRoutingChangeListeners.containsKey(listener)) { synchronized (mRoutingChangeListeners) { synchronized (mRoutingChangeListeners) { if (mRoutingChangeListeners.size() == 0) { testEnableNativeRoutingCallbacks(); native_enableDeviceCallback(); } mRoutingChangeListeners.put( mRoutingChangeListeners.put( listener, new NativeRoutingEventHandlerDelegate(this, listener, listener, new NativeRoutingEventHandlerDelegate(this, listener, handler != null ? handler : new Handler(mInitializationLooper))); handler != null ? handler : new Handler(mInitializationLooper))); Loading @@ -1295,18 +1374,69 @@ public class AudioRecord * to receive rerouting notifications. * to receive rerouting notifications. * @param listener The previously added {@link OnRoutingChangedListener} interface to remove. * @param listener The previously added {@link OnRoutingChangedListener} interface to remove. */ */ @Deprecated public void removeOnRoutingChangedListener(OnRoutingChangedListener listener) { public void removeOnRoutingChangedListener(OnRoutingChangedListener listener) { synchronized (mRoutingChangeListeners) { synchronized (mRoutingChangeListeners) { if (mRoutingChangeListeners.containsKey(listener)) { if (mRoutingChangeListeners.containsKey(listener)) { mRoutingChangeListeners.remove(listener); mRoutingChangeListeners.remove(listener); if (mRoutingChangeListeners.size() == 0) { testDisableNativeRoutingCallbacks(); native_disableDeviceCallback(); } } } /** * >= "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 * Helper class to handle the forwarding of native events to the appropriate listener * (potentially) handled in a different thread * (potentially) handled in a different thread */ */ Loading Loading @@ -1355,21 +1485,34 @@ public class AudioRecord return mHandler; return mHandler; } } } } /** /** * Sends device list change notification to all listeners. * Sends device list change notification to all listeners. */ */ private void broadcastRoutingChange() { private void broadcastRoutingChange() { AudioManager.resetAudioPortGeneration(); // Marshmallow Routing Collection<NativeRoutingEventHandlerDelegate> values; Collection<NativeRoutingEventHandlerDelegate> values; synchronized (mRoutingChangeListeners) { synchronized (mRoutingChangeListeners) { values = mRoutingChangeListeners.values(); values = mRoutingChangeListeners.values(); } } AudioManager.resetAudioPortGeneration(); for(NativeRoutingEventHandlerDelegate delegate : values) { for(NativeRoutingEventHandlerDelegate delegate : values) { Handler handler = delegate.getHandler(); Handler handler = delegate.getHandler(); if (handler != null) { if (handler != null) { handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE); handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE); } } } } // >= "N" Routing Collection<NativeNewRoutingEventHandlerDelegate> newValues; synchronized (mNewRoutingChangeListeners) { newValues = mNewRoutingChangeListeners.values(); } for(NativeNewRoutingEventHandlerDelegate delegate : newValues) { Handler handler = delegate.getHandler(); if (handler != null) { handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE); } } } } /** /** Loading media/java/android/media/AudioRecordRoutingProxy.java 0 → 100644 +32 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2008 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; /** * An AudioRecord connected to a native (C/C++) which allows access only to routing methods. */ class AudioRecordRoutingProxy extends AudioRecord { /** * A constructor which explicitly connects a Native (C++) AudioRecord. For use by * the AudioRecordRoutingProxy subclass. * @param nativeRecordInJavaObj A C/C++ pointer to a native AudioRecord * (associated with an OpenSL ES recorder). */ public AudioRecordRoutingProxy(long nativeRecordInJavaObj) { super(nativeRecordInJavaObj); } } Loading
api/current.txt +23 −8 Original line number Original line Diff line number Diff line Loading @@ -19402,9 +19402,10 @@ package android.media { method public abstract void onAudioFocusChange(int); method public abstract void onAudioFocusChange(int); } } public class AudioRecord { public class AudioRecord implements android.media.AudioRouting { ctor public AudioRecord(int, int, int, int, int) throws java.lang.IllegalArgumentException; ctor public AudioRecord(int, int, int, int, int) throws java.lang.IllegalArgumentException; method public void addOnRoutingChangedListener(android.media.AudioRecord.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 getAudioFormat(); method public int getAudioSessionId(); method public int getAudioSessionId(); method public int getAudioSource(); method public int getAudioSource(); Loading @@ -19428,7 +19429,8 @@ package android.media { method public int read(java.nio.ByteBuffer, int); method public int read(java.nio.ByteBuffer, int); method public int read(java.nio.ByteBuffer, int, int); method public int read(java.nio.ByteBuffer, int, int); method public void release(); method public void release(); method public void removeOnRoutingChangedListener(android.media.AudioRecord.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 setNotificationMarkerPosition(int); method public int setPositionNotificationPeriod(int); method public int setPositionNotificationPeriod(int); method public boolean setPreferredDevice(android.media.AudioDeviceInfo); method public boolean setPreferredDevice(android.media.AudioDeviceInfo); Loading Loading @@ -19466,17 +19468,29 @@ package android.media { method public abstract void onRoutingChanged(android.media.AudioRecord); method public abstract void onRoutingChanged(android.media.AudioRecord); } } public abstract interface AudioRouting { method public abstract void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); method public abstract android.media.AudioDeviceInfo getPreferredDevice(); method public abstract void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener); method public abstract boolean setPreferredDevice(android.media.AudioDeviceInfo); } public static abstract interface AudioRouting.OnRoutingChangedListener { method public abstract void onRoutingChanged(android.media.AudioRouting); } public final class AudioTimestamp { public final class AudioTimestamp { ctor public AudioTimestamp(); ctor public AudioTimestamp(); field public long framePosition; field public long framePosition; field public long nanoTime; field public long nanoTime; } } public class AudioTrack { public class AudioTrack implements android.media.AudioRouting { ctor public AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException; 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(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; ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException; method public void addOnRoutingChangedListener(android.media.AudioTrack.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 int attachAuxEffect(int); method public void flush(); method public void flush(); method public int getAudioFormat(); method public int getAudioFormat(); Loading Loading @@ -19506,7 +19520,8 @@ package android.media { method public void play() throws java.lang.IllegalStateException; method public void play() throws java.lang.IllegalStateException; method public void release(); method public void release(); method public int reloadStaticData(); method public int reloadStaticData(); method public void removeOnRoutingChangedListener(android.media.AudioTrack.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 setAuxEffectSendLevel(float); method public int setLoopPoints(int, int, int); method public int setLoopPoints(int, int, int); method public int setNotificationMarkerPosition(int); method public int setNotificationMarkerPosition(int); Loading Loading @@ -19559,8 +19574,8 @@ package android.media { method public abstract void onPeriodicNotification(android.media.AudioTrack); method public abstract void onPeriodicNotification(android.media.AudioTrack); } } public static abstract interface AudioTrack.OnRoutingChangedListener { public static abstract deprecated interface AudioTrack.OnRoutingChangedListener { method public abstract void onRoutingChanged(android.media.AudioTrack); method public abstract deprecated void onRoutingChanged(android.media.AudioTrack); } } public class CamcorderProfile { public class CamcorderProfile {
api/system-current.txt +23 −8 Original line number Original line Diff line number Diff line Loading @@ -20706,10 +20706,11 @@ package android.media { method public abstract void onAudioFocusChange(int); method public abstract void onAudioFocusChange(int); } } public class AudioRecord { public class AudioRecord implements android.media.AudioRouting { ctor public AudioRecord(int, int, int, int, int) throws java.lang.IllegalArgumentException; 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; ctor public AudioRecord(android.media.AudioAttributes, android.media.AudioFormat, int, int) throws java.lang.IllegalArgumentException; method public void addOnRoutingChangedListener(android.media.AudioRecord.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 getAudioFormat(); method public int getAudioSessionId(); method public int getAudioSessionId(); method public int getAudioSource(); method public int getAudioSource(); Loading @@ -20733,7 +20734,8 @@ package android.media { method public int read(java.nio.ByteBuffer, int); method public int read(java.nio.ByteBuffer, int); method public int read(java.nio.ByteBuffer, int, int); method public int read(java.nio.ByteBuffer, int, int); method public void release(); method public void release(); method public void removeOnRoutingChangedListener(android.media.AudioRecord.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 setNotificationMarkerPosition(int); method public int setPositionNotificationPeriod(int); method public int setPositionNotificationPeriod(int); method public boolean setPreferredDevice(android.media.AudioDeviceInfo); method public boolean setPreferredDevice(android.media.AudioDeviceInfo); Loading Loading @@ -20773,17 +20775,29 @@ package android.media { method public abstract void onRoutingChanged(android.media.AudioRecord); method public abstract void onRoutingChanged(android.media.AudioRecord); } } public abstract interface AudioRouting { method public abstract void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); method public abstract android.media.AudioDeviceInfo getPreferredDevice(); method public abstract void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener); method public abstract boolean setPreferredDevice(android.media.AudioDeviceInfo); } public static abstract interface AudioRouting.OnRoutingChangedListener { method public abstract void onRoutingChanged(android.media.AudioRouting); } public final class AudioTimestamp { public final class AudioTimestamp { ctor public AudioTimestamp(); ctor public AudioTimestamp(); field public long framePosition; field public long framePosition; field public long nanoTime; field public long nanoTime; } } public class AudioTrack { public class AudioTrack implements android.media.AudioRouting { ctor public AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException; 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(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; ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException; method public void addOnRoutingChangedListener(android.media.AudioTrack.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 int attachAuxEffect(int); method public void flush(); method public void flush(); method public int getAudioFormat(); method public int getAudioFormat(); Loading Loading @@ -20813,7 +20827,8 @@ package android.media { method public void play() throws java.lang.IllegalStateException; method public void play() throws java.lang.IllegalStateException; method public void release(); method public void release(); method public int reloadStaticData(); method public int reloadStaticData(); method public void removeOnRoutingChangedListener(android.media.AudioTrack.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 setAuxEffectSendLevel(float); method public int setLoopPoints(int, int, int); method public int setLoopPoints(int, int, int); method public int setNotificationMarkerPosition(int); method public int setNotificationMarkerPosition(int); Loading Loading @@ -20866,8 +20881,8 @@ package android.media { method public abstract void onPeriodicNotification(android.media.AudioTrack); method public abstract void onPeriodicNotification(android.media.AudioTrack); } } public static abstract interface AudioTrack.OnRoutingChangedListener { public static abstract deprecated interface AudioTrack.OnRoutingChangedListener { method public abstract void onRoutingChanged(android.media.AudioTrack); method public abstract deprecated void onRoutingChanged(android.media.AudioTrack); } } public class CamcorderProfile { public class CamcorderProfile {
api/test-current.txt +23 −8 Original line number Original line Diff line number Diff line Loading @@ -19410,9 +19410,10 @@ package android.media { method public abstract void onAudioFocusChange(int); method public abstract void onAudioFocusChange(int); } } public class AudioRecord { public class AudioRecord implements android.media.AudioRouting { ctor public AudioRecord(int, int, int, int, int) throws java.lang.IllegalArgumentException; ctor public AudioRecord(int, int, int, int, int) throws java.lang.IllegalArgumentException; method public void addOnRoutingChangedListener(android.media.AudioRecord.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 getAudioFormat(); method public int getAudioSessionId(); method public int getAudioSessionId(); method public int getAudioSource(); method public int getAudioSource(); Loading @@ -19436,7 +19437,8 @@ package android.media { method public int read(java.nio.ByteBuffer, int); method public int read(java.nio.ByteBuffer, int); method public int read(java.nio.ByteBuffer, int, int); method public int read(java.nio.ByteBuffer, int, int); method public void release(); method public void release(); method public void removeOnRoutingChangedListener(android.media.AudioRecord.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 setNotificationMarkerPosition(int); method public int setPositionNotificationPeriod(int); method public int setPositionNotificationPeriod(int); method public boolean setPreferredDevice(android.media.AudioDeviceInfo); method public boolean setPreferredDevice(android.media.AudioDeviceInfo); Loading Loading @@ -19474,17 +19476,29 @@ package android.media { method public abstract void onRoutingChanged(android.media.AudioRecord); method public abstract void onRoutingChanged(android.media.AudioRecord); } } public abstract interface AudioRouting { method public abstract void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); method public abstract android.media.AudioDeviceInfo getPreferredDevice(); method public abstract void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener); method public abstract boolean setPreferredDevice(android.media.AudioDeviceInfo); } public static abstract interface AudioRouting.OnRoutingChangedListener { method public abstract void onRoutingChanged(android.media.AudioRouting); } public final class AudioTimestamp { public final class AudioTimestamp { ctor public AudioTimestamp(); ctor public AudioTimestamp(); field public long framePosition; field public long framePosition; field public long nanoTime; field public long nanoTime; } } public class AudioTrack { public class AudioTrack implements android.media.AudioRouting { ctor public AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException; 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(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; ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException; method public void addOnRoutingChangedListener(android.media.AudioTrack.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 int attachAuxEffect(int); method public void flush(); method public void flush(); method public int getAudioFormat(); method public int getAudioFormat(); Loading Loading @@ -19514,7 +19528,8 @@ package android.media { method public void play() throws java.lang.IllegalStateException; method public void play() throws java.lang.IllegalStateException; method public void release(); method public void release(); method public int reloadStaticData(); method public int reloadStaticData(); method public void removeOnRoutingChangedListener(android.media.AudioTrack.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 setAuxEffectSendLevel(float); method public int setLoopPoints(int, int, int); method public int setLoopPoints(int, int, int); method public int setNotificationMarkerPosition(int); method public int setNotificationMarkerPosition(int); Loading Loading @@ -19567,8 +19582,8 @@ package android.media { method public abstract void onPeriodicNotification(android.media.AudioTrack); method public abstract void onPeriodicNotification(android.media.AudioTrack); } } public static abstract interface AudioTrack.OnRoutingChangedListener { public static abstract deprecated interface AudioTrack.OnRoutingChangedListener { method public abstract void onRoutingChanged(android.media.AudioTrack); method public abstract deprecated void onRoutingChanged(android.media.AudioTrack); } } public class CamcorderProfile { public class CamcorderProfile {
media/java/android/media/AudioRecord.java +169 −26 Original line number Original line Diff line number Diff line Loading @@ -51,7 +51,7 @@ import android.util.Log; * been read yet. Data should be read from the audio hardware in chunks of sizes inferior to * been read yet. Data should be read from the audio hardware in chunks of sizes inferior to * the total recording buffer size. * the total recording buffer size. */ */ public class AudioRecord public class AudioRecord implements AudioRouting { { //--------------------------------------------------------- //--------------------------------------------------------- // Constants // Constants Loading Loading @@ -391,6 +391,20 @@ public class AudioRecord mState = STATE_INITIALIZED; mState = STATE_INITIALIZED; } } /** * A constructor which explicitly connects a Native (C++) AudioRecord. For use by * the AudioRecordRoutingProxy subclass. * @param nativeRecordInJavaObj A C/C++ pointer to a native AudioRecord * (associated with an OpenSL ES recorder). */ /*package*/ AudioRecord(long nativeRecordInJavaObj) { mNativeRecorderInJavaObj = nativeRecordInJavaObj; // other initialization here... mState = STATE_INITIALIZED; } /** /** * Builder class for {@link AudioRecord} objects. * Builder class for {@link AudioRecord} objects. * Use this class to configure and create an <code>AudioRecord</code> instance. By setting the * Use this class to configure and create an <code>AudioRecord</code> instance. By setting the Loading Loading @@ -1221,23 +1235,6 @@ public class AudioRecord return native_set_marker_pos(markerInFrames); return native_set_marker_pos(markerInFrames); } } //-------------------------------------------------------------------------- // (Re)Routing Info //-------------------- /** * Defines the interface by which applications can receive notifications of routing * changes for the associated {@link AudioRecord}. */ public interface 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. */ public void onRoutingChanged(AudioRecord audioRecord); } /** /** * Returns an {@link AudioDeviceInfo} identifying the current routing of this AudioRecord. * Returns an {@link AudioDeviceInfo} identifying the current routing of this AudioRecord. * Note: The query is only valid if the AudioRecord is currently recording. If it is not, * Note: The query is only valid if the AudioRecord is currently recording. If it is not, Loading @@ -1258,6 +1255,89 @@ public class AudioRecord return null; return null; } } /* * Call BEFORE adding a routing callback handler. */ private void testEnableNativeRoutingCallbacks() { if (mRoutingChangeListeners.size() == 0 && mNewRoutingChangeListeners.size() == 0) { native_enableDeviceCallback(); } } /* * Call AFTER removing a routing callback handler. */ private void testDisableNativeRoutingCallbacks() { if (mRoutingChangeListeners.size() == 0 && mNewRoutingChangeListeners.size() == 0) { native_disableDeviceCallback(); } } //-------------------------------------------------------------------------- // >= "N" (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. */ private ArrayMap<AudioRouting.OnRoutingChangedListener, NativeNewRoutingEventHandlerDelegate> mNewRoutingChangeListeners = new ArrayMap<AudioRouting.OnRoutingChangedListener, NativeNewRoutingEventHandlerDelegate>(); /** * Adds an {@link AudioRouting.OnRoutingChangedListener} to receive notifications of * routing changes on this AudioRecord. * @param listener The {@link AudioRouting.OnRoutingChangedListener} interface to receive * notifications of rerouting events. * @param handler Specifies the {@link Handler} object for the thread on which to execute * the callback. If <code>null</code>, the {@link Handler} associated with the main * {@link Looper} will be used. */ public void addOnRoutingListener(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))); } } } /** * Removes an {@link AudioRouting.OnRoutingChangedListener} which has been previously added * to receive rerouting notifications. * @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(); } } } //-------------------------------------------------------------------------- // Marshmallow (Re)Routing Info //-------------------- /** * Defines the interface by which applications can receive notifications of routing * changes for the associated {@link AudioRecord}. */ public interface 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. */ public void onRoutingChanged(AudioRecord audioRecord); } /** /** * The list of AudioRecord.OnRoutingChangedListener interface added (with * The list of AudioRecord.OnRoutingChangedListener interface added (with * {@link AudioRecord#addOnRoutingChangedListener(OnRoutingChangedListener,android.os.Handler)} * {@link AudioRecord#addOnRoutingChangedListener(OnRoutingChangedListener,android.os.Handler)} Loading @@ -1276,13 +1356,12 @@ public class AudioRecord * the callback. If <code>null</code>, the {@link Handler} associated with the main * the callback. If <code>null</code>, the {@link Handler} associated with the main * {@link Looper} will be used. * {@link Looper} will be used. */ */ @Deprecated public void addOnRoutingChangedListener(OnRoutingChangedListener listener, public void addOnRoutingChangedListener(OnRoutingChangedListener listener, android.os.Handler handler) { android.os.Handler handler) { if (listener != null && !mRoutingChangeListeners.containsKey(listener)) { if (listener != null && !mRoutingChangeListeners.containsKey(listener)) { synchronized (mRoutingChangeListeners) { synchronized (mRoutingChangeListeners) { if (mRoutingChangeListeners.size() == 0) { testEnableNativeRoutingCallbacks(); native_enableDeviceCallback(); } mRoutingChangeListeners.put( mRoutingChangeListeners.put( listener, new NativeRoutingEventHandlerDelegate(this, listener, listener, new NativeRoutingEventHandlerDelegate(this, listener, handler != null ? handler : new Handler(mInitializationLooper))); handler != null ? handler : new Handler(mInitializationLooper))); Loading @@ -1295,18 +1374,69 @@ public class AudioRecord * to receive rerouting notifications. * to receive rerouting notifications. * @param listener The previously added {@link OnRoutingChangedListener} interface to remove. * @param listener The previously added {@link OnRoutingChangedListener} interface to remove. */ */ @Deprecated public void removeOnRoutingChangedListener(OnRoutingChangedListener listener) { public void removeOnRoutingChangedListener(OnRoutingChangedListener listener) { synchronized (mRoutingChangeListeners) { synchronized (mRoutingChangeListeners) { if (mRoutingChangeListeners.containsKey(listener)) { if (mRoutingChangeListeners.containsKey(listener)) { mRoutingChangeListeners.remove(listener); mRoutingChangeListeners.remove(listener); if (mRoutingChangeListeners.size() == 0) { testDisableNativeRoutingCallbacks(); native_disableDeviceCallback(); } } } /** * >= "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 * Helper class to handle the forwarding of native events to the appropriate listener * (potentially) handled in a different thread * (potentially) handled in a different thread */ */ Loading Loading @@ -1355,21 +1485,34 @@ public class AudioRecord return mHandler; return mHandler; } } } } /** /** * Sends device list change notification to all listeners. * Sends device list change notification to all listeners. */ */ private void broadcastRoutingChange() { private void broadcastRoutingChange() { AudioManager.resetAudioPortGeneration(); // Marshmallow Routing Collection<NativeRoutingEventHandlerDelegate> values; Collection<NativeRoutingEventHandlerDelegate> values; synchronized (mRoutingChangeListeners) { synchronized (mRoutingChangeListeners) { values = mRoutingChangeListeners.values(); values = mRoutingChangeListeners.values(); } } AudioManager.resetAudioPortGeneration(); for(NativeRoutingEventHandlerDelegate delegate : values) { for(NativeRoutingEventHandlerDelegate delegate : values) { Handler handler = delegate.getHandler(); Handler handler = delegate.getHandler(); if (handler != null) { if (handler != null) { handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE); handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE); } } } } // >= "N" Routing Collection<NativeNewRoutingEventHandlerDelegate> newValues; synchronized (mNewRoutingChangeListeners) { newValues = mNewRoutingChangeListeners.values(); } for(NativeNewRoutingEventHandlerDelegate delegate : newValues) { Handler handler = delegate.getHandler(); if (handler != null) { handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE); } } } } /** /** Loading
media/java/android/media/AudioRecordRoutingProxy.java 0 → 100644 +32 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2008 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; /** * An AudioRecord connected to a native (C/C++) which allows access only to routing methods. */ class AudioRecordRoutingProxy extends AudioRecord { /** * A constructor which explicitly connects a Native (C++) AudioRecord. For use by * the AudioRecordRoutingProxy subclass. * @param nativeRecordInJavaObj A C/C++ pointer to a native AudioRecord * (associated with an OpenSL ES recorder). */ public AudioRecordRoutingProxy(long nativeRecordInJavaObj) { super(nativeRecordInJavaObj); } }