372 lines
13 KiB
Java
372 lines
13 KiB
Java
/*
|
|
* 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.FlaggedApi;
|
|
import android.annotation.IntDef;
|
|
import android.annotation.NonNull;
|
|
import android.annotation.Nullable;
|
|
import android.net.Uri;
|
|
import android.os.Parcel;
|
|
import android.os.Parcelable;
|
|
import android.text.TextUtils;
|
|
|
|
import com.android.server.telecom.flags.Flags;
|
|
|
|
import java.lang.annotation.Retention;
|
|
import java.lang.annotation.RetentionPolicy;
|
|
import java.util.Objects;
|
|
|
|
/**
|
|
* CallAttributes represents a set of properties that define a new Call. Apps should build an
|
|
* instance of this class and use {@link TelecomManager#addCall} to start a new call with Telecom.
|
|
*
|
|
* <p>
|
|
* Apps should first register a {@link PhoneAccount} via {@link TelecomManager#registerPhoneAccount}
|
|
* and use the same {@link PhoneAccountHandle} registered with Telecom when creating an
|
|
* instance of CallAttributes.
|
|
*/
|
|
public final class CallAttributes implements Parcelable {
|
|
|
|
/** PhoneAccountHandle associated with the App managing calls **/
|
|
private final PhoneAccountHandle mPhoneAccountHandle;
|
|
|
|
/** Display name of the person on the other end of the call **/
|
|
private final CharSequence mDisplayName;
|
|
|
|
/** Address of the call. Note, this can be extended to a meeting link **/
|
|
private final Uri mAddress;
|
|
|
|
/** The direction (Outgoing/Incoming) of the new Call **/
|
|
@Direction private final int mDirection;
|
|
|
|
/** Information related to data being transmitted (voice, video, etc. ) **/
|
|
@CallType private final int mCallType;
|
|
|
|
/** Allows a package to opt into capabilities on the telecom side, on a per-call basis **/
|
|
@CallCapability private final int mCallCapabilities;
|
|
|
|
/** @hide **/
|
|
public static final String CALL_CAPABILITIES_KEY = "TelecomCapabilities";
|
|
|
|
/** @hide **/
|
|
public static final String DISPLAY_NAME_KEY = "DisplayName";
|
|
|
|
/** @hide **/
|
|
public static final String CALLER_PID_KEY = "CallerPid";
|
|
|
|
/** @hide **/
|
|
public static final String CALLER_UID_KEY = "CallerUid";
|
|
|
|
private CallAttributes(@NonNull PhoneAccountHandle phoneAccountHandle,
|
|
@NonNull CharSequence displayName,
|
|
@NonNull Uri address,
|
|
int direction,
|
|
int callType,
|
|
int callCapabilities) {
|
|
mPhoneAccountHandle = phoneAccountHandle;
|
|
mDisplayName = displayName;
|
|
mAddress = address;
|
|
mDirection = direction;
|
|
mCallType = callType;
|
|
mCallCapabilities = callCapabilities;
|
|
}
|
|
|
|
/** @hide */
|
|
@IntDef(value = {DIRECTION_INCOMING, DIRECTION_OUTGOING})
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
public @interface Direction {
|
|
}
|
|
/**
|
|
* Indicates that the call is an incoming call.
|
|
*/
|
|
public static final int DIRECTION_INCOMING = 1;
|
|
/**
|
|
* Indicates that the call is an outgoing call.
|
|
*/
|
|
public static final int DIRECTION_OUTGOING = 2;
|
|
|
|
/** @hide */
|
|
@IntDef(value = {AUDIO_CALL, VIDEO_CALL})
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
public @interface CallType {
|
|
}
|
|
/**
|
|
* Used when answering or dialing a call to indicate that the call does not have a video
|
|
* component
|
|
*/
|
|
public static final int AUDIO_CALL = 1;
|
|
/**
|
|
* Indicates video transmission is supported
|
|
*/
|
|
public static final int VIDEO_CALL = 2;
|
|
|
|
/** @hide */
|
|
@IntDef(value = {SUPPORTS_SET_INACTIVE, SUPPORTS_STREAM, SUPPORTS_TRANSFER,
|
|
SUPPORTS_VIDEO_CALLING}, flag = true)
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
public @interface CallCapability {
|
|
}
|
|
/**
|
|
* The call being created can be set to inactive (traditionally referred to as hold). This
|
|
* means that once a new call goes active, if the active call needs to be held in order to
|
|
* place or receive an incoming call, the active call will be placed on hold. otherwise, the
|
|
* active call may be disconnected.
|
|
*/
|
|
public static final int SUPPORTS_SET_INACTIVE = 1 << 1;
|
|
/**
|
|
* The call can be streamed from a root device to another device to continue the call without
|
|
* completely transferring it.
|
|
*/
|
|
public static final int SUPPORTS_STREAM = 1 << 2;
|
|
/**
|
|
* The call can be completely transferred from one endpoint to another.
|
|
*/
|
|
public static final int SUPPORTS_TRANSFER = 1 << 3;
|
|
/**
|
|
* The call supports video calling. This allows clients to gate video calling on a per call
|
|
* basis as opposed to re-registering the phone account.
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_TRANSACTIONAL_VIDEO_STATE)
|
|
public static final int SUPPORTS_VIDEO_CALLING = 1 << 4;
|
|
|
|
/**
|
|
* Build an instance of {@link CallAttributes}. In order to build a valid instance, a
|
|
* {@link PhoneAccountHandle}, call direction, display name, and {@link Uri} address
|
|
* are required.
|
|
*
|
|
* <p>
|
|
* Note: Pass in the same {@link PhoneAccountHandle} that was used to register a
|
|
* {@link PhoneAccount} with Telecom. see {@link TelecomManager#registerPhoneAccount}
|
|
*/
|
|
public static final class Builder {
|
|
// required and final fields
|
|
private final PhoneAccountHandle mPhoneAccountHandle;
|
|
@Direction private final int mDirection;
|
|
private final CharSequence mDisplayName;
|
|
private final Uri mAddress;
|
|
// optional fields
|
|
@CallType private int mCallType = CallAttributes.AUDIO_CALL;
|
|
@CallCapability private int mCallCapabilities = SUPPORTS_SET_INACTIVE;
|
|
|
|
/**
|
|
* Constructor for the CallAttributes.Builder class
|
|
*
|
|
* @param phoneAccountHandle that belongs to package registered with Telecom
|
|
* @param callDirection of the new call that will be added to Telecom
|
|
* @param displayName of the caller for incoming calls or initiating user for outgoing calls
|
|
* @param address of the caller for incoming calls or destination for outgoing calls
|
|
*/
|
|
public Builder(@NonNull PhoneAccountHandle phoneAccountHandle,
|
|
@Direction int callDirection, @NonNull CharSequence displayName,
|
|
@NonNull Uri address) {
|
|
if (!isInRange(DIRECTION_INCOMING, DIRECTION_OUTGOING, callDirection)) {
|
|
throw new IllegalArgumentException(TextUtils.formatSimple("CallDirection=[%d] is"
|
|
+ " invalid. CallDirections value should be within [%d, %d]",
|
|
callDirection, DIRECTION_INCOMING, DIRECTION_OUTGOING));
|
|
}
|
|
Objects.requireNonNull(phoneAccountHandle);
|
|
Objects.requireNonNull(displayName);
|
|
Objects.requireNonNull(address);
|
|
mPhoneAccountHandle = phoneAccountHandle;
|
|
mDirection = callDirection;
|
|
mDisplayName = displayName;
|
|
mAddress = address;
|
|
}
|
|
|
|
/**
|
|
* Sets the type of call; uses to indicate if a call is a video call or audio call.
|
|
* @param callType The call type.
|
|
* @return Builder
|
|
*/
|
|
@NonNull
|
|
public Builder setCallType(@CallType int callType) {
|
|
if (!isInRange(AUDIO_CALL, VIDEO_CALL, callType)) {
|
|
throw new IllegalArgumentException(TextUtils.formatSimple("CallType=[%d] is"
|
|
+ " invalid. CallTypes value should be within [%d, %d]",
|
|
callType, AUDIO_CALL, VIDEO_CALL));
|
|
}
|
|
mCallType = callType;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the capabilities of this call. Use this to indicate whether your app supports
|
|
* holding, streaming and call transfers.
|
|
* @param callCapabilities Bitmask of call capabilities.
|
|
* @return Builder
|
|
*/
|
|
@NonNull
|
|
public Builder setCallCapabilities(@CallCapability int callCapabilities) {
|
|
mCallCapabilities = callCapabilities;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Build an instance of {@link CallAttributes} based on the last values passed to the
|
|
* setters or default values.
|
|
*
|
|
* @return an instance of {@link CallAttributes}
|
|
*/
|
|
@NonNull
|
|
public CallAttributes build() {
|
|
return new CallAttributes(mPhoneAccountHandle, mDisplayName, mAddress, mDirection,
|
|
mCallType, mCallCapabilities);
|
|
}
|
|
|
|
/** @hide */
|
|
private boolean isInRange(int floor, int ceiling, int value) {
|
|
return value >= floor && value <= ceiling;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The {@link PhoneAccountHandle} that should be registered to Telecom to allow calls. The
|
|
* {@link PhoneAccountHandle} should be registered before creating a CallAttributes instance.
|
|
*
|
|
* @return the {@link PhoneAccountHandle} for this package that allows this call to be created
|
|
*/
|
|
@NonNull public PhoneAccountHandle getPhoneAccountHandle() {
|
|
return mPhoneAccountHandle;
|
|
}
|
|
|
|
/**
|
|
* @return display name of the incoming caller or the person being called for an outgoing call
|
|
*/
|
|
@NonNull public CharSequence getDisplayName() {
|
|
return mDisplayName;
|
|
}
|
|
|
|
/**
|
|
* @return address of the incoming caller
|
|
* or the address of the person being called for an outgoing call
|
|
*/
|
|
@NonNull public Uri getAddress() {
|
|
return mAddress;
|
|
}
|
|
|
|
/**
|
|
* @return the direction of the new call.
|
|
*/
|
|
public @Direction int getDirection() {
|
|
return mDirection;
|
|
}
|
|
|
|
/**
|
|
* @return Information related to data being transmitted (voice, video, etc. )
|
|
*/
|
|
public @CallType int getCallType() {
|
|
return mCallType;
|
|
}
|
|
|
|
/**
|
|
* @return The allowed capabilities of the new call
|
|
*/
|
|
public @CallCapability int getCallCapabilities() {
|
|
return mCallCapabilities;
|
|
}
|
|
|
|
@Override
|
|
public int describeContents() {
|
|
return 0;
|
|
}
|
|
|
|
@Override
|
|
public void writeToParcel(@Nullable Parcel dest, int flags) {
|
|
dest.writeParcelable(mPhoneAccountHandle, flags);
|
|
dest.writeCharSequence(mDisplayName);
|
|
dest.writeParcelable(mAddress, flags);
|
|
dest.writeInt(mDirection);
|
|
dest.writeInt(mCallType);
|
|
dest.writeInt(mCallCapabilities);
|
|
}
|
|
|
|
/**
|
|
* Responsible for creating CallAttribute objects for deserialized Parcels.
|
|
*/
|
|
public static final @android.annotation.NonNull
|
|
Parcelable.Creator<CallAttributes> CREATOR =
|
|
new Parcelable.Creator<>() {
|
|
@Override
|
|
public CallAttributes createFromParcel(Parcel source) {
|
|
return new CallAttributes(source.readParcelable(getClass().getClassLoader(),
|
|
android.telecom.PhoneAccountHandle.class),
|
|
source.readCharSequence(),
|
|
source.readParcelable(getClass().getClassLoader(),
|
|
android.net.Uri.class),
|
|
source.readInt(),
|
|
source.readInt(),
|
|
source.readInt());
|
|
}
|
|
|
|
@Override
|
|
public CallAttributes[] newArray(int size) {
|
|
return new CallAttributes[size];
|
|
}
|
|
};
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
@Override
|
|
public String toString() {
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
sb.append("{ CallAttributes: [phoneAccountHandle: ")
|
|
.append(mPhoneAccountHandle) /* PhoneAccountHandle#toString handles PII */
|
|
.append("], [contactName: ")
|
|
.append(Log.pii(mDisplayName))
|
|
.append("], [address=")
|
|
.append(Log.pii(mAddress))
|
|
.append("], [direction=")
|
|
.append(mDirection)
|
|
.append("], [callType=")
|
|
.append(mCallType)
|
|
.append("], [mCallCapabilities=")
|
|
.append(mCallCapabilities)
|
|
.append("] }");
|
|
|
|
return sb.toString();
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
@Override
|
|
public boolean equals(Object obj) {
|
|
if (obj == null || obj.getClass() != this.getClass()) {
|
|
return false;
|
|
}
|
|
CallAttributes that = (CallAttributes) obj;
|
|
return this.mDirection == that.mDirection
|
|
&& this.mCallType == that.mCallType
|
|
&& this.mCallCapabilities == that.mCallCapabilities
|
|
&& Objects.equals(this.mPhoneAccountHandle, that.mPhoneAccountHandle)
|
|
&& Objects.equals(this.mAddress, that.mAddress)
|
|
&& Objects.equals(this.mDisplayName, that.mDisplayName);
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
@Override
|
|
public int hashCode() {
|
|
return Objects.hash(mPhoneAccountHandle, mAddress, mDisplayName,
|
|
mDirection, mCallType, mCallCapabilities);
|
|
}
|
|
}
|