1 /*
2  * Copyright (C) 2018 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.telephony.ims;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.SystemApi;
23 import android.annotation.TestApi;
24 import android.net.Uri;
25 import android.os.Parcel;
26 import android.os.Parcelable;
27 
28 import com.android.telephony.Rlog;
29 
30 import java.lang.annotation.Retention;
31 import java.lang.annotation.RetentionPolicy;
32 
33 /**
34  * Parcelable object to handle MultiEndpoint Dialog Event Package Information.
35  * @hide
36  */
37 @SystemApi
38 @TestApi
39 public final class ImsExternalCallState implements Parcelable {
40 
41     private static final String TAG = "ImsExternalCallState";
42 
43     // Dialog States
44     /**
45      * The external call is in the confirmed dialog state.
46      */
47     public static final int CALL_STATE_CONFIRMED = 1;
48     /**
49      * The external call is in the terminated dialog state.
50      */
51     public static final int CALL_STATE_TERMINATED = 2;
52 
53     /**@hide*/
54     @IntDef(flag = true,
55             value = {
56                     CALL_STATE_CONFIRMED,
57                     CALL_STATE_TERMINATED
58             },
59             prefix = "CALL_STATE_")
60     @Retention(RetentionPolicy.SOURCE)
61     public @interface ExternalCallState {}
62 
63     /**@hide*/
64     @IntDef(flag = true,
65             value = {
66                     ImsCallProfile.CALL_TYPE_VOICE,
67                     ImsCallProfile.CALL_TYPE_VT_TX,
68                     ImsCallProfile.CALL_TYPE_VT_RX,
69                     ImsCallProfile.CALL_TYPE_VT
70             },
71             prefix = "CALL_TYPE_")
72     @Retention(RetentionPolicy.SOURCE)
73     public @interface ExternalCallType {}
74 
75 
76 
77     // Dialog Id
78     private int mCallId;
79     // Number
80     private Uri mAddress;
81     private Uri mLocalAddress;
82     private boolean mIsPullable;
83     // CALL_STATE_CONFIRMED / CALL_STATE_TERMINATED
84     private int mCallState;
85     // ImsCallProfile#CALL_TYPE_*
86     private int mCallType;
87     private boolean mIsHeld;
88 
89     /** @hide */
ImsExternalCallState()90     public ImsExternalCallState() {
91     }
92 
93     /**@hide*/
ImsExternalCallState(int callId, Uri address, boolean isPullable, @ExternalCallState int callState, int callType, boolean isCallheld)94     public ImsExternalCallState(int callId, Uri address, boolean isPullable,
95             @ExternalCallState int callState, int callType, boolean isCallheld) {
96         mCallId = callId;
97         mAddress = address;
98         mIsPullable = isPullable;
99         mCallState = callState;
100         mCallType = callType;
101         mIsHeld = isCallheld;
102         Rlog.d(TAG, "ImsExternalCallState = " + this);
103     }
104 
105     /**@hide*/
ImsExternalCallState(int callId, Uri address, Uri localAddress, boolean isPullable, @ExternalCallState int callState, int callType, boolean isCallheld)106     public ImsExternalCallState(int callId, Uri address, Uri localAddress,
107             boolean isPullable, @ExternalCallState int callState, int callType,
108             boolean isCallheld) {
109         mCallId = callId;
110         mAddress = address;
111         mLocalAddress = localAddress;
112         mIsPullable = isPullable;
113         mCallState = callState;
114         mCallType = callType;
115         mIsHeld = isCallheld;
116         Rlog.d(TAG, "ImsExternalCallState = " + this);
117     }
118 
119     /**
120      * Create a new ImsExternalCallState instance to contain Multiendpoint Dialog information.
121      * @param callId The unique ID of the call, which will be used to identify this external
122      *               connection.
123      * @param address A {@link Uri} containing the remote address of this external connection.
124      * @param localAddress A {@link Uri} containing the local address information.
125      * @param isPullable A flag determining if this external connection can be pulled to the current
126      *         device.
127      * @param callState The state of the external call.
128      * @param callType The type of external call.
129      * @param isCallheld A flag determining if the external connection is currently held.
130      */
ImsExternalCallState(@onNull String callId, @NonNull Uri address, @Nullable Uri localAddress, boolean isPullable, @ExternalCallState int callState, @ExternalCallType int callType, boolean isCallheld)131     public ImsExternalCallState(@NonNull String callId, @NonNull Uri address,
132             @Nullable Uri localAddress, boolean isPullable, @ExternalCallState int callState,
133             @ExternalCallType int callType, boolean isCallheld) {
134         mCallId = getIdForString(callId);
135         mAddress = address;
136         mLocalAddress = localAddress;
137         mIsPullable = isPullable;
138         mCallState = callState;
139         mCallType = callType;
140         mIsHeld = isCallheld;
141         Rlog.d(TAG, "ImsExternalCallState = " + this);
142     }
143 
144     /** @hide */
ImsExternalCallState(Parcel in)145     public ImsExternalCallState(Parcel in) {
146         mCallId = in.readInt();
147         ClassLoader classLoader = ImsExternalCallState.class.getClassLoader();
148         mAddress = in.readParcelable(classLoader);
149         mLocalAddress = in.readParcelable(classLoader);
150         mIsPullable = (in.readInt() != 0);
151         mCallState = in.readInt();
152         mCallType = in.readInt();
153         mIsHeld = (in.readInt() != 0);
154         Rlog.d(TAG, "ImsExternalCallState const = " + this);
155     }
156 
157     @Override
describeContents()158     public int describeContents() {
159         return 0;
160     }
161 
162     @Override
writeToParcel(Parcel out, int flags)163     public void writeToParcel(Parcel out, int flags) {
164         out.writeInt(mCallId);
165         out.writeParcelable(mAddress, 0);
166         out.writeParcelable(mLocalAddress, 0);
167         out.writeInt(mIsPullable ? 1 : 0);
168         out.writeInt(mCallState);
169         out.writeInt(mCallType);
170         out.writeInt(mIsHeld ? 1 : 0);
171         Rlog.d(TAG, "ImsExternalCallState writeToParcel = " + out.toString());
172     }
173 
174     public static final @android.annotation.NonNull Parcelable.Creator<ImsExternalCallState> CREATOR =
175             new Parcelable.Creator<ImsExternalCallState>() {
176         @Override
177         public ImsExternalCallState createFromParcel(Parcel in) {
178             return new ImsExternalCallState(in);
179         }
180 
181         @Override
182         public ImsExternalCallState[] newArray(int size) {
183             return new ImsExternalCallState[size];
184         }
185     };
186 
getCallId()187     public int getCallId() {
188         return mCallId;
189     }
190 
getAddress()191     public @NonNull Uri getAddress() {
192         return mAddress;
193     }
194 
195     /**
196      * @return A {@link Uri} containing the local address from the Multiendpoint Dialog Information.
197      */
getLocalAddress()198     public @Nullable Uri getLocalAddress() {
199         return mLocalAddress;
200     }
201 
isCallPullable()202     public boolean isCallPullable() {
203         return mIsPullable;
204     }
205 
getCallState()206     public @ExternalCallState int getCallState() {
207         return mCallState;
208     }
209 
getCallType()210     public @ExternalCallType int getCallType() {
211         return mCallType;
212     }
213 
isCallHeld()214     public boolean isCallHeld() {
215         return mIsHeld;
216     }
217 
218     @NonNull
219     @Override
toString()220     public String toString() {
221         return "ImsExternalCallState { mCallId = " + mCallId +
222                 ", mAddress = " + Rlog.pii(TAG, mAddress) +
223                 ", mLocalAddress = " + Rlog.pii(TAG, mLocalAddress) +
224                 ", mIsPullable = " + mIsPullable +
225                 ", mCallState = " + mCallState +
226                 ", mCallType = " + mCallType +
227                 ", mIsHeld = " + mIsHeld + "}";
228     }
229 
getIdForString(String idString)230     private int getIdForString(String idString) {
231         try {
232             return Integer.parseInt(idString);
233         } catch (NumberFormatException e) {
234             // In the case that there are alphanumeric characters, we will create a hash of the
235             // String value as a backup.
236             // TODO: Modify call IDs to use Strings as keys instead of integers in telephony/telecom
237             return idString.hashCode();
238         }
239     }
240 }
241