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