Unhide audio recording notification API
Introduce new methods and classes for the audio recording configuration update and query API. Callback registration supports a Handler. Bug 22876530 Change-Id: I819ad464f095d970b5d1d8a3781fcf8dbb310424
This commit is contained in:
@@ -19297,6 +19297,7 @@ package android.media {
|
||||
method public void adjustVolume(int, int);
|
||||
method public void dispatchMediaKeyEvent(android.view.KeyEvent);
|
||||
method public int generateAudioSessionId();
|
||||
method public android.media.AudioRecordConfiguration[] getActiveRecordConfigurations();
|
||||
method public android.media.AudioDeviceInfo[] getDevices(int);
|
||||
method public int getMode();
|
||||
method public java.lang.String getParameters(java.lang.String);
|
||||
@@ -19319,6 +19320,7 @@ package android.media {
|
||||
method public void playSoundEffect(int);
|
||||
method public void playSoundEffect(int, float);
|
||||
method public void registerAudioDeviceCallback(android.media.AudioDeviceCallback, android.os.Handler);
|
||||
method public void registerAudioRecordingCallback(android.media.AudioManager.AudioRecordingCallback, android.os.Handler);
|
||||
method public deprecated void registerMediaButtonEventReceiver(android.content.ComponentName);
|
||||
method public deprecated void registerMediaButtonEventReceiver(android.app.PendingIntent);
|
||||
method public deprecated void registerRemoteControlClient(android.media.RemoteControlClient);
|
||||
@@ -19342,6 +19344,7 @@ package android.media {
|
||||
method public void stopBluetoothSco();
|
||||
method public void unloadSoundEffects();
|
||||
method public void unregisterAudioDeviceCallback(android.media.AudioDeviceCallback);
|
||||
method public void unregisterAudioRecordingCallback(android.media.AudioManager.AudioRecordingCallback);
|
||||
method public deprecated void unregisterMediaButtonEventReceiver(android.content.ComponentName);
|
||||
method public deprecated void unregisterMediaButtonEventReceiver(android.app.PendingIntent);
|
||||
method public deprecated void unregisterRemoteControlClient(android.media.RemoteControlClient);
|
||||
@@ -19438,6 +19441,11 @@ package android.media {
|
||||
field public static final deprecated int VIBRATE_TYPE_RINGER = 0; // 0x0
|
||||
}
|
||||
|
||||
public static abstract class AudioManager.AudioRecordingCallback {
|
||||
ctor public AudioManager.AudioRecordingCallback();
|
||||
method public void onRecordConfigChanged();
|
||||
}
|
||||
|
||||
public static abstract interface AudioManager.OnAudioFocusChangeListener {
|
||||
method public abstract void onAudioFocusChange(int);
|
||||
}
|
||||
@@ -19508,6 +19516,14 @@ package android.media {
|
||||
method public abstract void onRoutingChanged(android.media.AudioRecord);
|
||||
}
|
||||
|
||||
public class AudioRecordConfiguration implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public int getAudioSessionId();
|
||||
method public int getClientAudioSource();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator<android.media.AudioRecordConfiguration> CREATOR;
|
||||
}
|
||||
|
||||
public abstract interface AudioRouting {
|
||||
method public abstract void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
|
||||
method public abstract android.media.AudioDeviceInfo getPreferredDevice();
|
||||
|
||||
@@ -20623,6 +20623,7 @@ package android.media {
|
||||
method public void adjustVolume(int, int);
|
||||
method public void dispatchMediaKeyEvent(android.view.KeyEvent);
|
||||
method public int generateAudioSessionId();
|
||||
method public android.media.AudioRecordConfiguration[] getActiveRecordConfigurations();
|
||||
method public android.media.AudioDeviceInfo[] getDevices(int);
|
||||
method public int getMode();
|
||||
method public java.lang.String getParameters(java.lang.String);
|
||||
@@ -20647,6 +20648,7 @@ package android.media {
|
||||
method public void playSoundEffect(int, float);
|
||||
method public void registerAudioDeviceCallback(android.media.AudioDeviceCallback, android.os.Handler);
|
||||
method public int registerAudioPolicy(android.media.audiopolicy.AudioPolicy);
|
||||
method public void registerAudioRecordingCallback(android.media.AudioManager.AudioRecordingCallback, android.os.Handler);
|
||||
method public deprecated void registerMediaButtonEventReceiver(android.content.ComponentName);
|
||||
method public deprecated void registerMediaButtonEventReceiver(android.app.PendingIntent);
|
||||
method public deprecated void registerRemoteControlClient(android.media.RemoteControlClient);
|
||||
@@ -20673,6 +20675,7 @@ package android.media {
|
||||
method public void unloadSoundEffects();
|
||||
method public void unregisterAudioDeviceCallback(android.media.AudioDeviceCallback);
|
||||
method public void unregisterAudioPolicyAsync(android.media.audiopolicy.AudioPolicy);
|
||||
method public void unregisterAudioRecordingCallback(android.media.AudioManager.AudioRecordingCallback);
|
||||
method public deprecated void unregisterMediaButtonEventReceiver(android.content.ComponentName);
|
||||
method public deprecated void unregisterMediaButtonEventReceiver(android.app.PendingIntent);
|
||||
method public deprecated void unregisterRemoteControlClient(android.media.RemoteControlClient);
|
||||
@@ -20772,6 +20775,11 @@ package android.media {
|
||||
field public static final deprecated int VIBRATE_TYPE_RINGER = 0; // 0x0
|
||||
}
|
||||
|
||||
public static abstract class AudioManager.AudioRecordingCallback {
|
||||
ctor public AudioManager.AudioRecordingCallback();
|
||||
method public void onRecordConfigChanged();
|
||||
}
|
||||
|
||||
public static abstract interface AudioManager.OnAudioFocusChangeListener {
|
||||
method public abstract void onAudioFocusChange(int);
|
||||
}
|
||||
@@ -20845,6 +20853,14 @@ package android.media {
|
||||
method public abstract void onRoutingChanged(android.media.AudioRecord);
|
||||
}
|
||||
|
||||
public class AudioRecordConfiguration implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public int getAudioSessionId();
|
||||
method public int getClientAudioSource();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator<android.media.AudioRecordConfiguration> CREATOR;
|
||||
}
|
||||
|
||||
public abstract interface AudioRouting {
|
||||
method public abstract void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
|
||||
method public abstract android.media.AudioDeviceInfo getPreferredDevice();
|
||||
|
||||
@@ -19305,6 +19305,7 @@ package android.media {
|
||||
method public void adjustVolume(int, int);
|
||||
method public void dispatchMediaKeyEvent(android.view.KeyEvent);
|
||||
method public int generateAudioSessionId();
|
||||
method public android.media.AudioRecordConfiguration[] getActiveRecordConfigurations();
|
||||
method public android.media.AudioDeviceInfo[] getDevices(int);
|
||||
method public int getMode();
|
||||
method public java.lang.String getParameters(java.lang.String);
|
||||
@@ -19327,6 +19328,7 @@ package android.media {
|
||||
method public void playSoundEffect(int);
|
||||
method public void playSoundEffect(int, float);
|
||||
method public void registerAudioDeviceCallback(android.media.AudioDeviceCallback, android.os.Handler);
|
||||
method public void registerAudioRecordingCallback(android.media.AudioManager.AudioRecordingCallback, android.os.Handler);
|
||||
method public deprecated void registerMediaButtonEventReceiver(android.content.ComponentName);
|
||||
method public deprecated void registerMediaButtonEventReceiver(android.app.PendingIntent);
|
||||
method public deprecated void registerRemoteControlClient(android.media.RemoteControlClient);
|
||||
@@ -19350,6 +19352,7 @@ package android.media {
|
||||
method public void stopBluetoothSco();
|
||||
method public void unloadSoundEffects();
|
||||
method public void unregisterAudioDeviceCallback(android.media.AudioDeviceCallback);
|
||||
method public void unregisterAudioRecordingCallback(android.media.AudioManager.AudioRecordingCallback);
|
||||
method public deprecated void unregisterMediaButtonEventReceiver(android.content.ComponentName);
|
||||
method public deprecated void unregisterMediaButtonEventReceiver(android.app.PendingIntent);
|
||||
method public deprecated void unregisterRemoteControlClient(android.media.RemoteControlClient);
|
||||
@@ -19446,6 +19449,11 @@ package android.media {
|
||||
field public static final deprecated int VIBRATE_TYPE_RINGER = 0; // 0x0
|
||||
}
|
||||
|
||||
public static abstract class AudioManager.AudioRecordingCallback {
|
||||
ctor public AudioManager.AudioRecordingCallback();
|
||||
method public void onRecordConfigChanged();
|
||||
}
|
||||
|
||||
public static abstract interface AudioManager.OnAudioFocusChangeListener {
|
||||
method public abstract void onAudioFocusChange(int);
|
||||
}
|
||||
@@ -19516,6 +19524,14 @@ package android.media {
|
||||
method public abstract void onRoutingChanged(android.media.AudioRecord);
|
||||
}
|
||||
|
||||
public class AudioRecordConfiguration implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public int getAudioSessionId();
|
||||
method public int getClientAudioSource();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator<android.media.AudioRecordConfiguration> CREATOR;
|
||||
}
|
||||
|
||||
public abstract interface AudioRouting {
|
||||
method public abstract void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
|
||||
method public abstract android.media.AudioDeviceInfo getPreferredDevice();
|
||||
|
||||
@@ -2163,7 +2163,7 @@ public class AudioManager {
|
||||
* audio service.
|
||||
*/
|
||||
private final ServiceEventHandlerDelegate mServiceEventHandlerDelegate =
|
||||
new ServiceEventHandlerDelegate();
|
||||
new ServiceEventHandlerDelegate(null);
|
||||
|
||||
/**
|
||||
* Event types
|
||||
@@ -2177,10 +2177,14 @@ public class AudioManager {
|
||||
private class ServiceEventHandlerDelegate {
|
||||
private final Handler mHandler;
|
||||
|
||||
ServiceEventHandlerDelegate() {
|
||||
ServiceEventHandlerDelegate(Handler handler) {
|
||||
Looper looper;
|
||||
if ((looper = Looper.myLooper()) == null) {
|
||||
looper = Looper.getMainLooper();
|
||||
if (handler == null) {
|
||||
if ((looper = Looper.myLooper()) == null) {
|
||||
looper = Looper.getMainLooper();
|
||||
}
|
||||
} else {
|
||||
looper = handler.getLooper();
|
||||
}
|
||||
|
||||
if (looper != null) {
|
||||
@@ -2201,27 +2205,9 @@ public class AudioManager {
|
||||
}
|
||||
break;
|
||||
case MSSG_RECORDING_CONFIG_CHANGE:
|
||||
// optimizing for the case of a single callback
|
||||
AudioRecordingCallback singleCallback = null;
|
||||
ArrayList<AudioRecordingCallback> multipleCallbacks = null;
|
||||
synchronized(mRecordCallbackLock) {
|
||||
if ((mRecordCallbackList != null)
|
||||
&& (mRecordCallbackList.size() != 0)) {
|
||||
if (mRecordCallbackList.size() == 1) {
|
||||
singleCallback = mRecordCallbackList.get(0);
|
||||
} else {
|
||||
multipleCallbacks =
|
||||
new ArrayList<AudioRecordingCallback>(
|
||||
mRecordCallbackList);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (singleCallback != null) {
|
||||
singleCallback.onRecordConfigChanged();
|
||||
} else if (multipleCallbacks != null) {
|
||||
for (int i=0 ; i < multipleCallbacks.size() ; i++) {
|
||||
multipleCallbacks.get(i).onRecordConfigChanged();
|
||||
}
|
||||
final AudioRecordingCallback cb = (AudioRecordingCallback) msg.obj;
|
||||
if (cb != null) {
|
||||
cb.onRecordConfigChanged();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -2798,34 +2784,51 @@ public class AudioManager {
|
||||
//====================================================================
|
||||
// Recording configuration
|
||||
/**
|
||||
* @hide
|
||||
* candidate for public API
|
||||
* Interface for receiving update notifications about the recording configuration. Extend
|
||||
* this abstract class and register it with
|
||||
* {@link AudioManager#registerAudioRecordingCallback(AudioRecordingCallback, Handler)}
|
||||
* to be notified.
|
||||
* Use {@link AudioManager#getActiveRecordConfigurations()} to query the current configuration.
|
||||
*/
|
||||
public static abstract class AudioRecordingCallback {
|
||||
/**
|
||||
* @hide
|
||||
* candidate for public API
|
||||
* Called whenever the device recording configuration has changed.
|
||||
*/
|
||||
public void onRecordConfigChanged() {}
|
||||
}
|
||||
|
||||
private static class AudioRecordingCallbackInfo {
|
||||
final AudioRecordingCallback mCb;
|
||||
final Handler mHandler;
|
||||
AudioRecordingCallbackInfo(AudioRecordingCallback cb, Handler handler) {
|
||||
mCb = cb;
|
||||
mHandler = handler;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* candidate for public API
|
||||
* @param non-null callback
|
||||
* Register a callback to be notified of audio recording changes through
|
||||
* {@link AudioRecordingCallback}
|
||||
* @param cb non-null callback to register
|
||||
* @param handler 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 registerAudioRecordingCallback(@NonNull AudioRecordingCallback cb) {
|
||||
public void registerAudioRecordingCallback(@NonNull AudioRecordingCallback cb, Handler handler)
|
||||
{
|
||||
if (cb == null) {
|
||||
throw new IllegalArgumentException("Illegal null AudioRecordingCallback argument");
|
||||
}
|
||||
|
||||
synchronized(mRecordCallbackLock) {
|
||||
// lazy initialization of the list of recording callbacks
|
||||
if (mRecordCallbackList == null) {
|
||||
mRecordCallbackList = new ArrayList<AudioRecordingCallback>();
|
||||
mRecordCallbackList = new ArrayList<AudioRecordingCallbackInfo>();
|
||||
}
|
||||
final int oldCbCount = mRecordCallbackList.size();
|
||||
if (!mRecordCallbackList.contains(cb)) {
|
||||
mRecordCallbackList.add(cb);
|
||||
if (!hasRecordCallback_sync(cb)) {
|
||||
mRecordCallbackList.add(new AudioRecordingCallbackInfo(cb,
|
||||
new ServiceEventHandlerDelegate(handler).getHandler()));
|
||||
final int newCbCount = mRecordCallbackList.size();
|
||||
if ((oldCbCount == 0) && (newCbCount > 0)) {
|
||||
// register binder for callbacks
|
||||
@@ -2844,9 +2847,9 @@ public class AudioManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* candidate for public API
|
||||
* @param non-null callback
|
||||
* Unregister an audio recording callback previously registered with
|
||||
* {@link #registerAudioRecordingCallback(AudioRecordingCallback, Handler)}.
|
||||
* @param cb non-null callback to unregister
|
||||
*/
|
||||
public void unregisterAudioRecordingCallback(@NonNull AudioRecordingCallback cb) {
|
||||
if (cb == null) {
|
||||
@@ -2857,7 +2860,7 @@ public class AudioManager {
|
||||
return;
|
||||
}
|
||||
final int oldCbCount = mRecordCallbackList.size();
|
||||
if (mRecordCallbackList.remove(cb)) {
|
||||
if (removeRecordCallback_sync(cb)) {
|
||||
final int newCbCount = mRecordCallbackList.size();
|
||||
if ((oldCbCount > 0) && (newCbCount == 0)) {
|
||||
// unregister binder for callbacks
|
||||
@@ -2876,8 +2879,7 @@ public class AudioManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* candidate for public API
|
||||
* Returns the current active audio recording configurations of the device.
|
||||
* @return a non-null array of recording configurations. An array of length 0 indicates there is
|
||||
* no recording active when queried.
|
||||
*/
|
||||
@@ -2902,18 +2904,57 @@ public class AudioManager {
|
||||
|
||||
/**
|
||||
* All operations on this list are sync'd on mRecordCallbackLock.
|
||||
* List is lazy-initialized in {@link #registerAudioRecordingCallback(AudioRecordingCallback)}.
|
||||
* List is lazy-initialized in
|
||||
* {@link #registerAudioRecordingCallback(AudioRecordingCallback, Handler)}.
|
||||
* List can be null.
|
||||
*/
|
||||
private List<AudioRecordingCallback> mRecordCallbackList;
|
||||
private List<AudioRecordingCallbackInfo> mRecordCallbackList;
|
||||
private final Object mRecordCallbackLock = new Object();
|
||||
|
||||
/**
|
||||
* Must be called synchronized on mRecordCallbackLock
|
||||
*/
|
||||
private boolean hasRecordCallback_sync(@NonNull AudioRecordingCallback cb) {
|
||||
if (mRecordCallbackList != null) {
|
||||
for (int i=0 ; i < mRecordCallbackList.size() ; i++) {
|
||||
if (cb.equals(mRecordCallbackList.get(i).mCb)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Must be called synchronized on mRecordCallbackLock
|
||||
*/
|
||||
private boolean removeRecordCallback_sync(@NonNull AudioRecordingCallback cb) {
|
||||
if (mRecordCallbackList != null) {
|
||||
for (int i=0 ; i < mRecordCallbackList.size() ; i++) {
|
||||
if (cb.equals(mRecordCallbackList.get(i).mCb)) {
|
||||
mRecordCallbackList.remove(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private final IRecordingConfigDispatcher mRecCb = new IRecordingConfigDispatcher.Stub() {
|
||||
|
||||
public void dispatchRecordingConfigChange() {
|
||||
final Message m = mServiceEventHandlerDelegate.getHandler().obtainMessage(
|
||||
MSSG_RECORDING_CONFIG_CHANGE/*what*/);
|
||||
mServiceEventHandlerDelegate.getHandler().sendMessage(m);
|
||||
synchronized(mRecordCallbackLock) {
|
||||
if (mRecordCallbackList != null) {
|
||||
for (int i=0 ; i < mRecordCallbackList.size() ; i++) {
|
||||
final AudioRecordingCallbackInfo arci = mRecordCallbackList.get(i);
|
||||
if (arci.mHandler != null) {
|
||||
final Message m = arci.mHandler.obtainMessage(
|
||||
MSSG_RECORDING_CONFIG_CHANGE/*what*/, arci.mCb/*obj*/);
|
||||
arci.mHandler.sendMessage(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -22,8 +22,9 @@ import android.os.Parcelable;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Candidate for public API, see AudioManager.getActiveRecordConfiguration()
|
||||
* The AudioRecordConfiguration class collects the information describing an audio recording
|
||||
* session. This information is returned through the
|
||||
* {@link AudioManager#getActiveRecordConfigurations()} method.
|
||||
*
|
||||
*/
|
||||
public class AudioRecordConfiguration implements Parcelable {
|
||||
@@ -41,19 +42,23 @@ public class AudioRecordConfiguration implements Parcelable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return one of AudioSource.MIC, AudioSource.VOICE_UPLINK,
|
||||
* AudioSource.VOICE_DOWNLINK, AudioSource.VOICE_CALL,
|
||||
* AudioSource.CAMCORDER, AudioSource.VOICE_RECOGNITION,
|
||||
* AudioSource.VOICE_COMMUNICATION.
|
||||
* Returns the audio source being used for the recording.
|
||||
* @return one of {@link MediaRecorder.AudioSource#MIC},
|
||||
* {@link MediaRecorder.AudioSource#VOICE_UPLINK},
|
||||
* {@link MediaRecorder.AudioSource#VOICE_DOWNLINK},
|
||||
* {@link MediaRecorder.AudioSource#VOICE_CALL},
|
||||
* {@link MediaRecorder.AudioSource#CAMCORDER},
|
||||
* {@link MediaRecorder.AudioSource#VOICE_RECOGNITION},
|
||||
* {@link MediaRecorder.AudioSource#VOICE_COMMUNICATION}.
|
||||
*/
|
||||
public int getClientAudioSource() { return mClientSource; }
|
||||
|
||||
/**
|
||||
* @return the session number of the recorder.
|
||||
* Returns the session number of the recording, see {@link AudioRecord#getAudioSessionId()}.
|
||||
* @return the session number.
|
||||
*/
|
||||
public int getAudioSessionId() { return mSessionId; }
|
||||
|
||||
|
||||
public static final Parcelable.Creator<AudioRecordConfiguration> CREATOR
|
||||
= new Parcelable.Creator<AudioRecordConfiguration>() {
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user