Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 17351b67 authored by Jean-Michel Trivi's avatar Jean-Michel Trivi Committed by Android (Google) Code Review
Browse files

Merge "Unhide audio recording notification API"

parents b11da88d b919f6fd
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -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();
+16 −0
Original line number Diff line number Diff line
@@ -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();
+16 −0
Original line number Diff line number Diff line
@@ -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();
+88 −47
Original line number Diff line number Diff line
@@ -2163,7 +2163,7 @@ public class AudioManager {
     * audio service.
     */
    private final ServiceEventHandlerDelegate mServiceEventHandlerDelegate =
            new ServiceEventHandlerDelegate();
            new ServiceEventHandlerDelegate(null);

    /**
     * Event types
@@ -2177,11 +2177,15 @@ public class AudioManager {
    private class ServiceEventHandlerDelegate {
        private final Handler mHandler;

        ServiceEventHandlerDelegate() {
        ServiceEventHandlerDelegate(Handler handler) {
            Looper looper;
            if (handler == null) {
                if ((looper = Looper.myLooper()) == null) {
                    looper = Looper.getMainLooper();
                }
            } else {
                looper = handler.getLooper();
            }

            if (looper != null) {
                // implement the event handler delegate to receive events from audio service
@@ -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);
                        }
                    }
                }
            }
        }

    };
+13 −8
Original line number Diff line number Diff line
@@ -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>() {
        /**