• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.telecom;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.SuppressLint;
22 import android.annotation.SystemApi;
23 import android.annotation.TestApi;
24 import android.net.Uri;
25 import android.os.Bundle;
26 import android.os.Parcel;
27 import android.os.ParcelFileDescriptor;
28 import android.os.Parcelable;
29 
30 import java.util.ArrayList;
31 import java.util.List;
32 
33 /**
34  * Simple data container encapsulating a request to some entity to
35  * create a new {@link Connection}.
36  */
37 public final class ConnectionRequest implements Parcelable {
38 
39     /**
40      * Builder class for {@link ConnectionRequest}
41      * @hide
42      */
43     @TestApi // For convenience in CTS tests
44     public static final class Builder {
45         private PhoneAccountHandle mAccountHandle;
46         private Uri mAddress;
47         private Bundle mExtras;
48         private int mVideoState = VideoProfile.STATE_AUDIO_ONLY;
49         private String mTelecomCallId;
50         private boolean mShouldShowIncomingCallUi = false;
51         private ParcelFileDescriptor mRttPipeToInCall;
52         private ParcelFileDescriptor mRttPipeFromInCall;
53         private List<Uri> mParticipants;
54         private boolean mIsAdhocConference = false;
55 
Builder()56         public Builder() { }
57 
58         /**
59          * Sets the phone account handle for the resulting {@link ConnectionRequest}
60          * @param accountHandle The accountHandle which should be used to place the call.
61          */
setAccountHandle(@onNull PhoneAccountHandle accountHandle)62         public @NonNull Builder setAccountHandle(@NonNull PhoneAccountHandle accountHandle) {
63             this.mAccountHandle = accountHandle;
64             return this;
65         }
66 
67         /**
68          * Sets the participants for the resulting {@link ConnectionRequest}
69          * @param participants The participants to which the {@link Connection} is to connect.
70          */
setParticipants( @uppressLint"NullableCollection") @ullable List<Uri> participants)71         public @NonNull Builder setParticipants(
72                 @SuppressLint("NullableCollection") @Nullable List<Uri> participants) {
73             this.mParticipants = participants;
74             return this;
75         }
76 
77         /**
78          * Sets the address for the resulting {@link ConnectionRequest}
79          * @param address The address(e.g., phone number) to which the {@link Connection} is to
80          *                connect.
81          */
setAddress(@onNull Uri address)82         public @NonNull Builder setAddress(@NonNull Uri address) {
83             this.mAddress = address;
84             return this;
85         }
86 
87         /**
88          * Sets the extras bundle for the resulting {@link ConnectionRequest}
89          * @param extras Application-specific extra data.
90          */
setExtras(@onNull Bundle extras)91         public @NonNull Builder setExtras(@NonNull Bundle extras) {
92             this.mExtras = extras;
93             return this;
94         }
95 
96         /**
97          * Sets the video state for the resulting {@link ConnectionRequest}
98          * @param videoState Determines the video state for the connection.
99          */
setVideoState(int videoState)100         public @NonNull Builder setVideoState(int videoState) {
101             this.mVideoState = videoState;
102             return this;
103         }
104 
105         /**
106          * Sets the Telecom call ID for the resulting {@link ConnectionRequest}
107          * @param telecomCallId The telecom call ID.
108          */
setTelecomCallId(@onNull String telecomCallId)109         public @NonNull Builder setTelecomCallId(@NonNull String telecomCallId) {
110             this.mTelecomCallId = telecomCallId;
111             return this;
112         }
113 
114         /**
115          * Sets shouldShowIncomingUi for the resulting {@link ConnectionRequest}
116          * @param shouldShowIncomingCallUi For a self-managed {@link ConnectionService}, will be
117          *                                 {@code true} if the {@link ConnectionService} should show
118          *                                 its own incoming call UI for an incoming call.  When
119          *                                 {@code false}, Telecom shows the incoming call UI.
120          */
setShouldShowIncomingCallUi(boolean shouldShowIncomingCallUi)121         public @NonNull Builder setShouldShowIncomingCallUi(boolean shouldShowIncomingCallUi) {
122             this.mShouldShowIncomingCallUi = shouldShowIncomingCallUi;
123             return this;
124         }
125 
126         /**
127          * Sets isAdhocConference for the resulting {@link ConnectionRequest}
128          * @param isAdhocConference {@code true} if it is a adhoc conference call
129          *                          {@code false}, if not a adhoc conference call
130          */
setIsAdhocConferenceCall(boolean isAdhocConference)131         public @NonNull Builder setIsAdhocConferenceCall(boolean isAdhocConference) {
132             this.mIsAdhocConference = isAdhocConference;
133             return this;
134         }
135 
136         /**
137          * Sets the RTT pipe for transferring text into the {@link ConnectionService} for the
138          * resulting {@link ConnectionRequest}
139          * @param rttPipeFromInCall The data pipe to read from.
140          */
setRttPipeFromInCall( @onNull ParcelFileDescriptor rttPipeFromInCall)141         public @NonNull Builder setRttPipeFromInCall(
142                 @NonNull ParcelFileDescriptor rttPipeFromInCall) {
143             this.mRttPipeFromInCall = rttPipeFromInCall;
144             return this;
145         }
146 
147         /**
148          * Sets the RTT pipe for transferring text out of {@link ConnectionService} for the
149          * resulting {@link ConnectionRequest}
150          * @param rttPipeToInCall The data pipe to write to.
151          */
setRttPipeToInCall(@onNull ParcelFileDescriptor rttPipeToInCall)152         public @NonNull Builder setRttPipeToInCall(@NonNull ParcelFileDescriptor rttPipeToInCall) {
153             this.mRttPipeToInCall = rttPipeToInCall;
154             return this;
155         }
156 
157         /**
158          * Build the {@link ConnectionRequest}
159          * @return Result of the builder
160          */
build()161         public @NonNull ConnectionRequest build() {
162             return new ConnectionRequest(
163                     mAccountHandle,
164                     mAddress,
165                     mExtras,
166                     mVideoState,
167                     mTelecomCallId,
168                     mShouldShowIncomingCallUi,
169                     mRttPipeFromInCall,
170                     mRttPipeToInCall,
171                     mParticipants,
172                     mIsAdhocConference);
173         }
174     }
175 
176     private final PhoneAccountHandle mAccountHandle;
177     private final Uri mAddress;
178     private final Bundle mExtras;
179     private final int mVideoState;
180     private final String mTelecomCallId;
181     private final boolean mShouldShowIncomingCallUi;
182     private final ParcelFileDescriptor mRttPipeToInCall;
183     private final ParcelFileDescriptor mRttPipeFromInCall;
184     // Cached return value of getRttTextStream -- we don't want to wrap it more than once.
185     private Connection.RttTextStream mRttTextStream;
186     private List<Uri> mParticipants;
187     private final boolean mIsAdhocConference;
188 
189     /**
190      * @param accountHandle The accountHandle which should be used to place the call.
191      * @param handle The handle (e.g., phone number) to which the {@link Connection} is to connect.
192      * @param extras Application-specific extra data.
193      */
ConnectionRequest( PhoneAccountHandle accountHandle, Uri handle, Bundle extras)194     public ConnectionRequest(
195             PhoneAccountHandle accountHandle,
196             Uri handle,
197             Bundle extras) {
198         this(accountHandle, handle, extras, VideoProfile.STATE_AUDIO_ONLY, null, false, null, null);
199     }
200 
201     /**
202      * @param accountHandle The accountHandle which should be used to place the call.
203      * @param handle The handle (e.g., phone number) to which the {@link Connection} is to connect.
204      * @param extras Application-specific extra data.
205      * @param videoState Determines the video state for the connection.
206      */
ConnectionRequest( PhoneAccountHandle accountHandle, Uri handle, Bundle extras, int videoState)207     public ConnectionRequest(
208             PhoneAccountHandle accountHandle,
209             Uri handle,
210             Bundle extras,
211             int videoState) {
212         this(accountHandle, handle, extras, videoState, null, false, null, null);
213     }
214 
215     /**
216      * @param accountHandle The accountHandle which should be used to place the call.
217      * @param handle The handle (e.g., phone number) to which the {@link Connection} is to connect.
218      * @param extras Application-specific extra data.
219      * @param videoState Determines the video state for the connection.
220      * @param telecomCallId The telecom call ID.
221      * @param shouldShowIncomingCallUi For a self-managed {@link ConnectionService}, will be
222      *                                 {@code true} if the {@link ConnectionService} should show its
223      *                                 own incoming call UI for an incoming call.  When
224      *                                 {@code false}, Telecom shows the incoming call UI.
225      * @hide
226      */
ConnectionRequest( PhoneAccountHandle accountHandle, Uri handle, Bundle extras, int videoState, String telecomCallId, boolean shouldShowIncomingCallUi)227     public ConnectionRequest(
228             PhoneAccountHandle accountHandle,
229             Uri handle,
230             Bundle extras,
231             int videoState,
232             String telecomCallId,
233             boolean shouldShowIncomingCallUi) {
234         this(accountHandle, handle, extras, videoState, telecomCallId,
235                 shouldShowIncomingCallUi, null, null);
236     }
237 
ConnectionRequest( PhoneAccountHandle accountHandle, Uri handle, Bundle extras, int videoState, String telecomCallId, boolean shouldShowIncomingCallUi, ParcelFileDescriptor rttPipeFromInCall, ParcelFileDescriptor rttPipeToInCall)238     private ConnectionRequest(
239             PhoneAccountHandle accountHandle,
240             Uri handle,
241             Bundle extras,
242             int videoState,
243             String telecomCallId,
244             boolean shouldShowIncomingCallUi,
245             ParcelFileDescriptor rttPipeFromInCall,
246             ParcelFileDescriptor rttPipeToInCall) {
247         this(accountHandle, handle, extras, videoState, telecomCallId,
248                 shouldShowIncomingCallUi, rttPipeFromInCall, rttPipeToInCall, null, false);
249     }
250 
ConnectionRequest( PhoneAccountHandle accountHandle, Uri handle, Bundle extras, int videoState, String telecomCallId, boolean shouldShowIncomingCallUi, ParcelFileDescriptor rttPipeFromInCall, ParcelFileDescriptor rttPipeToInCall, List<Uri> participants, boolean isAdhocConference)251     private ConnectionRequest(
252             PhoneAccountHandle accountHandle,
253             Uri handle,
254             Bundle extras,
255             int videoState,
256             String telecomCallId,
257             boolean shouldShowIncomingCallUi,
258             ParcelFileDescriptor rttPipeFromInCall,
259             ParcelFileDescriptor rttPipeToInCall,
260             List<Uri> participants,
261             boolean isAdhocConference) {
262         mAccountHandle = accountHandle;
263         mAddress = handle;
264         mExtras = extras;
265         mVideoState = videoState;
266         mTelecomCallId = telecomCallId;
267         mShouldShowIncomingCallUi = shouldShowIncomingCallUi;
268         mRttPipeFromInCall = rttPipeFromInCall;
269         mRttPipeToInCall = rttPipeToInCall;
270         mParticipants = participants;
271         mIsAdhocConference = isAdhocConference;
272     }
273 
ConnectionRequest(Parcel in)274     private ConnectionRequest(Parcel in) {
275         mAccountHandle = in.readParcelable(getClass().getClassLoader(), android.telecom.PhoneAccountHandle.class);
276         mAddress = in.readParcelable(getClass().getClassLoader(), android.net.Uri.class);
277         mExtras = in.readParcelable(getClass().getClassLoader(), android.os.Bundle.class);
278         mVideoState = in.readInt();
279         mTelecomCallId = in.readString();
280         mShouldShowIncomingCallUi = in.readInt() == 1;
281         mRttPipeFromInCall = in.readParcelable(getClass().getClassLoader(), android.os.ParcelFileDescriptor.class);
282         mRttPipeToInCall = in.readParcelable(getClass().getClassLoader(), android.os.ParcelFileDescriptor.class);
283 
284         mParticipants = new ArrayList<Uri>();
285         in.readList(mParticipants, getClass().getClassLoader(), android.net.Uri.class);
286 
287         mIsAdhocConference = in.readInt() == 1;
288     }
289 
290     /**
291      * The account which should be used to place the call.
292      */
getAccountHandle()293     public PhoneAccountHandle getAccountHandle() { return mAccountHandle; }
294 
295     /**
296      * The handle (e.g., phone number) to which the {@link Connection} is to connect.
297      */
getAddress()298     public Uri getAddress() { return mAddress; }
299 
300     /**
301      * The participants to which the {@link Connection} is to connect.
302      */
getParticipants()303     public @Nullable List<Uri> getParticipants() { return mParticipants; }
304 
305     /**
306      * Application-specific extra data. Used for passing back information from an incoming
307      * call {@code Intent}, and for any proprietary extensions arranged between a client
308      * and servant {@code ConnectionService} which agree on a vocabulary for such data.
309      */
getExtras()310     public Bundle getExtras() { return mExtras; }
311 
312     /**
313      * Describes the video states supported by the client requesting the connection.
314      * Valid values: {@link VideoProfile#STATE_AUDIO_ONLY},
315      * {@link VideoProfile#STATE_BIDIRECTIONAL},
316      * {@link VideoProfile#STATE_TX_ENABLED},
317      * {@link VideoProfile#STATE_RX_ENABLED}.
318      *
319      * @return The video state for the connection.
320      */
getVideoState()321     public int getVideoState() {
322         return mVideoState;
323     }
324 
325     /**
326      * Returns the internal Telecom ID associated with the connection request.
327      *
328      * @return The Telecom ID.
329      * @hide
330      */
331     @SystemApi
getTelecomCallId()332     public @Nullable String getTelecomCallId() {
333         return mTelecomCallId;
334     }
335 
336     /**
337      * For a self-managed {@link ConnectionService}, indicates for an incoming call whether the
338      * {@link ConnectionService} should show its own incoming call UI for an incoming call.
339      *
340      * @return {@code true} if the {@link ConnectionService} should show its own incoming call UI.
341      * When {@code false}, Telecom shows the incoming call UI for the call.
342      * @hide
343      */
shouldShowIncomingCallUi()344     public boolean shouldShowIncomingCallUi() {
345         return mShouldShowIncomingCallUi;
346     }
347 
348     /**
349      * @return {@code true} if the call is a adhoc conference call else @return {@code false}
350      */
isAdhocConferenceCall()351     public boolean isAdhocConferenceCall() {
352         return mIsAdhocConference;
353     }
354 
355     /**
356      * Gets the {@link ParcelFileDescriptor} that is used to send RTT text from the connection
357      * service to the in-call UI. In order to obtain an
358      * {@link java.io.InputStream} from this {@link ParcelFileDescriptor}, use
359      * {@link android.os.ParcelFileDescriptor.AutoCloseInputStream}.
360      * Only text data encoded using UTF-8 should be written into this {@link ParcelFileDescriptor}.
361      * @return The {@link ParcelFileDescriptor} that should be used for communication.
362      * Do not un-hide -- only for use by Telephony
363      * @hide
364      */
getRttPipeToInCall()365     public ParcelFileDescriptor getRttPipeToInCall() {
366         return mRttPipeToInCall;
367     }
368 
369     /**
370      * Gets the {@link ParcelFileDescriptor} that is used to send RTT text from the in-call UI to
371      * the connection service. In order to obtain an
372      * {@link java.io.OutputStream} from this {@link ParcelFileDescriptor}, use
373      * {@link android.os.ParcelFileDescriptor.AutoCloseOutputStream}.
374      * The contents of this {@link ParcelFileDescriptor} will consist solely of text encoded in
375      * UTF-8.
376      * @return The {@link ParcelFileDescriptor} that should be used for communication
377      * Do not un-hide -- only for use by Telephony
378      * @hide
379      */
getRttPipeFromInCall()380     public ParcelFileDescriptor getRttPipeFromInCall() {
381         return mRttPipeFromInCall;
382     }
383 
384     /**
385      * Gets the {@link android.telecom.Connection.RttTextStream} object that should be used to
386      * send and receive RTT text to/from the in-call app.
387      * @return An instance of {@link android.telecom.Connection.RttTextStream}, or {@code null}
388      * if this connection request is not requesting an RTT session upon connection establishment.
389      */
getRttTextStream()390     public Connection.RttTextStream getRttTextStream() {
391         if (isRequestingRtt()) {
392             if (mRttTextStream == null) {
393                 mRttTextStream = new Connection.RttTextStream(mRttPipeToInCall, mRttPipeFromInCall);
394             }
395             return mRttTextStream;
396         } else {
397             return null;
398         }
399     }
400 
401     /**
402      * Convenience method for determining whether the ConnectionRequest is requesting an RTT session
403      * @return {@code true} if RTT is requested, {@code false} otherwise.
404      */
isRequestingRtt()405     public boolean isRequestingRtt() {
406         return mRttPipeFromInCall != null && mRttPipeToInCall != null;
407     }
408 
409     @Override
toString()410     public String toString() {
411         return String.format("ConnectionRequest %s %s isAdhocConf: %s",
412                 mAddress == null
413                         ? Uri.EMPTY
414                         : Connection.toLogSafePhoneNumber(mAddress.toString()),
415                 bundleToString(mExtras),
416                 isAdhocConferenceCall() ? "Y" : "N");
417     }
418 
bundleToString(Bundle extras)419     private static String bundleToString(Bundle extras){
420         if (extras == null) {
421             return "";
422         }
423         StringBuilder sb = new StringBuilder();
424         sb.append("Bundle[");
425         for (String key : extras.keySet()) {
426             sb.append(key);
427             sb.append("=");
428             switch (key) {
429                 case TelecomManager.EXTRA_INCOMING_CALL_ADDRESS:
430                 case TelecomManager.EXTRA_UNKNOWN_CALL_HANDLE:
431                     sb.append(Log.pii(extras.get(key)));
432                     break;
433                 default:
434                     sb.append(extras.get(key));
435                     break;
436             }
437             sb.append(", ");
438         }
439         sb.append("]");
440         return sb.toString();
441     }
442 
443     public static final @android.annotation.NonNull Creator<ConnectionRequest> CREATOR = new Creator<ConnectionRequest> () {
444         @Override
445         public ConnectionRequest createFromParcel(Parcel source) {
446             return new ConnectionRequest(source);
447         }
448 
449         @Override
450         public ConnectionRequest[] newArray(int size) {
451             return new ConnectionRequest[size];
452         }
453     };
454 
455     /**
456      * {@inheritDoc}
457      */
458     @Override
describeContents()459     public int describeContents() {
460         return 0;
461     }
462 
463     @Override
writeToParcel(Parcel destination, int flags)464     public void writeToParcel(Parcel destination, int flags) {
465         destination.writeParcelable(mAccountHandle, 0);
466         destination.writeParcelable(mAddress, 0);
467         destination.writeParcelable(mExtras, 0);
468         destination.writeInt(mVideoState);
469         destination.writeString(mTelecomCallId);
470         destination.writeInt(mShouldShowIncomingCallUi ? 1 : 0);
471         destination.writeParcelable(mRttPipeFromInCall, 0);
472         destination.writeParcelable(mRttPipeToInCall, 0);
473         destination.writeList(mParticipants);
474         destination.writeInt(mIsAdhocConference ? 1 : 0);
475     }
476 }
477