• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 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 com.android.services.telephony.common;
18 
19 import android.os.Parcel;
20 import android.os.Parcelable;
21 
22 import com.android.internal.telephony.PhoneConstants;
23 import com.google.android.collect.Sets;
24 import com.google.common.base.Objects;
25 import com.google.common.collect.ImmutableMap;
26 import com.google.common.collect.ImmutableSortedSet;
27 import com.google.common.primitives.Ints;
28 
29 import java.util.Map;
30 import java.util.SortedSet;
31 import java.util.TreeSet;
32 
33 /**
34  * Class object used across CallHandlerService APIs.
35  * Describes a single call and its state.
36  */
37 public final class Call implements Parcelable {
38 
39     public static final int INVALID_CALL_ID = -1;
40     public static final int MAX_CONFERENCED_CALLS = 5;
41 
42     /* Defines different states of this call */
43     public static class State {
44         public static final int INVALID = 0;
45         public static final int IDLE = 1;           /* The call is idle.  Nothing active */
46         public static final int ACTIVE = 2;         /* There is an active call */
47         public static final int INCOMING = 3;       /* A normal incoming phone call */
48         public static final int CALL_WAITING = 4;   /* Incoming call while another is active */
49         public static final int DIALING = 5;        /* An outgoing call during dial phase */
50         public static final int REDIALING = 6;      /* Subsequent dialing attempt after a failure */
51         public static final int ONHOLD = 7;         /* An active phone call placed on hold */
52         public static final int DISCONNECTING = 8;  /* A call is being ended. */
53         public static final int DISCONNECTED = 9;   /* State after a call disconnects */
54         public static final int CONFERENCED = 10;   /* Call part of a conference call */
55 
isConnected(int state)56         public static boolean isConnected(int state) {
57             switch(state) {
58                 case ACTIVE:
59                 case INCOMING:
60                 case CALL_WAITING:
61                 case DIALING:
62                 case REDIALING:
63                 case ONHOLD:
64                 case CONFERENCED:
65                     return true;
66                 default:
67             }
68             return false;
69         }
70 
isDialing(int state)71         public static boolean isDialing(int state) {
72             return state == DIALING || state == REDIALING;
73         }
74     }
75 
76     /**
77      * Defines a set of capabilities that a call can have as a bit mask.
78      * TODO: Should some of these be capabilities of the Phone instead of the call?
79      * TODO: This is starting to be a mix of capabilities and call properties.  Capabilities
80      *       and properties should be separated.
81      */
82     public static class Capabilities {
83         public static final int HOLD               = 0x00000001; /* has ability to hold the call */
84         public static final int SUPPORT_HOLD       = 0x00000002; /* can show the hold button */
85         public static final int MERGE_CALLS        = 0x00000004; /* has ability to merge calls */
86         public static final int SWAP_CALLS         = 0x00000008; /* swap with a background call */
87         public static final int ADD_CALL           = 0x00000010; /* add another call to this one */
88         public static final int RESPOND_VIA_TEXT   = 0x00000020; /* has respond via text option */
89         public static final int MUTE               = 0x00000040; /* can mute the call */
90         public static final int GENERIC_CONFERENCE = 0x00000080; /* Generic conference mode */
91 
92         public static final int ALL = HOLD | SUPPORT_HOLD | MERGE_CALLS | SWAP_CALLS | ADD_CALL
93                 | RESPOND_VIA_TEXT | MUTE | GENERIC_CONFERENCE;
94     }
95 
96     /**
97      * Copy of states found in Connection object since Connection object is not available to the UI
98      * code.
99      * TODO: Consider cutting this down to only the types used by the UI.
100      * TODO: Consider adding a CUSTOM cause type and a customDisconnect member variable to
101      *       the Call object.  This would allow OEMs to extend the cause list without
102      *       needing to alter our implementation.
103      */
104     public enum DisconnectCause {
105         NOT_DISCONNECTED,               /* has not yet disconnected */
106         INCOMING_MISSED,                /* an incoming call that was missed and never answered */
107         NORMAL,                         /* normal; remote */
108         LOCAL,                          /* normal; local hangup */
109         BUSY,                           /* outgoing call to busy line */
110         CONGESTION,                     /* outgoing call to congested network */
111         MMI,                            /* not presently used; dial() returns null */
112         INVALID_NUMBER,                 /* invalid dial string */
113         NUMBER_UNREACHABLE,             /* cannot reach the peer */
114         SERVER_UNREACHABLE,             /* cannot reach the server */
115         INVALID_CREDENTIALS,            /* invalid credentials */
116         OUT_OF_NETWORK,                 /* calling from out of network is not allowed */
117         SERVER_ERROR,                   /* server error */
118         TIMED_OUT,                      /* client timed out */
119         LOST_SIGNAL,
120         LIMIT_EXCEEDED,                 /* eg GSM ACM limit exceeded */
121         INCOMING_REJECTED,              /* an incoming call that was rejected */
122         POWER_OFF,                      /* radio is turned off explicitly */
123         OUT_OF_SERVICE,                 /* out of service */
124         ICC_ERROR,                      /* No ICC, ICC locked, or other ICC error */
125         CALL_BARRED,                    /* call was blocked by call barring */
126         FDN_BLOCKED,                    /* call was blocked by fixed dial number */
127         CS_RESTRICTED,                  /* call was blocked by restricted all voice access */
128         CS_RESTRICTED_NORMAL,           /* call was blocked by restricted normal voice access */
129         CS_RESTRICTED_EMERGENCY,        /* call was blocked by restricted emergency voice access */
130         UNOBTAINABLE_NUMBER,            /* Unassigned number (3GPP TS 24.008 table 10.5.123) */
131         CDMA_LOCKED_UNTIL_POWER_CYCLE,  /* MS is locked until next power cycle */
132         CDMA_DROP,
133         CDMA_INTERCEPT,                 /* INTERCEPT order received, MS state idle entered */
134         CDMA_REORDER,                   /* MS has been redirected, call is cancelled */
135         CDMA_SO_REJECT,                 /* service option rejection */
136         CDMA_RETRY_ORDER,               /* requested service is rejected, retry delay is set */
137         CDMA_ACCESS_FAILURE,
138         CDMA_PREEMPTED,
139         CDMA_NOT_EMERGENCY,              /* not an emergency call */
140         CDMA_ACCESS_BLOCKED,            /* Access Blocked by CDMA network */
141         ERROR_UNSPECIFIED,
142 
143         UNKNOWN                         /* Disconnect cause doesn't map to any above */
144     }
145 
146     private static final Map<Integer, String> STATE_MAP = ImmutableMap.<Integer, String>builder()
147             .put(Call.State.ACTIVE, "ACTIVE")
148             .put(Call.State.CALL_WAITING, "CALL_WAITING")
149             .put(Call.State.DIALING, "DIALING")
150             .put(Call.State.REDIALING, "REDIALING")
151             .put(Call.State.IDLE, "IDLE")
152             .put(Call.State.INCOMING, "INCOMING")
153             .put(Call.State.ONHOLD, "ONHOLD")
154             .put(Call.State.INVALID, "INVALID")
155             .put(Call.State.DISCONNECTING, "DISCONNECTING")
156             .put(Call.State.DISCONNECTED, "DISCONNECTED")
157             .put(Call.State.CONFERENCED, "CONFERENCED")
158             .build();
159 
160     // Number presentation type for caller id display
161     // normal
162     public static int PRESENTATION_ALLOWED = PhoneConstants.PRESENTATION_ALLOWED;
163     // block by user
164     public static int PRESENTATION_RESTRICTED = PhoneConstants.PRESENTATION_RESTRICTED;
165     // no specified or unknown by network
166     public static int PRESENTATION_UNKNOWN = PhoneConstants.PRESENTATION_UNKNOWN;
167     // show pay phone info
168     public static int PRESENTATION_PAYPHONE = PhoneConstants.PRESENTATION_PAYPHONE;
169 
170     // Unique identifier for the call
171     private int mCallId;
172 
173     private CallIdentification mIdentification;
174 
175     // The current state of the call
176     private int mState = State.INVALID;
177 
178     // Reason for disconnect. Valid when the call state is DISCONNECTED.
179     private DisconnectCause mDisconnectCause = DisconnectCause.UNKNOWN;
180 
181     // Bit mask of capabilities unique to this call.
182     private int mCapabilities;
183 
184     // Time that this call transitioned into ACTIVE state from INCOMING, WAITING, or OUTGOING.
185     private long mConnectTime = 0;
186 
187     // List of call Ids for for this call.  (Used for managing conference calls).
188     private SortedSet<Integer> mChildCallIds = Sets.newSortedSet();
189 
190     // Gateway number used to dial this call
191     private String mGatewayNumber;
192 
193     // Gateway service package name
194     private String mGatewayPackage;
195 
Call(int callId)196     public Call(int callId) {
197         mCallId = callId;
198         mIdentification = new CallIdentification(mCallId);
199     }
200 
Call(Call call)201     public Call(Call call) {
202         mCallId = call.mCallId;
203         mIdentification = new CallIdentification(call.mIdentification);
204         mState = call.mState;
205         mDisconnectCause = call.mDisconnectCause;
206         mCapabilities = call.mCapabilities;
207         mConnectTime = call.mConnectTime;
208         mChildCallIds = new TreeSet<Integer>(call.mChildCallIds);
209         mGatewayNumber = call.mGatewayNumber;
210         mGatewayPackage = call.mGatewayPackage;
211     }
212 
getCallId()213     public int getCallId() {
214         return mCallId;
215     }
216 
getIdentification()217     public CallIdentification getIdentification() {
218         return mIdentification;
219     }
220 
getNumber()221     public String getNumber() {
222         return mIdentification.getNumber();
223     }
224 
setNumber(String number)225     public void setNumber(String number) {
226         mIdentification.setNumber(number);
227     }
228 
getState()229     public int getState() {
230         return mState;
231     }
232 
setState(int state)233     public void setState(int state) {
234         mState = state;
235     }
236 
getNumberPresentation()237     public int getNumberPresentation() {
238         return mIdentification.getNumberPresentation();
239     }
240 
setNumberPresentation(int presentation)241     public void setNumberPresentation(int presentation) {
242         mIdentification.setNumberPresentation(presentation);
243     }
244 
getCnapNamePresentation()245     public int getCnapNamePresentation() {
246         return mIdentification.getCnapNamePresentation();
247     }
248 
setCnapNamePresentation(int presentation)249     public void setCnapNamePresentation(int presentation) {
250         mIdentification.setCnapNamePresentation(presentation);
251     }
252 
getCnapName()253     public String getCnapName() {
254         return mIdentification.getCnapName();
255     }
256 
setCnapName(String cnapName)257     public void setCnapName(String cnapName) {
258         mIdentification.setCnapName(cnapName);
259     }
260 
getDisconnectCause()261     public DisconnectCause getDisconnectCause() {
262         if (mState == State.DISCONNECTED || mState == State.IDLE) {
263             return mDisconnectCause;
264         }
265 
266         return DisconnectCause.NOT_DISCONNECTED;
267     }
268 
setDisconnectCause(DisconnectCause cause)269     public void setDisconnectCause(DisconnectCause cause) {
270         mDisconnectCause = cause;
271     }
272 
getCapabilities()273     public int getCapabilities() {
274         return mCapabilities;
275     }
276 
setCapabilities(int capabilities)277     public void setCapabilities(int capabilities) {
278         mCapabilities = (Capabilities.ALL & capabilities);
279     }
280 
can(int capabilities)281     public boolean can(int capabilities) {
282         return (capabilities == (capabilities & mCapabilities));
283     }
284 
addCapabilities(int capabilities)285     public void addCapabilities(int capabilities) {
286         setCapabilities(capabilities | mCapabilities);
287     }
288 
setConnectTime(long connectTime)289     public void setConnectTime(long connectTime) {
290         mConnectTime = connectTime;
291     }
292 
getConnectTime()293     public long getConnectTime() {
294         return mConnectTime;
295     }
296 
removeChildId(int id)297     public void removeChildId(int id) {
298         mChildCallIds.remove(id);
299     }
300 
removeAllChildren()301     public void removeAllChildren() {
302         mChildCallIds.clear();
303     }
304 
addChildId(int id)305     public void addChildId(int id) {
306         mChildCallIds.add(id);
307     }
308 
getChildCallIds()309     public ImmutableSortedSet<Integer> getChildCallIds() {
310         return ImmutableSortedSet.copyOf(mChildCallIds);
311     }
312 
isConferenceCall()313     public boolean isConferenceCall() {
314         return mChildCallIds.size() >= 2;
315     }
316 
getGatewayNumber()317     public String getGatewayNumber() {
318         return mGatewayNumber;
319     }
320 
setGatewayNumber(String number)321     public void setGatewayNumber(String number) {
322         mGatewayNumber = number;
323     }
324 
getGatewayPackage()325     public String getGatewayPackage() {
326         return mGatewayPackage;
327     }
328 
setGatewayPackage(String packageName)329     public void setGatewayPackage(String packageName) {
330         mGatewayPackage = packageName;
331     }
332 
333     /**
334      * Parcelable implementation
335      */
336 
337     @Override
writeToParcel(Parcel dest, int flags)338     public void writeToParcel(Parcel dest, int flags) {
339         dest.writeInt(mCallId);
340         dest.writeInt(mState);
341         dest.writeString(getDisconnectCause().toString());
342         dest.writeInt(getCapabilities());
343         dest.writeLong(getConnectTime());
344         dest.writeIntArray(Ints.toArray(mChildCallIds));
345         dest.writeString(getGatewayNumber());
346         dest.writeString(getGatewayPackage());
347         dest.writeParcelable(mIdentification, 0);
348     }
349 
350     /**
351      * Constructor for Parcelable implementation.
352      */
Call(Parcel in)353     private Call(Parcel in) {
354         mCallId = in.readInt();
355         mState = in.readInt();
356         mDisconnectCause = DisconnectCause.valueOf(in.readString());
357         mCapabilities = in.readInt();
358         mConnectTime = in.readLong();
359         mChildCallIds.addAll(Ints.asList(in.createIntArray()));
360         mGatewayNumber = in.readString();
361         mGatewayPackage = in.readString();
362         mIdentification = in.readParcelable(CallIdentification.class.getClassLoader());
363     }
364 
365     @Override
describeContents()366     public int describeContents() {
367         return 0;
368     }
369 
370     /**
371      * Creates Call objects for Parcelable implementation.
372      */
373     public static final Parcelable.Creator<Call> CREATOR
374             = new Parcelable.Creator<Call>() {
375 
376         @Override
377         public Call createFromParcel(Parcel in) {
378             return new Call(in);
379         }
380 
381         @Override
382         public Call[] newArray(int size) {
383             return new Call[size];
384         }
385     };
386 
387     @Override
toString()388     public String toString() {
389         return Objects.toStringHelper(this)
390                 .add("mCallId", mCallId)
391                 .add("mState", STATE_MAP.get(mState))
392                 .add("mDisconnectCause", mDisconnectCause)
393                 .add("mCapabilities", mCapabilities)
394                 .add("mConnectTime", mConnectTime)
395                 .add("mChildCallIds", mChildCallIds)
396                 .add("mGatewayNumber", MoreStrings.toSafeString(mGatewayNumber))
397                 .add("mGatewayPackage", mGatewayPackage)
398                 .add("mIdentification", mIdentification)
399                 .toString();
400     }
401 }
402