Merge "Update Telecom APIs to include multi-hfp"

This commit is contained in:
Hall Liu
2017-11-10 19:49:01 +00:00
committed by Gerrit Code Review
14 changed files with 188 additions and 23 deletions

View File

@@ -38806,7 +38806,9 @@ package android.telecom {
ctor public CallAudioState(boolean, int, int);
method public static java.lang.String audioRouteToString(int);
method public int describeContents();
method public android.bluetooth.BluetoothDevice getActiveBluetoothDevice();
method public int getRoute();
method public java.util.Collection<android.bluetooth.BluetoothDevice> getSupportedBluetoothDevices();
method public int getSupportedRouteMask();
method public boolean isMuted();
method public void writeToParcel(android.os.Parcel, int);
@@ -38938,6 +38940,7 @@ package android.telecom {
method public final void putExtras(android.os.Bundle);
method public final void removeExtras(java.util.List<java.lang.String>);
method public final void removeExtras(java.lang.String...);
method public void requestBluetoothAudio(java.lang.String);
method public void sendConnectionEvent(java.lang.String, android.os.Bundle);
method public final void setActive();
method public final void setAddress(android.net.Uri, int);
@@ -39128,6 +39131,7 @@ package android.telecom {
method public void onCanAddCallChanged(boolean);
method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle);
method public void onSilenceRinger();
method public final void requestBluetoothAudio(java.lang.String);
method public final void setAudioRoute(int);
method public final void setMuted(boolean);
field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.InCallService";

View File

@@ -42045,7 +42045,9 @@ package android.telecom {
ctor public CallAudioState(boolean, int, int);
method public static java.lang.String audioRouteToString(int);
method public int describeContents();
method public android.bluetooth.BluetoothDevice getActiveBluetoothDevice();
method public int getRoute();
method public java.util.Collection<android.bluetooth.BluetoothDevice> getSupportedBluetoothDevices();
method public int getSupportedRouteMask();
method public boolean isMuted();
method public void writeToParcel(android.os.Parcel, int);
@@ -42184,6 +42186,7 @@ package android.telecom {
method public final void putExtras(android.os.Bundle);
method public final void removeExtras(java.util.List<java.lang.String>);
method public final void removeExtras(java.lang.String...);
method public void requestBluetoothAudio(java.lang.String);
method public void sendConnectionEvent(java.lang.String, android.os.Bundle);
method public final void setActive();
method public final void setAddress(android.net.Uri, int);
@@ -42377,6 +42380,7 @@ package android.telecom {
method public deprecated void onPhoneCreated(android.telecom.Phone);
method public deprecated void onPhoneDestroyed(android.telecom.Phone);
method public void onSilenceRinger();
method public final void requestBluetoothAudio(java.lang.String);
method public final void setAudioRoute(int);
method public final void setMuted(boolean);
field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.InCallService";
@@ -42515,6 +42519,7 @@ package android.telecom {
method public final android.telecom.CallAudioState getCallAudioState();
method public final java.util.List<android.telecom.Call> getCalls();
method public final void removeListener(android.telecom.Phone.Listener);
method public void requestBluetoothAudio(java.lang.String);
method public final void setAudioRoute(int);
method public final void setMuted(boolean);
}

View File

@@ -39014,7 +39014,9 @@ package android.telecom {
ctor public CallAudioState(boolean, int, int);
method public static java.lang.String audioRouteToString(int);
method public int describeContents();
method public android.bluetooth.BluetoothDevice getActiveBluetoothDevice();
method public int getRoute();
method public java.util.Collection<android.bluetooth.BluetoothDevice> getSupportedBluetoothDevices();
method public int getSupportedRouteMask();
method public boolean isMuted();
method public void writeToParcel(android.os.Parcel, int);
@@ -39149,6 +39151,7 @@ package android.telecom {
method public final void putExtras(android.os.Bundle);
method public final void removeExtras(java.util.List<java.lang.String>);
method public final void removeExtras(java.lang.String...);
method public void requestBluetoothAudio(java.lang.String);
method public void sendConnectionEvent(java.lang.String, android.os.Bundle);
method public final void sendRemoteRttRequest();
method public final void sendRttInitiationFailure(int);
@@ -39352,6 +39355,7 @@ package android.telecom {
method public void onCanAddCallChanged(boolean);
method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle);
method public void onSilenceRinger();
method public final void requestBluetoothAudio(java.lang.String);
method public final void setAudioRoute(int);
method public final void setMuted(boolean);
field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.InCallService";

View File

@@ -16,16 +16,35 @@
package android.telecom;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.bluetooth.BluetoothDevice;
import android.os.Parcel;
import android.os.Parcelable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* Encapsulates the telecom audio state, including the current audio routing, supported audio
* routing and mute.
*/
public final class CallAudioState implements Parcelable {
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(value={ROUTE_EARPIECE, ROUTE_BLUETOOTH, ROUTE_WIRED_HEADSET, ROUTE_SPEAKER},
flag=true)
public @interface CallAudioRoute {}
/** Direct the audio stream through the device's earpiece. */
public static final int ROUTE_EARPIECE = 0x00000001;
@@ -55,6 +74,8 @@ public final class CallAudioState implements Parcelable {
private final boolean isMuted;
private final int route;
private final int supportedRouteMask;
private final BluetoothDevice activeBluetoothDevice;
private final Collection<BluetoothDevice> supportedBluetoothDevices;
/**
* Constructor for a {@link CallAudioState} object.
@@ -73,10 +94,21 @@ public final class CallAudioState implements Parcelable {
* {@link #ROUTE_WIRED_HEADSET}
* {@link #ROUTE_SPEAKER}
*/
public CallAudioState(boolean muted, int route, int supportedRouteMask) {
this.isMuted = muted;
public CallAudioState(boolean muted, @CallAudioRoute int route,
@CallAudioRoute int supportedRouteMask) {
this(muted, route, supportedRouteMask, null, Collections.emptyList());
}
/** @hide */
public CallAudioState(boolean isMuted, @CallAudioRoute int route,
@CallAudioRoute int supportedRouteMask,
@Nullable BluetoothDevice activeBluetoothDevice,
@NonNull Collection<BluetoothDevice> supportedBluetoothDevices) {
this.isMuted = isMuted;
this.route = route;
this.supportedRouteMask = supportedRouteMask;
this.activeBluetoothDevice = activeBluetoothDevice;
this.supportedBluetoothDevices = supportedBluetoothDevices;
}
/** @hide */
@@ -84,6 +116,8 @@ public final class CallAudioState implements Parcelable {
isMuted = state.isMuted();
route = state.getRoute();
supportedRouteMask = state.getSupportedRouteMask();
activeBluetoothDevice = state.activeBluetoothDevice;
supportedBluetoothDevices = state.getSupportedBluetoothDevices();
}
/** @hide */
@@ -92,6 +126,8 @@ public final class CallAudioState implements Parcelable {
isMuted = state.isMuted();
route = state.getRoute();
supportedRouteMask = state.getSupportedRouteMask();
activeBluetoothDevice = null;
supportedBluetoothDevices = Collections.emptyList();
}
@Override
@@ -103,17 +139,32 @@ public final class CallAudioState implements Parcelable {
return false;
}
CallAudioState state = (CallAudioState) obj;
return isMuted() == state.isMuted() && getRoute() == state.getRoute() &&
getSupportedRouteMask() == state.getSupportedRouteMask();
if (supportedBluetoothDevices.size() != state.supportedBluetoothDevices.size()) {
return false;
}
for (BluetoothDevice device : supportedBluetoothDevices) {
if (!state.supportedBluetoothDevices.contains(device)) {
return false;
}
}
return Objects.equals(activeBluetoothDevice, state.activeBluetoothDevice) && isMuted() ==
state.isMuted() && getRoute() == state.getRoute() && getSupportedRouteMask() ==
state.getSupportedRouteMask();
}
@Override
public String toString() {
String bluetoothDeviceList = supportedBluetoothDevices.stream()
.map(BluetoothDevice::getAddress).collect(Collectors.joining(", "));
return String.format(Locale.US,
"[AudioState isMuted: %b, route: %s, supportedRouteMask: %s]",
"[AudioState isMuted: %b, route: %s, supportedRouteMask: %s, " +
"activeBluetoothDevice: [%s], supportedBluetoothDevices: [%s]]",
isMuted,
audioRouteToString(route),
audioRouteToString(supportedRouteMask));
audioRouteToString(supportedRouteMask),
activeBluetoothDevice,
bluetoothDeviceList);
}
/**
@@ -126,6 +177,7 @@ public final class CallAudioState implements Parcelable {
/**
* @return The current audio route being used.
*/
@CallAudioRoute
public int getRoute() {
return route;
}
@@ -133,10 +185,26 @@ public final class CallAudioState implements Parcelable {
/**
* @return Bit mask of all routes supported by this call.
*/
@CallAudioRoute
public int getSupportedRouteMask() {
return supportedRouteMask;
}
/**
* @return The {@link BluetoothDevice} through which audio is being routed.
* Will not be {@code null} if {@link #getRoute()} returns {@link #ROUTE_BLUETOOTH}.
*/
public BluetoothDevice getActiveBluetoothDevice() {
return activeBluetoothDevice;
}
/**
* @return {@link List} of {@link BluetoothDevice}s that can be used for this call.
*/
public Collection<BluetoothDevice> getSupportedBluetoothDevices() {
return supportedBluetoothDevices;
}
/**
* Converts the provided audio route into a human readable string representation.
*
@@ -177,7 +245,13 @@ public final class CallAudioState implements Parcelable {
boolean isMuted = source.readByte() == 0 ? false : true;
int route = source.readInt();
int supportedRouteMask = source.readInt();
return new CallAudioState(isMuted, route, supportedRouteMask);
BluetoothDevice activeBluetoothDevice = source.readParcelable(
ClassLoader.getSystemClassLoader());
List<BluetoothDevice> supportedBluetoothDevices = new ArrayList<>();
source.readParcelableList(supportedBluetoothDevices,
ClassLoader.getSystemClassLoader());
return new CallAudioState(isMuted, route,
supportedRouteMask, activeBluetoothDevice, supportedBluetoothDevices);
}
@Override
@@ -202,6 +276,8 @@ public final class CallAudioState implements Parcelable {
destination.writeByte((byte) (isMuted ? 1 : 0));
destination.writeInt(route);
destination.writeInt(supportedRouteMask);
destination.writeParcelable(activeBluetoothDevice, 0);
destination.writeParcelableList(new ArrayList<>(supportedBluetoothDevices), 0);
}
private static void listAppend(StringBuffer buffer, String str) {

View File

@@ -25,6 +25,7 @@ import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.app.Notification;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.hardware.camera2.CameraManager;
import android.net.Uri;
@@ -819,7 +820,7 @@ public abstract class Connection extends Conferenceable {
public void onConnectionEvent(Connection c, String event, Bundle extras) {}
/** @hide */
public void onConferenceSupportedChanged(Connection c, boolean isConferenceSupported) {}
public void onAudioRouteChanged(Connection c, int audioRoute) {}
public void onAudioRouteChanged(Connection c, int audioRoute, String bluetoothAddress) {}
public void onRttInitiationSuccess(Connection c) {}
public void onRttInitiationFailure(Connection c, int reason) {}
public void onRttSessionRemotelyTerminated(Connection c) {}
@@ -2576,7 +2577,29 @@ public abstract class Connection extends Conferenceable {
*/
public final void setAudioRoute(int route) {
for (Listener l : mListeners) {
l.onAudioRouteChanged(this, route);
l.onAudioRouteChanged(this, route, null);
}
}
/**
*
* Request audio routing to a specific bluetooth device. Calling this method may result in
* the device routing audio to a different bluetooth device than the one specified if the
* bluetooth stack is unable to route audio to the requested device.
* A list of available devices can be obtained via
* {@link CallAudioState#getSupportedBluetoothDevices()}
*
* <p>
* Used by self-managed {@link ConnectionService}s which wish to use bluetooth audio for a
* self-managed {@link Connection} (see {@link PhoneAccount#CAPABILITY_SELF_MANAGED}.)
* <p>
* See also {@link InCallService#requestBluetoothAudio(String)}
* @param bluetoothAddress The address of the bluetooth device to connect to, as returned by
* {@link BluetoothDevice#getAddress()}.
*/
public void requestBluetoothAudio(@NonNull String bluetoothAddress) {
for (Listener l : mListeners) {
l.onAudioRouteChanged(this, CallAudioState.ROUTE_BLUETOOTH, bluetoothAddress);
}
}

View File

@@ -1294,10 +1294,10 @@ public abstract class ConnectionService extends Service {
}
@Override
public void onAudioRouteChanged(Connection c, int audioRoute) {
public void onAudioRouteChanged(Connection c, int audioRoute, String bluetoothAddress) {
String id = mIdByConnection.get(c);
if (id != null) {
mAdapter.setAudioRoute(id, audioRoute);
mAdapter.setAudioRoute(id, audioRoute, bluetoothAddress);
}
}

View File

@@ -520,11 +520,14 @@ final class ConnectionServiceAdapter implements DeathRecipient {
* @param callId The unique ID of the call.
* @param audioRoute The new audio route (see {@code CallAudioState#ROUTE_*}).
*/
void setAudioRoute(String callId, int audioRoute) {
Log.v(this, "setAudioRoute: %s %s", callId, CallAudioState.audioRouteToString(audioRoute));
void setAudioRoute(String callId, int audioRoute, String bluetoothAddress) {
Log.v(this, "setAudioRoute: %s %s %s", callId,
CallAudioState.audioRouteToString(audioRoute),
bluetoothAddress);
for (IConnectionServiceAdapter adapter : mAdapters) {
try {
adapter.setAudioRoute(callId, audioRoute, Log.getExternalSession());
adapter.setAudioRoute(callId, audioRoute,
bluetoothAddress, Log.getExternalSession());
} catch (RemoteException ignored) {
}
}

View File

@@ -298,8 +298,8 @@ final class ConnectionServiceAdapterServant {
case MSG_SET_AUDIO_ROUTE: {
SomeArgs args = (SomeArgs) msg.obj;
try {
mDelegate.setAudioRoute((String) args.arg1, args.argi1,
(Session.Info) args.arg2);
mDelegate.setAudioRoute((String) args.arg1, args.argi1, (String) args.arg2,
(Session.Info) args.arg3);
} finally {
args.recycle();
}
@@ -548,12 +548,12 @@ final class ConnectionServiceAdapterServant {
@Override
public final void setAudioRoute(String connectionId, int audioRoute,
Session.Info sessionInfo) {
String bluetoothAddress, Session.Info sessionInfo) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = connectionId;
args.argi1 = audioRoute;
args.arg2 = sessionInfo;
args.arg2 = bluetoothAddress;
args.arg3 = sessionInfo;
mHandler.obtainMessage(MSG_SET_AUDIO_ROUTE, args).sendToTarget();
}

View File

@@ -16,6 +16,7 @@
package android.telecom;
import android.bluetooth.BluetoothDevice;
import android.os.Bundle;
import android.os.RemoteException;
@@ -128,7 +129,22 @@ public final class InCallAdapter {
*/
public void setAudioRoute(int route) {
try {
mAdapter.setAudioRoute(route);
mAdapter.setAudioRoute(route, null);
} catch (RemoteException e) {
}
}
/**
* Request audio routing to a specific bluetooth device. Calling this method may result in
* the device routing audio to a different bluetooth device than the one specified. A list of
* available devices can be obtained via {@link CallAudioState#getSupportedBluetoothDevices()}
*
* @param bluetoothAddress The address of the bluetooth device to connect to, as returned by
* {@link BluetoothDevice#getAddress()}, or {@code null} if no device is preferred.
*/
public void requestBluetoothAudio(String bluetoothAddress) {
try {
mAdapter.setAudioRoute(CallAudioState.ROUTE_BLUETOOTH, bluetoothAddress);
} catch (RemoteException e) {
}
}

View File

@@ -16,9 +16,11 @@
package android.telecom;
import android.annotation.NonNull;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
import android.app.Service;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.hardware.camera2.CameraManager;
import android.net.Uri;
@@ -376,6 +378,22 @@ public abstract class InCallService extends Service {
}
}
/**
* Request audio routing to a specific bluetooth device. Calling this method may result in
* the device routing audio to a different bluetooth device than the one specified if the
* bluetooth stack is unable to route audio to the requested device.
* A list of available devices can be obtained via
* {@link CallAudioState#getSupportedBluetoothDevices()}
*
* @param bluetoothAddress The address of the bluetooth device to connect to, as returned by
* {@link BluetoothDevice#getAddress()}.
*/
public final void requestBluetoothAudio(@NonNull String bluetoothAddress) {
if (mPhone != null) {
mPhone.requestBluetoothAudio(bluetoothAddress);
}
}
/**
* Invoked when the {@code Phone} has been created. This is a signal to the in-call experience
* to start displaying in-call information to the user. Each instance of {@code InCallService}

View File

@@ -17,7 +17,9 @@
package android.telecom;
import android.annotation.SystemApi;
import android.bluetooth.BluetoothDevice;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.ArrayMap;
import java.util.Collections;
@@ -294,6 +296,18 @@ public final class Phone {
mInCallAdapter.setAudioRoute(route);
}
/**
* Request audio routing to a specific bluetooth device. Calling this method may result in
* the device routing audio to a different bluetooth device than the one specified. A list of
* available devices can be obtained via {@link CallAudioState#getSupportedBluetoothDevices()}
*
* @param bluetoothAddress The address of the bluetooth device to connect to, as returned by
* {@link BluetoothDevice#getAddress()}, or {@code null} if no device is preferred.
*/
public void requestBluetoothAudio(String bluetoothAddress) {
mInCallAdapter.requestBluetoothAudio(bluetoothAddress);
}
/**
* Turns the proximity sensor on. When this request is made, the proximity sensor will
* become active, and the touch screen and display will be turned off when the user's face

View File

@@ -398,7 +398,8 @@ final class RemoteConnectionService {
}
@Override
public void setAudioRoute(String callId, int audioRoute, Session.Info sessionInfo) {
public void setAudioRoute(String callId, int audioRoute, String bluetoothAddress,
Session.Info sessionInfo) {
if (hasConnection(callId)) {
// TODO(3pcalls): handle this for remote connections.
// Likely we don't want to do anything since it doesn't make sense for self-managed

View File

@@ -103,7 +103,8 @@ oneway interface IConnectionServiceAdapter {
void removeExtras(String callId, in List<String> keys, in Session.Info sessionInfo);
void setAudioRoute(String callId, int audioRoute, in Session.Info sessionInfo);
void setAudioRoute(String callId, int audioRoute, String bluetoothAddress,
in Session.Info sessionInfo);
void onConnectionEvent(String callId, String event, in Bundle extras,
in Session.Info sessionInfo);

View File

@@ -39,7 +39,7 @@ oneway interface IInCallAdapter {
void mute(boolean shouldMute);
void setAudioRoute(int route);
void setAudioRoute(int route, String bluetoothAddress);
void playDtmfTone(String callId, char digit);