package android.telecom;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
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;
public final class CallAudioState implements Parcelable {
@Retention(RetentionPolicy.SOURCE)
@IntDef(value={ROUTE_EARPIECE, ROUTE_BLUETOOTH, ROUTE_WIRED_HEADSET, ROUTE_SPEAKER},
flag=true)
public @interface CallAudioRoute {}
public static final int ROUTE_EARPIECE = 0x00000001;
public static final int ROUTE_BLUETOOTH = 0x00000002;
public static final int ROUTE_WIRED_HEADSET = 0x00000004;
public static final int ROUTE_SPEAKER = 0x00000008;
public static final int ROUTE_WIRED_OR_EARPIECE = ROUTE_EARPIECE | ROUTE_WIRED_HEADSET;
public static final int ROUTE_ALL = ROUTE_EARPIECE | ROUTE_BLUETOOTH | ROUTE_WIRED_HEADSET |
ROUTE_SPEAKER;
private final boolean isMuted;
private final int route;
private final int supportedRouteMask;
private final BluetoothDevice activeBluetoothDevice;
private final Collection<BluetoothDevice> supportedBluetoothDevices;
public CallAudioState(boolean muted, @CallAudioRoute int route,
@CallAudioRoute int supportedRouteMask) {
this(muted, route, supportedRouteMask, null, Collections.emptyList());
}
@TestApi
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;
}
public CallAudioState(CallAudioState state) {
isMuted = state.isMuted();
route = state.getRoute();
supportedRouteMask = state.getSupportedRouteMask();
activeBluetoothDevice = state.activeBluetoothDevice;
supportedBluetoothDevices = state.getSupportedBluetoothDevices();
}
@SuppressWarnings("deprecation")
public CallAudioState(AudioState state) {
isMuted = state.isMuted();
route = state.getRoute();
supportedRouteMask = state.getSupportedRouteMask();
activeBluetoothDevice = null;
supportedBluetoothDevices = Collections.emptyList();
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (!(obj instanceof CallAudioState)) {
return false;
}
CallAudioState state = (CallAudioState) obj;
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, " +
"activeBluetoothDevice: [%s], supportedBluetoothDevices: [%s]]",
isMuted,
audioRouteToString(route),
audioRouteToString(supportedRouteMask),
activeBluetoothDevice,
bluetoothDeviceList);
}
public boolean isMuted() {
return isMuted;
}
@CallAudioRoute
public int getRoute() {
return route;
}
@CallAudioRoute
public int getSupportedRouteMask() {
return supportedRouteMask;
}
public BluetoothDevice getActiveBluetoothDevice() {
return activeBluetoothDevice;
}
public Collection<BluetoothDevice> getSupportedBluetoothDevices() {
return supportedBluetoothDevices;
}
public static String audioRouteToString(int route) {
if (route == 0 || (route & ~ROUTE_ALL) != 0x0) {
return "UNKNOWN";
}
StringBuffer buffer = new StringBuffer();
if ((route & ROUTE_EARPIECE) == ROUTE_EARPIECE) {
listAppend(buffer, "EARPIECE");
}
if ((route & ROUTE_BLUETOOTH) == ROUTE_BLUETOOTH) {
listAppend(buffer, "BLUETOOTH");
}
if ((route & ROUTE_WIRED_HEADSET) == ROUTE_WIRED_HEADSET) {
listAppend(buffer, "WIRED_HEADSET");
}
if ((route & ROUTE_SPEAKER) == ROUTE_SPEAKER) {
listAppend(buffer, "SPEAKER");
}
return buffer.toString();
}
public static final Parcelable.Creator<CallAudioState> CREATOR =
new Parcelable.Creator<CallAudioState> () {
@Override
public CallAudioState createFromParcel(Parcel source) {
boolean isMuted = source.readByte() == 0 ? false : true;
int route = source.readInt();
int supportedRouteMask = source.readInt();
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
public CallAudioState[] newArray(int size) {
return new CallAudioState[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel destination, int flags) {
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) {
if (buffer.length() > 0) {
buffer.append(", ");
}
buffer.append(str);
}
}