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

Commit dc03c61f authored by Eric Laurent's avatar Eric Laurent
Browse files

Bluetooth SCO audio API improvements.

The AudioManager API to control bluetooth SCO did not provide an easy way for
applications to handle SCO connection errors. When a request to activate SCO with
AudioManager.startBluetoothSco() failed, no state change was indicated via
AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED intent. The application had to
implement a timeout to handle connection failures.

The API change consists in defining a new intent AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED
and deprecate AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. The new intent
will broacast a new state CONNECTING when the SCO connection is initiated.
The application can monitor changes from CONNECTING to either CONNECTED or DISCONNECTED
states to detect connection success or failure.
An extra indicating the previous state is also added to the new intent.

Also improved BluetoothHeadset service management in AudioService. A disconnection
from the service is not considered as a device or SCO link disconnection. Instead, if the
service interface is not present when a request to activate SCO is received, an
attempt is made to reconnect to the service.

Change-Id: I005fda1caaf74bb7de64fece44e9c7e628e828db
parent 8f40e587
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -9687,7 +9687,8 @@ package android.media {
    method public void unloadSoundEffects();
    method public void unregisterMediaButtonEventReceiver(android.content.ComponentName);
    field public static final java.lang.String ACTION_AUDIO_BECOMING_NOISY = "android.media.AUDIO_BECOMING_NOISY";
    field public static final java.lang.String ACTION_SCO_AUDIO_STATE_CHANGED = "android.media.SCO_AUDIO_STATE_CHANGED";
    field public static final deprecated java.lang.String ACTION_SCO_AUDIO_STATE_CHANGED = "android.media.SCO_AUDIO_STATE_CHANGED";
    field public static final java.lang.String ACTION_SCO_AUDIO_STATE_UPDATED = "android.media.ACTION_SCO_AUDIO_STATE_UPDATED";
    field public static final int ADJUST_LOWER = -1; // 0xffffffff
    field public static final int ADJUST_RAISE = 1; // 0x1
    field public static final int ADJUST_SAME = 0; // 0x0
@@ -9700,6 +9701,7 @@ package android.media {
    field public static final int AUDIOFOCUS_REQUEST_FAILED = 0; // 0x0
    field public static final int AUDIOFOCUS_REQUEST_GRANTED = 1; // 0x1
    field public static final java.lang.String EXTRA_RINGER_MODE = "android.media.EXTRA_RINGER_MODE";
    field public static final java.lang.String EXTRA_SCO_AUDIO_PREVIOUS_STATE = "android.media.extra.SCO_AUDIO_PREVIOUS_STATE";
    field public static final java.lang.String EXTRA_SCO_AUDIO_STATE = "android.media.extra.SCO_AUDIO_STATE";
    field public static final java.lang.String EXTRA_VIBRATE_SETTING = "android.media.EXTRA_VIBRATE_SETTING";
    field public static final java.lang.String EXTRA_VIBRATE_TYPE = "android.media.EXTRA_VIBRATE_TYPE";
@@ -9736,6 +9738,7 @@ package android.media {
    field public static final deprecated int ROUTE_HEADSET = 8; // 0x8
    field public static final deprecated int ROUTE_SPEAKER = 2; // 0x2
    field public static final int SCO_AUDIO_STATE_CONNECTED = 1; // 0x1
    field public static final int SCO_AUDIO_STATE_CONNECTING = 2; // 0x2
    field public static final int SCO_AUDIO_STATE_DISCONNECTED = 0; // 0x0
    field public static final int SCO_AUDIO_STATE_ERROR = -1; // 0xffffffff
    field public static final int STREAM_ALARM = 4; // 0x4
+64 −21
Original line number Diff line number Diff line
@@ -828,29 +828,64 @@ public class AudioManager {
     * or {@link #SCO_AUDIO_STATE_CONNECTED}
     *
     * @see #startBluetoothSco()
     * @deprecated Use  {@link #ACTION_SCO_AUDIO_STATE_UPDATED} instead
     */
    @Deprecated
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String ACTION_SCO_AUDIO_STATE_CHANGED =
            "android.media.SCO_AUDIO_STATE_CHANGED";

     /**
     * Extra for intent {@link #ACTION_SCO_AUDIO_STATE_CHANGED} containing the new
     * bluetooth SCO connection state.
     * Sticky broadcast intent action indicating that the bluetoooth SCO audio
     * connection state has been updated.
     * <p>This intent has two extras:
     * <ul>
     *   <li> {@link #EXTRA_SCO_AUDIO_STATE} - The new SCO audio state. </li>
     *   <li> {@link #EXTRA_SCO_AUDIO_PREVIOUS_STATE}- The previous SCO audio state. </li>
     * </ul>
     * <p> EXTRA_SCO_AUDIO_STATE or EXTRA_SCO_AUDIO_PREVIOUS_STATE can be any of:
     * <ul>
     *   <li> {@link #SCO_AUDIO_STATE_DISCONNECTED}, </li>
     *   <li> {@link #SCO_AUDIO_STATE_CONNECTING} or </li>
     *   <li> {@link #SCO_AUDIO_STATE_CONNECTED}, </li>
     * </ul>
     * @see #startBluetoothSco()
     */
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String ACTION_SCO_AUDIO_STATE_UPDATED =
            "android.media.ACTION_SCO_AUDIO_STATE_UPDATED";

    /**
     * Extra for intent {@link #ACTION_SCO_AUDIO_STATE_CHANGED} or
     * {@link #ACTION_SCO_AUDIO_STATE_UPDATED} containing the new bluetooth SCO connection state.
     */
    public static final String EXTRA_SCO_AUDIO_STATE =
            "android.media.extra.SCO_AUDIO_STATE";

    /**
     * Value for extra {@link #EXTRA_SCO_AUDIO_STATE} indicating that the
     * SCO audio channel is not established
     * Extra for intent {@link #ACTION_SCO_AUDIO_STATE_UPDATED} containing the previous
     * bluetooth SCO connection state.
     */
    public static final String EXTRA_SCO_AUDIO_PREVIOUS_STATE =
            "android.media.extra.SCO_AUDIO_PREVIOUS_STATE";

    /**
     * Value for extra EXTRA_SCO_AUDIO_STATE or EXTRA_SCO_AUDIO_PREVIOUS_STATE
     * indicating that the SCO audio channel is not established
     */
    public static final int SCO_AUDIO_STATE_DISCONNECTED = 0;
    /**
     * Value for extra {@link #EXTRA_SCO_AUDIO_STATE} indicating that the
     * SCO audio channel is established
     * Value for extra {@link #EXTRA_SCO_AUDIO_STATE} or {@link #EXTRA_SCO_AUDIO_PREVIOUS_STATE}
     * indicating that the SCO audio channel is established
     */
    public static final int SCO_AUDIO_STATE_CONNECTED = 1;
    /**
     * Value for extra {@link #EXTRA_SCO_AUDIO_STATE} indicating that
     * Value for extra EXTRA_SCO_AUDIO_STATE or EXTRA_SCO_AUDIO_PREVIOUS_STATE
     * indicating that the SCO audio channel is being established
     */
    public static final int SCO_AUDIO_STATE_CONNECTING = 2;
    /**
     * Value for extra EXTRA_SCO_AUDIO_STATE indicating that
     * there was an error trying to obtain the state
     */
    public static final int SCO_AUDIO_STATE_ERROR = -1;
@@ -878,29 +913,37 @@ public class AudioManager {
     * to/from a bluetooth SCO headset while the phone is not in call.
     * <p>As the SCO connection establishment can take several seconds,
     * applications should not rely on the connection to be available when the method
     * returns but instead register to receive the intent {@link #ACTION_SCO_AUDIO_STATE_CHANGED}
     * returns but instead register to receive the intent {@link #ACTION_SCO_AUDIO_STATE_UPDATED}
     * and wait for the state to be {@link #SCO_AUDIO_STATE_CONNECTED}.
     * <p>As the connection is not guaranteed to succeed, applications must wait for this intent with
     * a timeout.
     * <p>When finished with the SCO connection or if the establishment times out,
     * the application must call {@link #stopBluetoothSco()} to clear the request and turn
     * down the bluetooth connection.
     * <p>As the ACTION_SCO_AUDIO_STATE_UPDATED intent is sticky, the application can check the SCO
     * audio state before calling startBluetoothSco() by reading the intent returned by the receiver
     * registration. If the state is already CONNECTED, no state change will be received via the
     * intent after calling startBluetoothSco(). It is however useful to call startBluetoothSco()
     * so that the connection stays active in case the current initiator stops the connection.
     * <p>Unless the connection is already active as described above, the state will always
     * transition from DISCONNECTED to CONNECTING and then either to CONNECTED if the connection
     * succeeds or back to DISCONNECTED if the connection fails (e.g no headset is connected).
     * <p>When finished with the SCO connection or if the establishment fails, the application must
     * call {@link #stopBluetoothSco()} to clear the request and turn down the bluetooth connection.
     * <p>Even if a SCO connection is established, the following restrictions apply on audio
     * output streams so that they can be routed to SCO headset:
     * - the stream type must be {@link #STREAM_VOICE_CALL}
     * - the format must be mono
     * - the sampling must be 16kHz or 8kHz
     * <ul>
     *   <li> the stream type must be {@link #STREAM_VOICE_CALL} </li>
     *   <li> the format must be mono </li>
     *   <li> the sampling must be 16kHz or 8kHz </li>
     * </ul>
     * <p>The following restrictions apply on input streams:
     * - the format must be mono
     * - the sampling must be 8kHz
     *
     * <ul>
     *   <li> the format must be mono </li>
     *   <li> the sampling must be 8kHz </li>
     * </ul>
     * <p>Note that the phone application always has the priority on the usage of the SCO
     * connection for telephony. If this method is called while the phone is in call
     * it will be ignored. Similarly, if a call is received or sent while an application
     * is using the SCO connection, the connection will be lost for the application and NOT
     * returned automatically when the call ends.
     * @see #stopBluetoothSco()
     * @see #ACTION_SCO_AUDIO_STATE_CHANGED
     * @see #ACTION_SCO_AUDIO_STATE_UPDATED
     */
    public void startBluetoothSco(){
        IAudioService service = getService();
@@ -917,7 +960,7 @@ public class AudioManager {
     *   {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}.
     * <p>This method must be called by applications having requested the use of
     * bluetooth SCO audio with {@link #startBluetoothSco()}
     * when finished with the SCO connection or if the establishment times out.
     * when finished with the SCO connection or if connection fails.
     * @see #startBluetoothSco()
     */
    public void stopBluetoothSco(){
+194 −68

File changed.

Preview size limit exceeded, changes collapsed.