Merge "Implement CallEndpoint representation and related APIs"
This commit is contained in:
@@ -41015,6 +41015,36 @@ package android.telecom {
|
||||
field public static final int ROUTE_WIRED_OR_EARPIECE = 5; // 0x5
|
||||
}
|
||||
|
||||
public final class CallEndpoint implements android.os.Parcelable {
|
||||
ctor public CallEndpoint(@NonNull CharSequence, int, @NonNull android.os.ParcelUuid);
|
||||
method public int describeContents();
|
||||
method @NonNull public CharSequence getEndpointName();
|
||||
method public int getEndpointType();
|
||||
method @NonNull public android.os.ParcelUuid getIdentifier();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.telecom.CallEndpoint> CREATOR;
|
||||
field public static final int TYPE_BLUETOOTH = 2; // 0x2
|
||||
field public static final int TYPE_EARPIECE = 1; // 0x1
|
||||
field public static final int TYPE_SPEAKER = 4; // 0x4
|
||||
field public static final int TYPE_STREAMING = 5; // 0x5
|
||||
field public static final int TYPE_UNKNOWN = -1; // 0xffffffff
|
||||
field public static final int TYPE_WIRED_HEADSET = 3; // 0x3
|
||||
}
|
||||
|
||||
public final class CallEndpointException extends java.lang.RuntimeException implements android.os.Parcelable {
|
||||
ctor public CallEndpointException(@Nullable String);
|
||||
ctor public CallEndpointException(@Nullable String, int);
|
||||
ctor public CallEndpointException(@Nullable String, int, @Nullable Throwable);
|
||||
method public int describeContents();
|
||||
method public int getCode();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.telecom.CallEndpointException> CREATOR;
|
||||
field public static final int ERROR_ANOTHER_REQUEST = 3; // 0x3
|
||||
field public static final int ERROR_ENDPOINT_DOES_NOT_EXIST = 1; // 0x1
|
||||
field public static final int ERROR_REQUEST_TIME_OUT = 2; // 0x2
|
||||
field public static final int ERROR_UNSPECIFIED = 4; // 0x4
|
||||
}
|
||||
|
||||
public abstract class CallRedirectionService extends android.app.Service {
|
||||
ctor public CallRedirectionService();
|
||||
method public final void cancelCall();
|
||||
@@ -41064,13 +41094,14 @@ package android.telecom {
|
||||
method public final boolean addConnection(android.telecom.Connection);
|
||||
method @NonNull public static android.telecom.Conference createFailedConference(@NonNull android.telecom.DisconnectCause, @NonNull android.telecom.PhoneAccountHandle);
|
||||
method public final void destroy();
|
||||
method public final android.telecom.CallAudioState getCallAudioState();
|
||||
method @Deprecated public final android.telecom.CallAudioState getCallAudioState();
|
||||
method public final java.util.List<android.telecom.Connection> getConferenceableConnections();
|
||||
method public final int getConnectionCapabilities();
|
||||
method public final int getConnectionProperties();
|
||||
method public final long getConnectionStartElapsedRealtimeMillis();
|
||||
method @IntRange(from=0) public final long getConnectionTime();
|
||||
method public final java.util.List<android.telecom.Connection> getConnections();
|
||||
method @NonNull public final android.telecom.CallEndpoint getCurrentCallEndpoint();
|
||||
method public final android.telecom.DisconnectCause getDisconnectCause();
|
||||
method public final android.os.Bundle getExtras();
|
||||
method public final android.telecom.PhoneAccountHandle getPhoneAccountHandle();
|
||||
@@ -41081,13 +41112,16 @@ package android.telecom {
|
||||
method public final boolean isRingbackRequested();
|
||||
method public void onAddConferenceParticipants(@NonNull java.util.List<android.net.Uri>);
|
||||
method public void onAnswer(int);
|
||||
method public void onCallAudioStateChanged(android.telecom.CallAudioState);
|
||||
method public void onAvailableCallEndpointsChanged(@NonNull java.util.List<android.telecom.CallEndpoint>);
|
||||
method @Deprecated public void onCallAudioStateChanged(android.telecom.CallAudioState);
|
||||
method public void onCallEndpointChanged(@NonNull android.telecom.CallEndpoint);
|
||||
method public void onConnectionAdded(android.telecom.Connection);
|
||||
method public void onDisconnect();
|
||||
method public void onExtrasChanged(android.os.Bundle);
|
||||
method public void onHold();
|
||||
method public void onMerge(android.telecom.Connection);
|
||||
method public void onMerge();
|
||||
method public void onMuteStateChanged(boolean);
|
||||
method public void onPlayDtmfTone(char);
|
||||
method public void onReject();
|
||||
method public void onSeparate(android.telecom.Connection);
|
||||
@@ -41130,7 +41164,7 @@ package android.telecom {
|
||||
method public final android.net.Uri getAddress();
|
||||
method public final int getAddressPresentation();
|
||||
method public final boolean getAudioModeIsVoip();
|
||||
method public final android.telecom.CallAudioState getCallAudioState();
|
||||
method @Deprecated public final android.telecom.CallAudioState getCallAudioState();
|
||||
method public final String getCallerDisplayName();
|
||||
method public final int getCallerDisplayNamePresentation();
|
||||
method public final int getCallerNumberVerificationStatus();
|
||||
@@ -41138,6 +41172,7 @@ package android.telecom {
|
||||
method public final java.util.List<android.telecom.Conferenceable> getConferenceables();
|
||||
method public final int getConnectionCapabilities();
|
||||
method public final int getConnectionProperties();
|
||||
method @NonNull public final android.telecom.CallEndpoint getCurrentCallEndpoint();
|
||||
method public final android.telecom.DisconnectCause getDisconnectCause();
|
||||
method public final android.os.Bundle getExtras();
|
||||
method public final int getState();
|
||||
@@ -41151,13 +41186,16 @@ package android.telecom {
|
||||
method public void onAddConferenceParticipants(@NonNull java.util.List<android.net.Uri>);
|
||||
method public void onAnswer(int);
|
||||
method public void onAnswer();
|
||||
method public void onCallAudioStateChanged(android.telecom.CallAudioState);
|
||||
method public void onAvailableCallEndpointsChanged(@NonNull java.util.List<android.telecom.CallEndpoint>);
|
||||
method @Deprecated public void onCallAudioStateChanged(android.telecom.CallAudioState);
|
||||
method public void onCallEndpointChanged(@NonNull android.telecom.CallEndpoint);
|
||||
method public void onCallEvent(String, android.os.Bundle);
|
||||
method public void onDeflect(android.net.Uri);
|
||||
method public void onDisconnect();
|
||||
method public void onExtrasChanged(android.os.Bundle);
|
||||
method public void onHandoverComplete();
|
||||
method public void onHold();
|
||||
method public void onMuteStateChanged(boolean);
|
||||
method public void onPlayDtmfTone(char);
|
||||
method public void onPostDialContinue(boolean);
|
||||
method public void onPullExternalCall();
|
||||
@@ -41178,7 +41216,8 @@ package android.telecom {
|
||||
method public final void putExtras(@NonNull 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(@NonNull android.bluetooth.BluetoothDevice);
|
||||
method @Deprecated public void requestBluetoothAudio(@NonNull android.bluetooth.BluetoothDevice);
|
||||
method public final void requestCallEndpointChange(@NonNull android.telecom.CallEndpoint, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallEndpointException>);
|
||||
method public void sendConnectionEvent(String, android.os.Bundle);
|
||||
method public final void sendRemoteRttRequest();
|
||||
method public final void sendRttInitiationFailure(int);
|
||||
@@ -41187,7 +41226,7 @@ package android.telecom {
|
||||
method public final void setActive();
|
||||
method public final void setAddress(android.net.Uri, int);
|
||||
method public final void setAudioModeIsVoip(boolean);
|
||||
method public final void setAudioRoute(int);
|
||||
method @Deprecated public final void setAudioRoute(int);
|
||||
method public final void setCallerDisplayName(String, int);
|
||||
method public final void setCallerNumberVerificationStatus(int);
|
||||
method public final void setConferenceableConnections(java.util.List<android.telecom.Connection>);
|
||||
@@ -41439,18 +41478,23 @@ package android.telecom {
|
||||
public abstract class InCallService extends android.app.Service {
|
||||
ctor public InCallService();
|
||||
method public final boolean canAddCall();
|
||||
method public final android.telecom.CallAudioState getCallAudioState();
|
||||
method @Deprecated public final android.telecom.CallAudioState getCallAudioState();
|
||||
method public final java.util.List<android.telecom.Call> getCalls();
|
||||
method @NonNull public final android.telecom.CallEndpoint getCurrentCallEndpoint();
|
||||
method public void onAvailableCallEndpointsChanged(@NonNull java.util.List<android.telecom.CallEndpoint>);
|
||||
method public android.os.IBinder onBind(android.content.Intent);
|
||||
method public void onBringToForeground(boolean);
|
||||
method public void onCallAdded(android.telecom.Call);
|
||||
method public void onCallAudioStateChanged(android.telecom.CallAudioState);
|
||||
method @Deprecated public void onCallAudioStateChanged(android.telecom.CallAudioState);
|
||||
method public void onCallEndpointChanged(@NonNull android.telecom.CallEndpoint);
|
||||
method public void onCallRemoved(android.telecom.Call);
|
||||
method public void onCanAddCallChanged(boolean);
|
||||
method public void onConnectionEvent(android.telecom.Call, String, android.os.Bundle);
|
||||
method public void onMuteStateChanged(boolean);
|
||||
method public void onSilenceRinger();
|
||||
method public final void requestBluetoothAudio(@NonNull android.bluetooth.BluetoothDevice);
|
||||
method public final void setAudioRoute(int);
|
||||
method @Deprecated public final void requestBluetoothAudio(@NonNull android.bluetooth.BluetoothDevice);
|
||||
method public final void requestCallEndpointChange(@NonNull android.telecom.CallEndpoint, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallEndpointException>);
|
||||
method @Deprecated public final void setAudioRoute(int);
|
||||
method public final void setMuted(boolean);
|
||||
field public static final String SERVICE_INTERFACE = "android.telecom.InCallService";
|
||||
}
|
||||
|
||||
22
telecomm/java/android/telecom/CallEndpoint.aidl
Normal file
22
telecomm/java/android/telecom/CallEndpoint.aidl
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2022, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.telecom;
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
parcelable CallEndpoint;
|
||||
222
telecomm/java/android/telecom/CallEndpoint.java
Normal file
222
telecomm/java/android/telecom/CallEndpoint.java
Normal file
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.telecom;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.os.Parcel;
|
||||
import android.os.ParcelUuid;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Encapsulates the endpoint where call media can flow
|
||||
*/
|
||||
public final class CallEndpoint implements Parcelable {
|
||||
/** @hide */
|
||||
public static final int ENDPOINT_OPERATION_SUCCESS = 0;
|
||||
/** @hide */
|
||||
public static final int ENDPOINT_OPERATION_FAILED = 1;
|
||||
|
||||
/** @hide */
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({TYPE_UNKNOWN, TYPE_EARPIECE, TYPE_BLUETOOTH, TYPE_WIRED_HEADSET, TYPE_SPEAKER,
|
||||
TYPE_STREAMING})
|
||||
public @interface EndpointType {}
|
||||
|
||||
/** Indicates that the type of endpoint through which call media flows is unknown type. */
|
||||
public static final int TYPE_UNKNOWN = -1;
|
||||
|
||||
/** Indicates that the type of endpoint through which call media flows is an earpiece. */
|
||||
public static final int TYPE_EARPIECE = 1;
|
||||
|
||||
/** Indicates that the type of endpoint through which call media flows is a Bluetooth. */
|
||||
public static final int TYPE_BLUETOOTH = 2;
|
||||
|
||||
/** Indicates that the type of endpoint through which call media flows is a wired headset. */
|
||||
public static final int TYPE_WIRED_HEADSET = 3;
|
||||
|
||||
/** Indicates that the type of endpoint through which call media flows is a speakerphone. */
|
||||
public static final int TYPE_SPEAKER = 4;
|
||||
|
||||
/** Indicates that the type of endpoint through which call media flows is an external. */
|
||||
public static final int TYPE_STREAMING = 5;
|
||||
|
||||
private final CharSequence mName;
|
||||
private final int mType;
|
||||
private final ParcelUuid mIdentifier;
|
||||
|
||||
/**
|
||||
* Constructor for a {@link CallEndpoint} object.
|
||||
*
|
||||
* @param name Human-readable name associated with the endpoint
|
||||
* @param type The type of endpoint through which call media being routed
|
||||
* Allowed values:
|
||||
* {@link #TYPE_EARPIECE}
|
||||
* {@link #TYPE_BLUETOOTH}
|
||||
* {@link #TYPE_WIRED_HEADSET}
|
||||
* {@link #TYPE_SPEAKER}
|
||||
* {@link #TYPE_STREAMING}
|
||||
* {@link #TYPE_UNKNOWN}
|
||||
* @param id A unique identifier for this endpoint on the device
|
||||
*/
|
||||
public CallEndpoint(@NonNull CharSequence name, @EndpointType int type,
|
||||
@NonNull ParcelUuid id) {
|
||||
this.mName = name;
|
||||
this.mType = type;
|
||||
this.mIdentifier = id;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public CallEndpoint(@NonNull CharSequence name, @EndpointType int type) {
|
||||
this(name, type, new ParcelUuid(UUID.randomUUID()));
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public CallEndpoint(CallEndpoint endpoint) {
|
||||
mName = endpoint.getEndpointName();
|
||||
mType = endpoint.getEndpointType();
|
||||
mIdentifier = endpoint.getIdentifier();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(obj instanceof CallEndpoint)) {
|
||||
return false;
|
||||
}
|
||||
CallEndpoint endpoint = (CallEndpoint) obj;
|
||||
return getEndpointName().toString().contentEquals(endpoint.getEndpointName())
|
||||
&& getEndpointType() == endpoint.getEndpointType()
|
||||
&& getIdentifier().equals(endpoint.getIdentifier());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mName, mType, mIdentifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return TextUtils.formatSimple("[CallEndpoint Name: %s, Type: %s, Identifier: %s]",
|
||||
mName.toString(), endpointTypeToString(mType), mIdentifier.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Human-readable name associated with the endpoint
|
||||
*/
|
||||
@NonNull
|
||||
public CharSequence getEndpointName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The type of endpoint through which call media being routed
|
||||
*/
|
||||
@EndpointType
|
||||
public int getEndpointType() {
|
||||
return mType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A unique identifier for this endpoint on the device
|
||||
*/
|
||||
@NonNull
|
||||
public ParcelUuid getIdentifier() {
|
||||
return mIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the provided endpoint type into a human-readable string representation.
|
||||
*
|
||||
* @param endpointType to convert into a string.
|
||||
* @return String representation of the provided endpoint type.
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
public static String endpointTypeToString(int endpointType) {
|
||||
switch (endpointType) {
|
||||
case TYPE_EARPIECE:
|
||||
return "EARPIECE";
|
||||
case TYPE_BLUETOOTH:
|
||||
return "BLUETOOTH";
|
||||
case TYPE_WIRED_HEADSET:
|
||||
return "WIRED_HEADSET";
|
||||
case TYPE_SPEAKER:
|
||||
return "SPEAKER";
|
||||
case TYPE_STREAMING:
|
||||
return "EXTERNAL";
|
||||
default:
|
||||
return "UNKNOWN (" + endpointType + ")";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Responsible for creating CallEndpoint objects for deserialized Parcels.
|
||||
*/
|
||||
public static final @android.annotation.NonNull Parcelable.Creator<CallEndpoint> CREATOR =
|
||||
new Parcelable.Creator<CallEndpoint>() {
|
||||
|
||||
@Override
|
||||
public CallEndpoint createFromParcel(Parcel source) {
|
||||
CharSequence name = source.readCharSequence();
|
||||
int type = source.readInt();
|
||||
ParcelUuid id = ParcelUuid.CREATOR.createFromParcel(source);
|
||||
|
||||
return new CallEndpoint(name, type, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CallEndpoint[] newArray(int size) {
|
||||
return new CallEndpoint[size];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel destination, int flags) {
|
||||
destination.writeCharSequence(mName);
|
||||
destination.writeInt(mType);
|
||||
mIdentifier.writeToParcel(destination, flags);
|
||||
}
|
||||
}
|
||||
22
telecomm/java/android/telecom/CallEndpointException.aidl
Normal file
22
telecomm/java/android/telecom/CallEndpointException.aidl
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2022, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.telecom;
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
parcelable CallEndpointException;
|
||||
130
telecomm/java/android/telecom/CallEndpointException.java
Normal file
130
telecomm/java/android/telecom/CallEndpointException.java
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.telecom;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* This class represents a set of exceptions that can occur when requesting a
|
||||
* {@link CallEndpoint} change.
|
||||
*/
|
||||
public final class CallEndpointException extends RuntimeException implements Parcelable {
|
||||
/** @hide */
|
||||
public static final String CHANGE_ERROR = "ChangeErrorKey";
|
||||
|
||||
/**
|
||||
* The operation has failed because requested CallEndpoint does not exist.
|
||||
*/
|
||||
public static final int ERROR_ENDPOINT_DOES_NOT_EXIST = 1;
|
||||
|
||||
/**
|
||||
* The operation was not completed on time.
|
||||
*/
|
||||
public static final int ERROR_REQUEST_TIME_OUT = 2;
|
||||
|
||||
/**
|
||||
* The operation was canceled by another request.
|
||||
*/
|
||||
public static final int ERROR_ANOTHER_REQUEST = 3;
|
||||
|
||||
/**
|
||||
* The operation has failed due to an unknown or unspecified error.
|
||||
*/
|
||||
public static final int ERROR_UNSPECIFIED = 4;
|
||||
|
||||
private int mCode = ERROR_UNSPECIFIED;
|
||||
private final String mMessage;
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeString8(mMessage);
|
||||
dest.writeInt(mCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Responsible for creating CallEndpointException objects for deserialized Parcels.
|
||||
*/
|
||||
public static final @android.annotation.NonNull Parcelable.Creator<CallEndpointException>
|
||||
CREATOR = new Parcelable.Creator<>() {
|
||||
@Override
|
||||
public CallEndpointException createFromParcel(Parcel source) {
|
||||
return new CallEndpointException(source.readString8(), source.readInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CallEndpointException[] newArray(int size) {
|
||||
return new CallEndpointException[size];
|
||||
}
|
||||
};
|
||||
|
||||
/** @hide */
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({ERROR_ENDPOINT_DOES_NOT_EXIST, ERROR_REQUEST_TIME_OUT, ERROR_ANOTHER_REQUEST,
|
||||
ERROR_UNSPECIFIED})
|
||||
public @interface CallEndpointErrorCode {
|
||||
}
|
||||
|
||||
public CallEndpointException(@Nullable String message) {
|
||||
super(getMessage(message, ERROR_UNSPECIFIED));
|
||||
mMessage = message;
|
||||
}
|
||||
|
||||
public CallEndpointException(@Nullable String message, @CallEndpointErrorCode int code) {
|
||||
super(getMessage(message, code));
|
||||
mCode = code;
|
||||
mMessage = message;
|
||||
}
|
||||
|
||||
public CallEndpointException(@Nullable String message, @CallEndpointErrorCode int code,
|
||||
@Nullable Throwable cause) {
|
||||
super(getMessage(message, code), cause);
|
||||
mCode = code;
|
||||
mMessage = message;
|
||||
}
|
||||
|
||||
|
||||
public @CallEndpointErrorCode int getCode() {
|
||||
return mCode;
|
||||
}
|
||||
|
||||
private static String getMessage(String message, int code) {
|
||||
StringBuilder builder;
|
||||
if (!TextUtils.isEmpty(message)) {
|
||||
builder = new StringBuilder(message);
|
||||
builder.append(" (code: ");
|
||||
builder.append(code);
|
||||
builder.append(")");
|
||||
return builder.toString();
|
||||
} else {
|
||||
return "code: " + code;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -88,6 +88,7 @@ public abstract class Conference extends Conferenceable {
|
||||
private String mTelecomCallId;
|
||||
private PhoneAccountHandle mPhoneAccount;
|
||||
private CallAudioState mCallAudioState;
|
||||
private CallEndpoint mCallEndpoint;
|
||||
private int mState = Connection.STATE_NEW;
|
||||
private DisconnectCause mDisconnectCause;
|
||||
private int mConnectionCapabilities;
|
||||
@@ -223,11 +224,25 @@ public abstract class Conference extends Conferenceable {
|
||||
* @return The audio state of the conference, describing how its audio is currently
|
||||
* being routed by the system. This is {@code null} if this Conference
|
||||
* does not directly know about its audio state.
|
||||
* @deprecated Use {@link #getCurrentCallEndpoint()},
|
||||
* {@link #onAvailableCallEndpointsChanged(List)} and
|
||||
* {@link #onMuteStateChanged(boolean)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public final CallAudioState getCallAudioState() {
|
||||
return mCallAudioState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the current CallEndpoint.
|
||||
*
|
||||
* @return An object encapsulating the CallEndpoint.
|
||||
*/
|
||||
@NonNull
|
||||
public final CallEndpoint getCurrentCallEndpoint() {
|
||||
return mCallEndpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns VideoProvider of the primary call. This can be null.
|
||||
*/
|
||||
@@ -314,9 +329,34 @@ public abstract class Conference extends Conferenceable {
|
||||
* value.
|
||||
*
|
||||
* @param state The new call audio state.
|
||||
* @deprecated Use {@link #onCallEndpointChanged(CallEndpoint)},
|
||||
* {@link #onAvailableCallEndpointsChanged(List)} and
|
||||
* {@link #onMuteStateChanged(boolean)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public void onCallAudioStateChanged(CallAudioState state) {}
|
||||
|
||||
/**
|
||||
* Notifies the {@link Conference} that the audio endpoint has been changed.
|
||||
*
|
||||
* @param callEndpoint The new call endpoint.
|
||||
*/
|
||||
public void onCallEndpointChanged(@NonNull CallEndpoint callEndpoint) {}
|
||||
|
||||
/**
|
||||
* Notifies the {@link Conference} that the available call endpoints have been changed.
|
||||
*
|
||||
* @param availableEndpoints The available call endpoints.
|
||||
*/
|
||||
public void onAvailableCallEndpointsChanged(@NonNull List<CallEndpoint> availableEndpoints) {}
|
||||
|
||||
/**
|
||||
* Notifies the {@link Conference} that its audio mute state has been changed.
|
||||
*
|
||||
* @param isMuted The new mute state.
|
||||
*/
|
||||
public void onMuteStateChanged(boolean isMuted) {}
|
||||
|
||||
/**
|
||||
* Notifies the {@link Conference} that a {@link Connection} has been added to it.
|
||||
*
|
||||
@@ -730,6 +770,40 @@ public abstract class Conference extends Conferenceable {
|
||||
onCallAudioStateChanged(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inform this Conference that the audio endpoint has been changed.
|
||||
*
|
||||
* @param endpoint The new call endpoint.
|
||||
* @hide
|
||||
*/
|
||||
final void setCallEndpoint(CallEndpoint endpoint) {
|
||||
Log.d(this, "setCallEndpoint %s", endpoint);
|
||||
mCallEndpoint = endpoint;
|
||||
onCallEndpointChanged(endpoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inform this Conference that the available call endpoints have been changed.
|
||||
*
|
||||
* @param availableEndpoints The available call endpoints.
|
||||
* @hide
|
||||
*/
|
||||
final void setAvailableCallEndpoints(List<CallEndpoint> availableEndpoints) {
|
||||
Log.d(this, "setAvailableCallEndpoints");
|
||||
onAvailableCallEndpointsChanged(availableEndpoints);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inform this Conference that its audio mute state has been changed.
|
||||
*
|
||||
* @param isMuted The new mute state.
|
||||
* @hide
|
||||
*/
|
||||
final void setMuteState(boolean isMuted) {
|
||||
Log.d(this, "setMuteState %s", isMuted);
|
||||
onMuteStateChanged(isMuted);
|
||||
}
|
||||
|
||||
private void setState(int newState) {
|
||||
if (mState != newState) {
|
||||
int oldState = mState;
|
||||
|
||||
@@ -19,6 +19,7 @@ package android.telecom;
|
||||
import static android.Manifest.permission.MODIFY_PHONE_STATE;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.CallbackExecutor;
|
||||
import android.annotation.ElapsedRealtimeLong;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.IntRange;
|
||||
@@ -39,6 +40,7 @@ import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.OutcomeReceiver;
|
||||
import android.os.Parcel;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.Parcelable;
|
||||
@@ -69,6 +71,7 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* Represents a phone call or connection to a remote endpoint that carries voice and/or video
|
||||
@@ -1280,6 +1283,8 @@ public abstract class Connection extends Conferenceable {
|
||||
/** @hide */
|
||||
public void onPhoneAccountChanged(Connection c, PhoneAccountHandle pHandle) {}
|
||||
public void onConnectionTimeReset(Connection c) {}
|
||||
public void onEndpointChanged(Connection c, CallEndpoint endpoint, Executor executor,
|
||||
OutcomeReceiver<Void, CallEndpointException> callback) {}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2162,6 +2167,7 @@ public abstract class Connection extends Conferenceable {
|
||||
private PhoneAccountHandle mPhoneAccountHandle;
|
||||
private int mState = STATE_NEW;
|
||||
private CallAudioState mCallAudioState;
|
||||
private CallEndpoint mCallEndpoint;
|
||||
private Uri mAddress;
|
||||
private int mAddressPresentation;
|
||||
private String mCallerDisplayName;
|
||||
@@ -2290,7 +2296,11 @@ public abstract class Connection extends Conferenceable {
|
||||
* @return The audio state of the connection, describing how its audio is currently
|
||||
* being routed by the system. This is {@code null} if this Connection
|
||||
* does not directly know about its audio state.
|
||||
* @deprecated Use {@link #getCurrentCallEndpoint()},
|
||||
* {@link #onAvailableCallEndpointsChanged(List)} and
|
||||
* {@link #onMuteStateChanged(boolean)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public final CallAudioState getCallAudioState() {
|
||||
return mCallAudioState;
|
||||
}
|
||||
@@ -2456,6 +2466,43 @@ public abstract class Connection extends Conferenceable {
|
||||
onCallAudioStateChanged(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inform this Connection that the audio endpoint has been changed.
|
||||
*
|
||||
* @param endpoint The new call endpoint.
|
||||
* @hide
|
||||
*/
|
||||
final void setCallEndpoint(CallEndpoint endpoint) {
|
||||
checkImmutable();
|
||||
Log.d(this, "setCallEndpoint %s", endpoint);
|
||||
mCallEndpoint = endpoint;
|
||||
onCallEndpointChanged(endpoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inform this Connection that the available call endpoints have been changed.
|
||||
*
|
||||
* @param availableEndpoints The available call endpoints.
|
||||
* @hide
|
||||
*/
|
||||
final void setAvailableCallEndpoints(List<CallEndpoint> availableEndpoints) {
|
||||
checkImmutable();
|
||||
Log.d(this, "setAvailableCallEndpoints");
|
||||
onAvailableCallEndpointsChanged(availableEndpoints);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inform this Connection that its audio mute state has been changed.
|
||||
*
|
||||
* @param isMuted The new mute state.
|
||||
* @hide
|
||||
*/
|
||||
final void setMuteState(boolean isMuted) {
|
||||
checkImmutable();
|
||||
Log.d(this, "setMuteState %s", isMuted);
|
||||
onMuteStateChanged(isMuted);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param state An integer value of a {@code STATE_*} constant.
|
||||
* @return A string representation of the value.
|
||||
@@ -3081,7 +3128,10 @@ public abstract class Connection extends Conferenceable {
|
||||
* @param route The audio route to use (one of {@link CallAudioState#ROUTE_BLUETOOTH},
|
||||
* {@link CallAudioState#ROUTE_EARPIECE}, {@link CallAudioState#ROUTE_SPEAKER}, or
|
||||
* {@link CallAudioState#ROUTE_WIRED_HEADSET}).
|
||||
* @deprecated Use {@link #requestCallEndpointChange(CallEndpoint, Executor, OutcomeReceiver)}
|
||||
* instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public final void setAudioRoute(int route) {
|
||||
for (Listener l : mListeners) {
|
||||
l.onAudioRouteChanged(this, route, null);
|
||||
@@ -3101,7 +3151,10 @@ public abstract class Connection extends Conferenceable {
|
||||
* <p>
|
||||
* See also {@link InCallService#requestBluetoothAudio(BluetoothDevice)}
|
||||
* @param bluetoothDevice The bluetooth device to connect to.
|
||||
* @deprecated Use {@link #requestCallEndpointChange(CallEndpoint, Executor, OutcomeReceiver)}
|
||||
* instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public void requestBluetoothAudio(@NonNull BluetoothDevice bluetoothDevice) {
|
||||
for (Listener l : mListeners) {
|
||||
l.onAudioRouteChanged(this, CallAudioState.ROUTE_BLUETOOTH,
|
||||
@@ -3109,6 +3162,40 @@ public abstract class Connection extends Conferenceable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request audio routing to a specific CallEndpoint. Clients should not define their own
|
||||
* CallEndpoint when requesting a change. Instead, the new endpoint should be one of the valid
|
||||
* endpoints provided by {@link #onAvailableCallEndpointsChanged(List)}.
|
||||
* When this request is honored, there will be change to the {@link #getCurrentCallEndpoint()}.
|
||||
* <p>
|
||||
* Used by self-managed {@link ConnectionService}s which wish to change the CallEndpoint for a
|
||||
* self-managed {@link Connection} (see {@link PhoneAccount#CAPABILITY_SELF_MANAGED}.)
|
||||
* <p>
|
||||
* See also
|
||||
* {@link InCallService#requestCallEndpointChange(CallEndpoint, Executor, OutcomeReceiver)}.
|
||||
*
|
||||
* @param endpoint The call endpoint to use.
|
||||
* @param executor The executor of where the callback will execute.
|
||||
* @param callback The callback to notify the result of the endpoint change.
|
||||
*/
|
||||
public final void requestCallEndpointChange(@NonNull CallEndpoint endpoint,
|
||||
@NonNull @CallbackExecutor Executor executor,
|
||||
@NonNull OutcomeReceiver<Void, CallEndpointException> callback) {
|
||||
for (Listener l : mListeners) {
|
||||
l.onEndpointChanged(this, endpoint, executor, callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the current CallEndpoint.
|
||||
*
|
||||
* @return An object encapsulating the CallEndpoint.
|
||||
*/
|
||||
@NonNull
|
||||
public final CallEndpoint getCurrentCallEndpoint() {
|
||||
return mCallEndpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Informs listeners that a previously requested RTT session via
|
||||
* {@link ConnectionRequest#isRequestingRtt()} or
|
||||
@@ -3160,9 +3247,34 @@ public abstract class Connection extends Conferenceable {
|
||||
* Notifies this Connection that the {@link #getCallAudioState()} property has a new value.
|
||||
*
|
||||
* @param state The new connection audio state.
|
||||
* @deprecated Use {@link #onCallEndpointChanged(CallEndpoint)},
|
||||
* {@link #onAvailableCallEndpointsChanged(List)} and
|
||||
* {@link #onMuteStateChanged(boolean)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public void onCallAudioStateChanged(CallAudioState state) {}
|
||||
|
||||
/**
|
||||
* Notifies this Connection that the audio endpoint has been changed.
|
||||
*
|
||||
* @param callEndpoint The current CallEndpoint.
|
||||
*/
|
||||
public void onCallEndpointChanged(@NonNull CallEndpoint callEndpoint) {}
|
||||
|
||||
/**
|
||||
* Notifies this Connection that the available call endpoints have been changed.
|
||||
*
|
||||
* @param availableEndpoints The set of available CallEndpoint.
|
||||
*/
|
||||
public void onAvailableCallEndpointsChanged(@NonNull List<CallEndpoint> availableEndpoints) {}
|
||||
|
||||
/**
|
||||
* Notifies this Connection that its audio mute state has been changed.
|
||||
*
|
||||
* @param isMuted The current mute state.
|
||||
*/
|
||||
public void onMuteStateChanged(boolean isMuted) {}
|
||||
|
||||
/**
|
||||
* Inform this Connection when it will or will not be tracked by an {@link InCallService} which
|
||||
* can provide an InCall UI.
|
||||
|
||||
@@ -31,6 +31,7 @@ import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.OutcomeReceiver;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.RemoteException;
|
||||
import android.telecom.Logging.Session;
|
||||
@@ -48,6 +49,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* An abstract service that should be implemented by any apps which either:
|
||||
@@ -164,6 +166,9 @@ public abstract class ConnectionService extends Service {
|
||||
private static final String SESSION_CREATE_CONF = "CS.crConf";
|
||||
private static final String SESSION_CREATE_CONF_COMPLETE = "CS.crConfC";
|
||||
private static final String SESSION_CREATE_CONF_FAILED = "CS.crConfF";
|
||||
private static final String SESSION_CALL_ENDPOINT_CHANGED = "CS.oCEC";
|
||||
private static final String SESSION_AVAILABLE_CALL_ENDPOINTS_CHANGED = "CS.oACEC";
|
||||
private static final String SESSION_MUTE_STATE_CHANGED = "CS.oMSC";
|
||||
|
||||
private static final int MSG_ADD_CONNECTION_SERVICE_ADAPTER = 1;
|
||||
private static final int MSG_CREATE_CONNECTION = 2;
|
||||
@@ -208,6 +213,9 @@ public abstract class ConnectionService extends Service {
|
||||
private static final int MSG_ON_CALL_FILTERING_COMPLETED = 42;
|
||||
private static final int MSG_ON_USING_ALTERNATIVE_UI = 43;
|
||||
private static final int MSG_ON_TRACKED_BY_NON_UI_SERVICE = 44;
|
||||
private static final int MSG_ON_CALL_ENDPOINT_CHANGED = 45;
|
||||
private static final int MSG_ON_AVAILABLE_CALL_ENDPOINTS_CHANGED = 46;
|
||||
private static final int MSG_ON_MUTE_STATE_CHANGED = 47;
|
||||
|
||||
private static Connection sNullConnection;
|
||||
|
||||
@@ -591,6 +599,51 @@ public abstract class ConnectionService extends Service {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCallEndpointChanged(String callId, CallEndpoint callEndpoint,
|
||||
Session.Info sessionInfo) {
|
||||
Log.startSession(sessionInfo, SESSION_CALL_ENDPOINT_CHANGED);
|
||||
try {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = callId;
|
||||
args.arg2 = callEndpoint;
|
||||
args.arg3 = Log.createSubsession();
|
||||
mHandler.obtainMessage(MSG_ON_CALL_ENDPOINT_CHANGED, args).sendToTarget();
|
||||
} finally {
|
||||
Log.endSession();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAvailableCallEndpointsChanged(String callId,
|
||||
List<CallEndpoint> availableCallEndpoints, Session.Info sessionInfo) {
|
||||
Log.startSession(sessionInfo, SESSION_AVAILABLE_CALL_ENDPOINTS_CHANGED);
|
||||
try {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = callId;
|
||||
args.arg2 = availableCallEndpoints;
|
||||
args.arg3 = Log.createSubsession();
|
||||
mHandler.obtainMessage(MSG_ON_AVAILABLE_CALL_ENDPOINTS_CHANGED, args)
|
||||
.sendToTarget();
|
||||
} finally {
|
||||
Log.endSession();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMuteStateChanged(String callId, boolean isMuted, Session.Info sessionInfo) {
|
||||
Log.startSession(sessionInfo, SESSION_MUTE_STATE_CHANGED);
|
||||
try {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = callId;
|
||||
args.arg2 = isMuted;
|
||||
args.arg3 = Log.createSubsession();
|
||||
mHandler.obtainMessage(MSG_ON_MUTE_STATE_CHANGED, args).sendToTarget();
|
||||
} finally {
|
||||
Log.endSession();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUsingAlternativeUi(String callId, boolean usingAlternativeUiShowing,
|
||||
Session.Info sessionInfo) {
|
||||
@@ -1527,6 +1580,48 @@ public abstract class ConnectionService extends Service {
|
||||
case MSG_CONNECTION_SERVICE_FOCUS_LOST:
|
||||
onConnectionServiceFocusLost();
|
||||
break;
|
||||
case MSG_ON_CALL_ENDPOINT_CHANGED: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
Log.continueSession((Session) args.arg3,
|
||||
SESSION_HANDLER + SESSION_CALL_AUDIO_SC);
|
||||
try {
|
||||
String callId = (String) args.arg1;
|
||||
CallEndpoint callEndpoint = (CallEndpoint) args.arg2;
|
||||
onCallEndpointChanged(callId, callEndpoint);
|
||||
} finally {
|
||||
args.recycle();
|
||||
Log.endSession();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_ON_AVAILABLE_CALL_ENDPOINTS_CHANGED: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
Log.continueSession((Session) args.arg3,
|
||||
SESSION_HANDLER + SESSION_CALL_AUDIO_SC);
|
||||
try {
|
||||
String callId = (String) args.arg1;
|
||||
List<CallEndpoint> availableCallEndpoints = (List<CallEndpoint>) args.arg2;
|
||||
onAvailableCallEndpointsChanged(callId, availableCallEndpoints);
|
||||
} finally {
|
||||
args.recycle();
|
||||
Log.endSession();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_ON_MUTE_STATE_CHANGED: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
Log.continueSession((Session) args.arg3,
|
||||
SESSION_HANDLER + SESSION_CALL_AUDIO_SC);
|
||||
try {
|
||||
String callId = (String) args.arg1;
|
||||
boolean isMuted = (boolean) args.arg2;
|
||||
onMuteStateChanged(callId, isMuted);
|
||||
} finally {
|
||||
args.recycle();
|
||||
Log.endSession();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1916,6 +2011,15 @@ public abstract class ConnectionService extends Service {
|
||||
mAdapter.resetConnectionTime(id);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEndpointChanged(Connection c, CallEndpoint endpoint, Executor executor,
|
||||
OutcomeReceiver<Void, CallEndpointException> callback) {
|
||||
String id = mIdByConnection.get(c);
|
||||
if (id != null) {
|
||||
mAdapter.requestCallEndpointChange(id, endpoint, executor, callback);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@@ -2313,6 +2417,36 @@ public abstract class ConnectionService extends Service {
|
||||
}
|
||||
}
|
||||
|
||||
private void onCallEndpointChanged(String callId, CallEndpoint callEndpoint) {
|
||||
Log.i(this, "onCallEndpointChanged %s %s", callId, callEndpoint);
|
||||
if (mConnectionById.containsKey(callId)) {
|
||||
findConnectionForAction(callId, "onCallEndpointChanged").setCallEndpoint(callEndpoint);
|
||||
} else {
|
||||
findConferenceForAction(callId, "onCallEndpointChanged").setCallEndpoint(callEndpoint);
|
||||
}
|
||||
}
|
||||
|
||||
private void onAvailableCallEndpointsChanged(String callId,
|
||||
List<CallEndpoint> availableCallEndpoints) {
|
||||
Log.i(this, "onAvailableCallEndpointsChanged %s", callId);
|
||||
if (mConnectionById.containsKey(callId)) {
|
||||
findConnectionForAction(callId, "onAvailableCallEndpointsChanged")
|
||||
.setAvailableCallEndpoints(availableCallEndpoints);
|
||||
} else {
|
||||
findConferenceForAction(callId, "onAvailableCallEndpointsChanged")
|
||||
.setAvailableCallEndpoints(availableCallEndpoints);
|
||||
}
|
||||
}
|
||||
|
||||
private void onMuteStateChanged(String callId, boolean isMuted) {
|
||||
Log.i(this, "onMuteStateChanged %s %s", callId, isMuted);
|
||||
if (mConnectionById.containsKey(callId)) {
|
||||
findConnectionForAction(callId, "onMuteStateChanged").setMuteState(isMuted);
|
||||
} else {
|
||||
findConferenceForAction(callId, "onMuteStateChanged").setMuteState(isMuted);
|
||||
}
|
||||
}
|
||||
|
||||
private void onUsingAlternativeUi(String callId, boolean isUsingAlternativeUi) {
|
||||
Log.i(this, "onUsingAlternativeUi %s %s", callId, isUsingAlternativeUi);
|
||||
if (mConnectionById.containsKey(callId)) {
|
||||
|
||||
@@ -17,9 +17,12 @@
|
||||
package android.telecom;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder.DeathRecipient;
|
||||
import android.os.OutcomeReceiver;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ResultReceiver;
|
||||
|
||||
import com.android.internal.telecom.IConnectionServiceAdapter;
|
||||
import com.android.internal.telecom.RemoteServiceCallback;
|
||||
@@ -29,6 +32,7 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* Provides methods for IConnectionService implementations to interact with the system phone app.
|
||||
@@ -567,6 +571,41 @@ final class ConnectionServiceAdapter implements DeathRecipient {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the call endpoint associated with a {@link Connection}.
|
||||
*
|
||||
* @param callId The unique ID of the call.
|
||||
* @param endpoint The new call endpoint (see {@link CallEndpoint}).
|
||||
* @param executor The executor of where the callback will execute.
|
||||
* @param callback The callback to notify the result of the endpoint change.
|
||||
*/
|
||||
void requestCallEndpointChange(String callId, CallEndpoint endpoint, Executor executor,
|
||||
OutcomeReceiver<Void, CallEndpointException> callback) {
|
||||
Log.v(this, "requestCallEndpointChange");
|
||||
for (IConnectionServiceAdapter adapter : mAdapters) {
|
||||
try {
|
||||
adapter.requestCallEndpointChange(callId, endpoint, new ResultReceiver(null) {
|
||||
@Override
|
||||
protected void onReceiveResult(int resultCode, Bundle result) {
|
||||
super.onReceiveResult(resultCode, result);
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
if (resultCode == CallEndpoint.ENDPOINT_OPERATION_SUCCESS) {
|
||||
executor.execute(() -> callback.onResult(null));
|
||||
} else {
|
||||
executor.execute(() -> callback.onError(result.getParcelable(
|
||||
CallEndpointException.CHANGE_ERROR,
|
||||
CallEndpointException.class)));
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}}, Log.getExternalSession());
|
||||
} catch (RemoteException ignored) {
|
||||
Log.d(this, "Remote exception calling requestCallEndpointChange");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Informs Telecom of a connection level event.
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ResultReceiver;
|
||||
import android.telecom.Logging.Session;
|
||||
|
||||
import com.android.internal.os.SomeArgs;
|
||||
@@ -692,6 +693,12 @@ final class ConnectionServiceAdapterServant {
|
||||
args.arg2 = sessionInfo;
|
||||
mHandler.obtainMessage(MSG_SET_CALL_DIRECTION, args).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestCallEndpointChange(String callId, CallEndpoint endpoint,
|
||||
ResultReceiver callback, Session.Info sessionInfo) {
|
||||
// Do nothing
|
||||
}
|
||||
};
|
||||
|
||||
public ConnectionServiceAdapterServant(IConnectionServiceAdapter delegate) {
|
||||
|
||||
@@ -19,12 +19,16 @@ package android.telecom;
|
||||
import android.annotation.NonNull;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.OutcomeReceiver;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ResultReceiver;
|
||||
|
||||
import com.android.internal.telecom.IInCallAdapter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* Receives commands from {@link InCallService} implementations which should be executed by
|
||||
@@ -226,6 +230,39 @@ public final class InCallAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request audio routing to a specific CallEndpoint.. See {@link CallEndpoint}.
|
||||
*
|
||||
* @param endpoint The call endpoint to use.
|
||||
* @param executor The executor of where the callback will execute.
|
||||
* @param callback The callback to notify the result of the endpoint change.
|
||||
*/
|
||||
public void requestCallEndpointChange(CallEndpoint endpoint, Executor executor,
|
||||
OutcomeReceiver<Void, CallEndpointException> callback) {
|
||||
try {
|
||||
mAdapter.requestCallEndpointChange(endpoint, new ResultReceiver(null) {
|
||||
@Override
|
||||
protected void onReceiveResult(int resultCode, Bundle result) {
|
||||
super.onReceiveResult(resultCode, result);
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
if (resultCode == CallEndpoint.ENDPOINT_OPERATION_SUCCESS) {
|
||||
executor.execute(() -> callback.onResult(null));
|
||||
} else {
|
||||
executor.execute(() -> callback.onError(
|
||||
result.getParcelable(CallEndpointException.CHANGE_ERROR,
|
||||
CallEndpointException.class)));
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (RemoteException e) {
|
||||
Log.d(this, "Remote exception calling requestCallEndpointChange");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs Telecom to play a dual-tone multi-frequency signaling (DTMF) tone in a call.
|
||||
*
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package android.telecom;
|
||||
|
||||
import android.annotation.CallbackExecutor;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.SdkConstant;
|
||||
import android.annotation.SystemApi;
|
||||
@@ -31,6 +32,7 @@ import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.OutcomeReceiver;
|
||||
import android.view.Surface;
|
||||
|
||||
import com.android.internal.os.SomeArgs;
|
||||
@@ -39,6 +41,8 @@ import com.android.internal.telecom.IInCallService;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* This service is implemented by an app that wishes to provide functionality for managing
|
||||
@@ -269,6 +273,11 @@ public abstract class InCallService extends Service {
|
||||
private static final int MSG_ON_RTT_INITIATION_FAILURE = 11;
|
||||
private static final int MSG_ON_HANDOVER_FAILED = 12;
|
||||
private static final int MSG_ON_HANDOVER_COMPLETE = 13;
|
||||
private static final int MSG_ON_CALL_ENDPOINT_CHANGED = 14;
|
||||
private static final int MSG_ON_AVAILABLE_CALL_ENDPOINTS_CHANGED = 15;
|
||||
private static final int MSG_ON_MUTE_STATE_CHANGED = 16;
|
||||
|
||||
private CallEndpoint mCallEndpoint;
|
||||
|
||||
/** Default Handler used to consolidate binder method calls onto a single thread. */
|
||||
private final Handler mHandler = new Handler(Looper.getMainLooper()) {
|
||||
@@ -350,6 +359,23 @@ public abstract class InCallService extends Service {
|
||||
mPhone.internalOnHandoverComplete(callId);
|
||||
break;
|
||||
}
|
||||
case MSG_ON_CALL_ENDPOINT_CHANGED: {
|
||||
CallEndpoint endpoint = (CallEndpoint) msg.obj;
|
||||
if (!Objects.equals(mCallEndpoint, endpoint)) {
|
||||
mCallEndpoint = endpoint;
|
||||
InCallService.this.onCallEndpointChanged(mCallEndpoint);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_ON_AVAILABLE_CALL_ENDPOINTS_CHANGED: {
|
||||
InCallService.this.onAvailableCallEndpointsChanged(
|
||||
(List<CallEndpoint>) msg.obj);
|
||||
break;
|
||||
}
|
||||
case MSG_ON_MUTE_STATE_CHANGED: {
|
||||
InCallService.this.onMuteStateChanged((boolean) msg.obj);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -391,6 +417,22 @@ public abstract class InCallService extends Service {
|
||||
mHandler.obtainMessage(MSG_ON_CALL_AUDIO_STATE_CHANGED, callAudioState).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCallEndpointChanged(CallEndpoint callEndpoint) {
|
||||
mHandler.obtainMessage(MSG_ON_CALL_ENDPOINT_CHANGED, callEndpoint).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAvailableCallEndpointsChanged(List<CallEndpoint> availableEndpoints) {
|
||||
mHandler.obtainMessage(MSG_ON_AVAILABLE_CALL_ENDPOINTS_CHANGED, availableEndpoints)
|
||||
.sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMuteStateChanged(boolean isMuted) {
|
||||
mHandler.obtainMessage(MSG_ON_MUTE_STATE_CHANGED, isMuted).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bringToForeground(boolean showDialpad) {
|
||||
mHandler.obtainMessage(MSG_BRING_TO_FOREGROUND, showDialpad ? 1 : 0, 0).sendToTarget();
|
||||
@@ -559,7 +601,11 @@ public abstract class InCallService extends Service {
|
||||
*
|
||||
* @return An object encapsulating the audio state. Returns null if the service is not
|
||||
* fully initialized.
|
||||
* @deprecated Use {@link #getCurrentCallEndpoint()},
|
||||
* {@link #onAvailableCallEndpointsChanged(List)} and
|
||||
* {@link #onMuteStateChanged(boolean)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public final CallAudioState getCallAudioState() {
|
||||
return mPhone == null ? null : mPhone.getCallAudioState();
|
||||
}
|
||||
@@ -581,7 +627,10 @@ public abstract class InCallService extends Service {
|
||||
* be change to the {@link #getCallAudioState()}.
|
||||
*
|
||||
* @param route The audio route to use.
|
||||
* @deprecated Use {@link #requestCallEndpointChange(CallEndpoint, Executor, OutcomeReceiver)}
|
||||
* instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public final void setAudioRoute(int route) {
|
||||
if (mPhone != null) {
|
||||
mPhone.setAudioRoute(route);
|
||||
@@ -596,13 +645,44 @@ public abstract class InCallService extends Service {
|
||||
* {@link CallAudioState#getSupportedBluetoothDevices()}
|
||||
*
|
||||
* @param bluetoothDevice The bluetooth device to connect to.
|
||||
* @deprecated Use {@link #requestCallEndpointChange(CallEndpoint, Executor, OutcomeReceiver)}
|
||||
* instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public final void requestBluetoothAudio(@NonNull BluetoothDevice bluetoothDevice) {
|
||||
if (mPhone != null) {
|
||||
mPhone.requestBluetoothAudio(bluetoothDevice.getAddress());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request audio routing to a specific CallEndpoint. Clients should not define their own
|
||||
* CallEndpoint when requesting a change. Instead, the new endpoint should be one of the valid
|
||||
* endpoints provided by {@link #onAvailableCallEndpointsChanged(List)}.
|
||||
* When this request is honored, there will be change to the {@link #getCurrentCallEndpoint()}.
|
||||
*
|
||||
* @param endpoint The call endpoint to use.
|
||||
* @param executor The executor of where the callback will execute.
|
||||
* @param callback The callback to notify the result of the endpoint change.
|
||||
*/
|
||||
public final void requestCallEndpointChange(@NonNull CallEndpoint endpoint,
|
||||
@NonNull @CallbackExecutor Executor executor,
|
||||
@NonNull OutcomeReceiver<Void, CallEndpointException> callback) {
|
||||
if (mPhone != null) {
|
||||
mPhone.requestCallEndpointChange(endpoint, executor, callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the current CallEndpoint.
|
||||
*
|
||||
* @return An object encapsulating the CallEndpoint.
|
||||
*/
|
||||
@NonNull
|
||||
public final CallEndpoint getCurrentCallEndpoint() {
|
||||
return mCallEndpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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}
|
||||
@@ -648,10 +728,38 @@ public abstract class InCallService extends Service {
|
||||
* Called when the audio state changes.
|
||||
*
|
||||
* @param audioState The new {@link CallAudioState}.
|
||||
* @deprecated Use {@link #onCallEndpointChanged(CallEndpoint)},
|
||||
* {@link #onAvailableCallEndpointsChanged(List)} and
|
||||
* {@link #onMuteStateChanged(boolean)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public void onCallAudioStateChanged(CallAudioState audioState) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the current CallEndpoint changes.
|
||||
*
|
||||
* @param callEndpoint The current CallEndpoint {@link CallEndpoint}.
|
||||
*/
|
||||
public void onCallEndpointChanged(@NonNull CallEndpoint callEndpoint) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the available CallEndpoint changes.
|
||||
*
|
||||
* @param availableEndpoints The set of available CallEndpoint {@link CallEndpoint}.
|
||||
*/
|
||||
public void onAvailableCallEndpointsChanged(@NonNull List<CallEndpoint> availableEndpoints) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the mute state changes.
|
||||
*
|
||||
* @param isMuted The current mute state.
|
||||
*/
|
||||
public void onMuteStateChanged(boolean isMuted) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to bring the in-call screen to the foreground. The in-call experience should
|
||||
* respond immediately by coming to the foreground to inform the user of the state of
|
||||
|
||||
@@ -16,11 +16,14 @@
|
||||
|
||||
package android.telecom;
|
||||
|
||||
import android.annotation.CallbackExecutor;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.SystemApi;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.OutcomeReceiver;
|
||||
import android.util.ArrayMap;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
@@ -30,6 +33,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* A unified virtual device providing a means of voice (and other) communication on a device.
|
||||
@@ -377,6 +381,21 @@ public final class Phone {
|
||||
mInCallAdapter.requestBluetoothAudio(bluetoothAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Request audio routing to a specific CallEndpoint. When this request is honored, there will
|
||||
* be change to the {@link #getCurrentCallEndpoint()}.
|
||||
*
|
||||
* @param endpoint The call endpoint to use.
|
||||
* @param executor The executor of where the callback will execute.
|
||||
* @param callback The callback to notify the result of the endpoint change.
|
||||
* @hide
|
||||
*/
|
||||
public void requestCallEndpointChange(@NonNull CallEndpoint endpoint,
|
||||
@NonNull @CallbackExecutor Executor executor,
|
||||
@NonNull OutcomeReceiver<Void, CallEndpointException> callback) {
|
||||
mInCallAdapter.requestCallEndpointChange(endpoint, executor, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
@@ -36,12 +36,10 @@ import com.android.internal.telecom.IVideoCallback;
|
||||
import com.android.internal.telecom.IVideoProvider;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* A connection provided to a {@link ConnectionService} by another {@code ConnectionService}
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.IBinder.DeathRecipient;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ResultReceiver;
|
||||
import android.telecom.Logging.Session;
|
||||
|
||||
import com.android.internal.telecom.IConnectionService;
|
||||
@@ -510,6 +511,12 @@ final class RemoteConnectionService {
|
||||
public void setCallDirection(String callId, int direction, Session.Info sessionInfo) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestCallEndpointChange(String callId, CallEndpoint endpoint,
|
||||
ResultReceiver callback, Session.Info sessionInfo) {
|
||||
// Do nothing
|
||||
}
|
||||
};
|
||||
|
||||
private final ConnectionServiceAdapterServant mServant =
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.telecom.CallAudioState;
|
||||
import android.telecom.CallEndpoint;
|
||||
import android.telecom.Connection;
|
||||
import android.telecom.ConnectionRequest;
|
||||
import android.telecom.Logging.Session;
|
||||
@@ -98,6 +99,14 @@ oneway interface IConnectionService {
|
||||
void onCallAudioStateChanged(String activeCallId, in CallAudioState callAudioState,
|
||||
in Session.Info sessionInfo);
|
||||
|
||||
void onCallEndpointChanged(String activeCallId, in CallEndpoint callEndpoint,
|
||||
in Session.Info sessionInfo);
|
||||
|
||||
void onAvailableCallEndpointsChanged(String activeCallId,
|
||||
in List<CallEndpoint> availableCallEndpoints, in Session.Info sessionInfo);
|
||||
|
||||
void onMuteStateChanged(String activeCallId, boolean isMuted, in Session.Info sessionInfo);
|
||||
|
||||
void playDtmfTone(String callId, char digit, in Session.Info sessionInfo);
|
||||
|
||||
void stopDtmfTone(String callId, in Session.Info sessionInfo);
|
||||
|
||||
@@ -19,6 +19,8 @@ package com.android.internal.telecom;
|
||||
import android.app.PendingIntent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.ResultReceiver;
|
||||
import android.telecom.CallEndpoint;
|
||||
import android.telecom.ConnectionRequest;
|
||||
import android.telecom.DisconnectCause;
|
||||
import android.telecom.Logging.Session;
|
||||
@@ -113,6 +115,9 @@ oneway interface IConnectionServiceAdapter {
|
||||
void setAudioRoute(String callId, int audioRoute, String bluetoothAddress,
|
||||
in Session.Info sessionInfo);
|
||||
|
||||
void requestCallEndpointChange(String callId, in CallEndpoint endpoint,
|
||||
in ResultReceiver callback, in Session.Info sessionInfo);
|
||||
|
||||
void onConnectionEvent(String callId, String event, in Bundle extras,
|
||||
in Session.Info sessionInfo);
|
||||
|
||||
|
||||
@@ -18,7 +18,9 @@ package com.android.internal.telecom;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.ResultReceiver;
|
||||
import android.telecom.PhoneAccountHandle;
|
||||
import android.telecom.CallEndpoint;
|
||||
|
||||
/**
|
||||
* Internal remote callback interface for in-call services.
|
||||
@@ -50,6 +52,8 @@ oneway interface IInCallAdapter {
|
||||
|
||||
void setAudioRoute(int route, String bluetoothAddress);
|
||||
|
||||
void requestCallEndpointChange(in CallEndpoint endpoint, in ResultReceiver callback);
|
||||
|
||||
void enterBackgroundAudioProcessing(String callId);
|
||||
|
||||
void exitBackgroundAudioProcessing(String callId, boolean shouldRing);
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.internal.telecom;
|
||||
import android.app.PendingIntent;
|
||||
import android.os.Bundle;
|
||||
import android.telecom.CallAudioState;
|
||||
import android.telecom.CallEndpoint;
|
||||
import android.telecom.ParcelableCall;
|
||||
|
||||
import com.android.internal.telecom.IInCallAdapter;
|
||||
@@ -43,6 +44,12 @@ oneway interface IInCallService {
|
||||
|
||||
void onCallAudioStateChanged(in CallAudioState callAudioState);
|
||||
|
||||
void onCallEndpointChanged(in CallEndpoint callEndpoint);
|
||||
|
||||
void onAvailableCallEndpointsChanged(in List<CallEndpoint> availableCallEndpoints);
|
||||
|
||||
void onMuteStateChanged(boolean isMuted);
|
||||
|
||||
void bringToForeground(boolean showDialpad);
|
||||
|
||||
void onCanAddCallChanged(boolean canAddCall);
|
||||
|
||||
Reference in New Issue
Block a user