|  | /* | 
|  | * Copyright (C) 2014 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.NonNull; | 
|  | import android.annotation.Nullable; | 
|  | import android.annotation.SuppressLint; | 
|  | import android.annotation.SystemApi; | 
|  | import android.annotation.TestApi; | 
|  | import android.net.Uri; | 
|  | import android.os.Bundle; | 
|  | import android.os.Parcel; | 
|  | import android.os.ParcelFileDescriptor; | 
|  | import android.os.Parcelable; | 
|  |  | 
|  | import java.util.ArrayList; | 
|  | import java.util.List; | 
|  |  | 
|  | /** | 
|  | * Simple data container encapsulating a request to some entity to | 
|  | * create a new {@link Connection}. | 
|  | */ | 
|  | public final class ConnectionRequest implements Parcelable { | 
|  |  | 
|  | /** | 
|  | * Builder class for {@link ConnectionRequest} | 
|  | * @hide | 
|  | */ | 
|  | @TestApi // For convenience in CTS tests | 
|  | public static final class Builder { | 
|  | private PhoneAccountHandle mAccountHandle; | 
|  | private Uri mAddress; | 
|  | private Bundle mExtras; | 
|  | private int mVideoState = VideoProfile.STATE_AUDIO_ONLY; | 
|  | private String mTelecomCallId; | 
|  | private boolean mShouldShowIncomingCallUi = false; | 
|  | private ParcelFileDescriptor mRttPipeToInCall; | 
|  | private ParcelFileDescriptor mRttPipeFromInCall; | 
|  | private List<Uri> mParticipants; | 
|  | private boolean mIsAdhocConference = false; | 
|  |  | 
|  | public Builder() { } | 
|  |  | 
|  | /** | 
|  | * Sets the phone account handle for the resulting {@link ConnectionRequest} | 
|  | * @param accountHandle The accountHandle which should be used to place the call. | 
|  | */ | 
|  | public @NonNull Builder setAccountHandle(@NonNull PhoneAccountHandle accountHandle) { | 
|  | this.mAccountHandle = accountHandle; | 
|  | return this; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Sets the participants for the resulting {@link ConnectionRequest} | 
|  | * @param participants The participants to which the {@link Connection} is to connect. | 
|  | */ | 
|  | public @NonNull Builder setParticipants( | 
|  | @SuppressLint("NullableCollection") @Nullable List<Uri> participants) { | 
|  | this.mParticipants = participants; | 
|  | return this; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Sets the address for the resulting {@link ConnectionRequest} | 
|  | * @param address The address(e.g., phone number) to which the {@link Connection} is to | 
|  | *                connect. | 
|  | */ | 
|  | public @NonNull Builder setAddress(@NonNull Uri address) { | 
|  | this.mAddress = address; | 
|  | return this; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Sets the extras bundle for the resulting {@link ConnectionRequest} | 
|  | * @param extras Application-specific extra data. | 
|  | */ | 
|  | public @NonNull Builder setExtras(@NonNull Bundle extras) { | 
|  | this.mExtras = extras; | 
|  | return this; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Sets the video state for the resulting {@link ConnectionRequest} | 
|  | * @param videoState Determines the video state for the connection. | 
|  | */ | 
|  | public @NonNull Builder setVideoState(int videoState) { | 
|  | this.mVideoState = videoState; | 
|  | return this; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Sets the Telecom call ID for the resulting {@link ConnectionRequest} | 
|  | * @param telecomCallId The telecom call ID. | 
|  | */ | 
|  | public @NonNull Builder setTelecomCallId(@NonNull String telecomCallId) { | 
|  | this.mTelecomCallId = telecomCallId; | 
|  | return this; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Sets shouldShowIncomingUi for the resulting {@link ConnectionRequest} | 
|  | * @param shouldShowIncomingCallUi For a self-managed {@link ConnectionService}, will be | 
|  | *                                 {@code true} if the {@link ConnectionService} should show | 
|  | *                                 its own incoming call UI for an incoming call.  When | 
|  | *                                 {@code false}, Telecom shows the incoming call UI. | 
|  | */ | 
|  | public @NonNull Builder setShouldShowIncomingCallUi(boolean shouldShowIncomingCallUi) { | 
|  | this.mShouldShowIncomingCallUi = shouldShowIncomingCallUi; | 
|  | return this; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Sets isAdhocConference for the resulting {@link ConnectionRequest} | 
|  | * @param isAdhocConference {@code true} if it is a adhoc conference call | 
|  | *                          {@code false}, if not a adhoc conference call | 
|  | */ | 
|  | public @NonNull Builder setIsAdhocConferenceCall(boolean isAdhocConference) { | 
|  | this.mIsAdhocConference = isAdhocConference; | 
|  | return this; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Sets the RTT pipe for transferring text into the {@link ConnectionService} for the | 
|  | * resulting {@link ConnectionRequest} | 
|  | * @param rttPipeFromInCall The data pipe to read from. | 
|  | */ | 
|  | public @NonNull Builder setRttPipeFromInCall( | 
|  | @NonNull ParcelFileDescriptor rttPipeFromInCall) { | 
|  | this.mRttPipeFromInCall = rttPipeFromInCall; | 
|  | return this; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Sets the RTT pipe for transferring text out of {@link ConnectionService} for the | 
|  | * resulting {@link ConnectionRequest} | 
|  | * @param rttPipeToInCall The data pipe to write to. | 
|  | */ | 
|  | public @NonNull Builder setRttPipeToInCall(@NonNull ParcelFileDescriptor rttPipeToInCall) { | 
|  | this.mRttPipeToInCall = rttPipeToInCall; | 
|  | return this; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Build the {@link ConnectionRequest} | 
|  | * @return Result of the builder | 
|  | */ | 
|  | public @NonNull ConnectionRequest build() { | 
|  | return new ConnectionRequest( | 
|  | mAccountHandle, | 
|  | mAddress, | 
|  | mExtras, | 
|  | mVideoState, | 
|  | mTelecomCallId, | 
|  | mShouldShowIncomingCallUi, | 
|  | mRttPipeFromInCall, | 
|  | mRttPipeToInCall, | 
|  | mParticipants, | 
|  | mIsAdhocConference); | 
|  | } | 
|  | } | 
|  |  | 
|  | private final PhoneAccountHandle mAccountHandle; | 
|  | private final Uri mAddress; | 
|  | private final Bundle mExtras; | 
|  | private final int mVideoState; | 
|  | private final String mTelecomCallId; | 
|  | private final boolean mShouldShowIncomingCallUi; | 
|  | private final ParcelFileDescriptor mRttPipeToInCall; | 
|  | private final ParcelFileDescriptor mRttPipeFromInCall; | 
|  | // Cached return value of getRttTextStream -- we don't want to wrap it more than once. | 
|  | private Connection.RttTextStream mRttTextStream; | 
|  | private List<Uri> mParticipants; | 
|  | private final boolean mIsAdhocConference; | 
|  |  | 
|  | /** | 
|  | * @param accountHandle The accountHandle which should be used to place the call. | 
|  | * @param handle The handle (e.g., phone number) to which the {@link Connection} is to connect. | 
|  | * @param extras Application-specific extra data. | 
|  | */ | 
|  | public ConnectionRequest( | 
|  | PhoneAccountHandle accountHandle, | 
|  | Uri handle, | 
|  | Bundle extras) { | 
|  | this(accountHandle, handle, extras, VideoProfile.STATE_AUDIO_ONLY, null, false, null, null); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @param accountHandle The accountHandle which should be used to place the call. | 
|  | * @param handle The handle (e.g., phone number) to which the {@link Connection} is to connect. | 
|  | * @param extras Application-specific extra data. | 
|  | * @param videoState Determines the video state for the connection. | 
|  | */ | 
|  | public ConnectionRequest( | 
|  | PhoneAccountHandle accountHandle, | 
|  | Uri handle, | 
|  | Bundle extras, | 
|  | int videoState) { | 
|  | this(accountHandle, handle, extras, videoState, null, false, null, null); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @param accountHandle The accountHandle which should be used to place the call. | 
|  | * @param handle The handle (e.g., phone number) to which the {@link Connection} is to connect. | 
|  | * @param extras Application-specific extra data. | 
|  | * @param videoState Determines the video state for the connection. | 
|  | * @param telecomCallId The telecom call ID. | 
|  | * @param shouldShowIncomingCallUi For a self-managed {@link ConnectionService}, will be | 
|  | *                                 {@code true} if the {@link ConnectionService} should show its | 
|  | *                                 own incoming call UI for an incoming call.  When | 
|  | *                                 {@code false}, Telecom shows the incoming call UI. | 
|  | * @hide | 
|  | */ | 
|  | public ConnectionRequest( | 
|  | PhoneAccountHandle accountHandle, | 
|  | Uri handle, | 
|  | Bundle extras, | 
|  | int videoState, | 
|  | String telecomCallId, | 
|  | boolean shouldShowIncomingCallUi) { | 
|  | this(accountHandle, handle, extras, videoState, telecomCallId, | 
|  | shouldShowIncomingCallUi, null, null); | 
|  | } | 
|  |  | 
|  | private ConnectionRequest( | 
|  | PhoneAccountHandle accountHandle, | 
|  | Uri handle, | 
|  | Bundle extras, | 
|  | int videoState, | 
|  | String telecomCallId, | 
|  | boolean shouldShowIncomingCallUi, | 
|  | ParcelFileDescriptor rttPipeFromInCall, | 
|  | ParcelFileDescriptor rttPipeToInCall) { | 
|  | this(accountHandle, handle, extras, videoState, telecomCallId, | 
|  | shouldShowIncomingCallUi, rttPipeFromInCall, rttPipeToInCall, null, false); | 
|  | } | 
|  |  | 
|  | private ConnectionRequest( | 
|  | PhoneAccountHandle accountHandle, | 
|  | Uri handle, | 
|  | Bundle extras, | 
|  | int videoState, | 
|  | String telecomCallId, | 
|  | boolean shouldShowIncomingCallUi, | 
|  | ParcelFileDescriptor rttPipeFromInCall, | 
|  | ParcelFileDescriptor rttPipeToInCall, | 
|  | List<Uri> participants, | 
|  | boolean isAdhocConference) { | 
|  | mAccountHandle = accountHandle; | 
|  | mAddress = handle; | 
|  | mExtras = extras; | 
|  | mVideoState = videoState; | 
|  | mTelecomCallId = telecomCallId; | 
|  | mShouldShowIncomingCallUi = shouldShowIncomingCallUi; | 
|  | mRttPipeFromInCall = rttPipeFromInCall; | 
|  | mRttPipeToInCall = rttPipeToInCall; | 
|  | mParticipants = participants; | 
|  | mIsAdhocConference = isAdhocConference; | 
|  | } | 
|  |  | 
|  | private ConnectionRequest(Parcel in) { | 
|  | mAccountHandle = in.readParcelable(getClass().getClassLoader(), android.telecom.PhoneAccountHandle.class); | 
|  | mAddress = in.readParcelable(getClass().getClassLoader(), android.net.Uri.class); | 
|  | mExtras = in.readParcelable(getClass().getClassLoader(), android.os.Bundle.class); | 
|  | mVideoState = in.readInt(); | 
|  | mTelecomCallId = in.readString(); | 
|  | mShouldShowIncomingCallUi = in.readInt() == 1; | 
|  | mRttPipeFromInCall = in.readParcelable(getClass().getClassLoader(), android.os.ParcelFileDescriptor.class); | 
|  | mRttPipeToInCall = in.readParcelable(getClass().getClassLoader(), android.os.ParcelFileDescriptor.class); | 
|  |  | 
|  | mParticipants = new ArrayList<Uri>(); | 
|  | in.readList(mParticipants, getClass().getClassLoader(), android.net.Uri.class); | 
|  |  | 
|  | mIsAdhocConference = in.readInt() == 1; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * The account which should be used to place the call. | 
|  | */ | 
|  | public PhoneAccountHandle getAccountHandle() { return mAccountHandle; } | 
|  |  | 
|  | /** | 
|  | * The handle (e.g., phone number) to which the {@link Connection} is to connect. | 
|  | */ | 
|  | public Uri getAddress() { return mAddress; } | 
|  |  | 
|  | /** | 
|  | * The participants to which the {@link Connection} is to connect. | 
|  | */ | 
|  | public @Nullable List<Uri> getParticipants() { return mParticipants; } | 
|  |  | 
|  | /** | 
|  | * Application-specific extra data. Used for passing back information from an incoming | 
|  | * call {@code Intent}, and for any proprietary extensions arranged between a client | 
|  | * and servant {@code ConnectionService} which agree on a vocabulary for such data. | 
|  | */ | 
|  | public Bundle getExtras() { return mExtras; } | 
|  |  | 
|  | /** | 
|  | * Describes the video states supported by the client requesting the connection. | 
|  | * Valid values: {@link VideoProfile#STATE_AUDIO_ONLY}, | 
|  | * {@link VideoProfile#STATE_BIDIRECTIONAL}, | 
|  | * {@link VideoProfile#STATE_TX_ENABLED}, | 
|  | * {@link VideoProfile#STATE_RX_ENABLED}. | 
|  | * | 
|  | * @return The video state for the connection. | 
|  | */ | 
|  | public int getVideoState() { | 
|  | return mVideoState; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the internal Telecom ID associated with the connection request. | 
|  | * | 
|  | * @return The Telecom ID. | 
|  | * @hide | 
|  | */ | 
|  | @SystemApi | 
|  | public @Nullable String getTelecomCallId() { | 
|  | return mTelecomCallId; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * For a self-managed {@link ConnectionService}, indicates for an incoming call whether the | 
|  | * {@link ConnectionService} should show its own incoming call UI for an incoming call. | 
|  | * | 
|  | * @return {@code true} if the {@link ConnectionService} should show its own incoming call UI. | 
|  | * When {@code false}, Telecom shows the incoming call UI for the call. | 
|  | * @hide | 
|  | */ | 
|  | public boolean shouldShowIncomingCallUi() { | 
|  | return mShouldShowIncomingCallUi; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @return {@code true} if the call is a adhoc conference call else @return {@code false} | 
|  | */ | 
|  | public boolean isAdhocConferenceCall() { | 
|  | return mIsAdhocConference; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Gets the {@link ParcelFileDescriptor} that is used to send RTT text from the connection | 
|  | * service to the in-call UI. In order to obtain an | 
|  | * {@link java.io.InputStream} from this {@link ParcelFileDescriptor}, use | 
|  | * {@link android.os.ParcelFileDescriptor.AutoCloseInputStream}. | 
|  | * Only text data encoded using UTF-8 should be written into this {@link ParcelFileDescriptor}. | 
|  | * @return The {@link ParcelFileDescriptor} that should be used for communication. | 
|  | * Do not un-hide -- only for use by Telephony | 
|  | * @hide | 
|  | */ | 
|  | public ParcelFileDescriptor getRttPipeToInCall() { | 
|  | return mRttPipeToInCall; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Gets the {@link ParcelFileDescriptor} that is used to send RTT text from the in-call UI to | 
|  | * the connection service. In order to obtain an | 
|  | * {@link java.io.OutputStream} from this {@link ParcelFileDescriptor}, use | 
|  | * {@link android.os.ParcelFileDescriptor.AutoCloseOutputStream}. | 
|  | * The contents of this {@link ParcelFileDescriptor} will consist solely of text encoded in | 
|  | * UTF-8. | 
|  | * @return The {@link ParcelFileDescriptor} that should be used for communication | 
|  | * Do not un-hide -- only for use by Telephony | 
|  | * @hide | 
|  | */ | 
|  | public ParcelFileDescriptor getRttPipeFromInCall() { | 
|  | return mRttPipeFromInCall; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Gets the {@link android.telecom.Connection.RttTextStream} object that should be used to | 
|  | * send and receive RTT text to/from the in-call app. | 
|  | * @return An instance of {@link android.telecom.Connection.RttTextStream}, or {@code null} | 
|  | * if this connection request is not requesting an RTT session upon connection establishment. | 
|  | */ | 
|  | public Connection.RttTextStream getRttTextStream() { | 
|  | if (isRequestingRtt()) { | 
|  | if (mRttTextStream == null) { | 
|  | mRttTextStream = new Connection.RttTextStream(mRttPipeToInCall, mRttPipeFromInCall); | 
|  | } | 
|  | return mRttTextStream; | 
|  | } else { | 
|  | return null; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Convenience method for determining whether the ConnectionRequest is requesting an RTT session | 
|  | * @return {@code true} if RTT is requested, {@code false} otherwise. | 
|  | */ | 
|  | public boolean isRequestingRtt() { | 
|  | return mRttPipeFromInCall != null && mRttPipeToInCall != null; | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public String toString() { | 
|  | return String.format("ConnectionRequest %s %s isAdhocConf: %s", | 
|  | mAddress == null | 
|  | ? Uri.EMPTY | 
|  | : Connection.toLogSafePhoneNumber(mAddress.toString()), | 
|  | bundleToString(mExtras), | 
|  | isAdhocConferenceCall() ? "Y" : "N"); | 
|  | } | 
|  |  | 
|  | private static String bundleToString(Bundle extras){ | 
|  | if (extras == null) { | 
|  | return ""; | 
|  | } | 
|  | StringBuilder sb = new StringBuilder(); | 
|  | sb.append("Bundle["); | 
|  | for (String key : extras.keySet()) { | 
|  | sb.append(key); | 
|  | sb.append("="); | 
|  | switch (key) { | 
|  | case TelecomManager.EXTRA_INCOMING_CALL_ADDRESS: | 
|  | case TelecomManager.EXTRA_UNKNOWN_CALL_HANDLE: | 
|  | sb.append(Log.pii(extras.get(key))); | 
|  | break; | 
|  | default: | 
|  | sb.append(extras.get(key)); | 
|  | break; | 
|  | } | 
|  | sb.append(", "); | 
|  | } | 
|  | sb.append("]"); | 
|  | return sb.toString(); | 
|  | } | 
|  |  | 
|  | public static final @android.annotation.NonNull Creator<ConnectionRequest> CREATOR = new Creator<ConnectionRequest> () { | 
|  | @Override | 
|  | public ConnectionRequest createFromParcel(Parcel source) { | 
|  | return new ConnectionRequest(source); | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public ConnectionRequest[] newArray(int size) { | 
|  | return new ConnectionRequest[size]; | 
|  | } | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * {@inheritDoc} | 
|  | */ | 
|  | @Override | 
|  | public int describeContents() { | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public void writeToParcel(Parcel destination, int flags) { | 
|  | destination.writeParcelable(mAccountHandle, 0); | 
|  | destination.writeParcelable(mAddress, 0); | 
|  | destination.writeParcelable(mExtras, 0); | 
|  | destination.writeInt(mVideoState); | 
|  | destination.writeString(mTelecomCallId); | 
|  | destination.writeInt(mShouldShowIncomingCallUi ? 1 : 0); | 
|  | destination.writeParcelable(mRttPipeFromInCall, 0); | 
|  | destination.writeParcelable(mRttPipeToInCall, 0); | 
|  | destination.writeList(mParticipants); | 
|  | destination.writeInt(mIsAdhocConference ? 1 : 0); | 
|  | } | 
|  | } |