1 /*
2  * Copyright (C) 2010 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.internal.telephony;
18 
19 import com.android.internal.telephony.sip.SipPhone;
20 
21 import android.content.Context;
22 import android.os.AsyncResult;
23 import android.os.Handler;
24 import android.os.Message;
25 import android.os.RegistrantList;
26 import android.os.Registrant;
27 import android.telecom.VideoProfile;
28 import android.telephony.PhoneNumberUtils;
29 import android.telephony.TelephonyManager;
30 import android.telephony.PhoneStateListener;
31 import android.telephony.ServiceState;
32 import android.telephony.Rlog;
33 
34 import java.util.ArrayList;
35 import java.util.Collections;
36 import java.util.HashMap;
37 import java.util.List;
38 
39 
40 
41 /**
42  * @hide
43  *
44  * CallManager class provides an abstract layer for PhoneApp to access
45  * and control calls. It implements Phone interface.
46  *
47  * CallManager provides call and connection control as well as
48  * channel capability.
49  *
50  * There are three categories of APIs CallManager provided
51  *
52  *  1. Call control and operation, such as dial() and hangup()
53  *  2. Channel capabilities, such as CanConference()
54  *  3. Register notification
55  *
56  *
57  */
58 public class CallManager {
59 
60     private static final String LOG_TAG ="CallManager";
61     private static final boolean DBG = true;
62     private static final boolean VDBG = false;
63 
64     private static final int EVENT_DISCONNECT = 100;
65     private static final int EVENT_PRECISE_CALL_STATE_CHANGED = 101;
66     private static final int EVENT_NEW_RINGING_CONNECTION = 102;
67     private static final int EVENT_UNKNOWN_CONNECTION = 103;
68     private static final int EVENT_INCOMING_RING = 104;
69     private static final int EVENT_RINGBACK_TONE = 105;
70     private static final int EVENT_IN_CALL_VOICE_PRIVACY_ON = 106;
71     private static final int EVENT_IN_CALL_VOICE_PRIVACY_OFF = 107;
72     private static final int EVENT_CALL_WAITING = 108;
73     private static final int EVENT_DISPLAY_INFO = 109;
74     private static final int EVENT_SIGNAL_INFO = 110;
75     private static final int EVENT_CDMA_OTA_STATUS_CHANGE = 111;
76     private static final int EVENT_RESEND_INCALL_MUTE = 112;
77     private static final int EVENT_MMI_INITIATE = 113;
78     private static final int EVENT_MMI_COMPLETE = 114;
79     private static final int EVENT_ECM_TIMER_RESET = 115;
80     private static final int EVENT_SUBSCRIPTION_INFO_READY = 116;
81     private static final int EVENT_SUPP_SERVICE_FAILED = 117;
82     private static final int EVENT_SERVICE_STATE_CHANGED = 118;
83     private static final int EVENT_POST_DIAL_CHARACTER = 119;
84     private static final int EVENT_ONHOLD_TONE = 120;
85     // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
86     //private static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 121;
87     private static final int EVENT_TTY_MODE_RECEIVED = 122;
88 
89     // Singleton instance
90     private static final CallManager INSTANCE = new CallManager();
91 
92     // list of registered phones, which are Phone objs
93     private final ArrayList<Phone> mPhones;
94 
95     // list of supported ringing calls
96     private final ArrayList<Call> mRingingCalls;
97 
98     // list of supported background calls
99     private final ArrayList<Call> mBackgroundCalls;
100 
101     // list of supported foreground calls
102     private final ArrayList<Call> mForegroundCalls;
103 
104     // empty connection list
105     private final ArrayList<Connection> mEmptyConnections = new ArrayList<Connection>();
106 
107     // mapping of phones to registered handler instances used for callbacks from RIL
108     private final HashMap<Phone, CallManagerHandler> mHandlerMap = new HashMap<>();
109 
110     // default phone as the first phone registered, which is Phone obj
111     private Phone mDefaultPhone;
112 
113     private boolean mSpeedUpAudioForMtCall = false;
114     // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
115     //private boolean mIsEccDialing = false;
116 
117     private Object mRegistrantidentifier = new Object();
118 
119     // state registrants
120     protected final RegistrantList mPreciseCallStateRegistrants
121     = new RegistrantList();
122 
123     protected final RegistrantList mNewRingingConnectionRegistrants
124     = new RegistrantList();
125 
126     protected final RegistrantList mIncomingRingRegistrants
127     = new RegistrantList();
128 
129     protected final RegistrantList mDisconnectRegistrants
130     = new RegistrantList();
131 
132     protected final RegistrantList mMmiRegistrants
133     = new RegistrantList();
134 
135     protected final RegistrantList mUnknownConnectionRegistrants
136     = new RegistrantList();
137 
138     protected final RegistrantList mRingbackToneRegistrants
139     = new RegistrantList();
140 
141     protected final RegistrantList mOnHoldToneRegistrants
142     = new RegistrantList();
143 
144     protected final RegistrantList mInCallVoicePrivacyOnRegistrants
145     = new RegistrantList();
146 
147     protected final RegistrantList mInCallVoicePrivacyOffRegistrants
148     = new RegistrantList();
149 
150     protected final RegistrantList mCallWaitingRegistrants
151     = new RegistrantList();
152 
153     protected final RegistrantList mDisplayInfoRegistrants
154     = new RegistrantList();
155 
156     protected final RegistrantList mSignalInfoRegistrants
157     = new RegistrantList();
158 
159     protected final RegistrantList mCdmaOtaStatusChangeRegistrants
160     = new RegistrantList();
161 
162     protected final RegistrantList mResendIncallMuteRegistrants
163     = new RegistrantList();
164 
165     protected final RegistrantList mMmiInitiateRegistrants
166     = new RegistrantList();
167 
168     protected final RegistrantList mMmiCompleteRegistrants
169     = new RegistrantList();
170 
171     protected final RegistrantList mEcmTimerResetRegistrants
172     = new RegistrantList();
173 
174     protected final RegistrantList mSubscriptionInfoReadyRegistrants
175     = new RegistrantList();
176 
177     protected final RegistrantList mSuppServiceFailedRegistrants
178     = new RegistrantList();
179 
180     protected final RegistrantList mServiceStateChangedRegistrants
181     = new RegistrantList();
182 
183     protected final RegistrantList mPostDialCharacterRegistrants
184     = new RegistrantList();
185 
186     protected final RegistrantList mTtyModeReceivedRegistrants
187     = new RegistrantList();
188 
CallManager()189     private CallManager() {
190         mPhones = new ArrayList<Phone>();
191         mRingingCalls = new ArrayList<Call>();
192         mBackgroundCalls = new ArrayList<Call>();
193         mForegroundCalls = new ArrayList<Call>();
194         mDefaultPhone = null;
195     }
196 
197     /**
198      * get singleton instance of CallManager
199      * @return CallManager
200      */
getInstance()201     public static CallManager getInstance() {
202         return INSTANCE;
203     }
204 
205     /**
206      * Returns all the registered phone objects.
207      * @return all the registered phone objects.
208      */
getAllPhones()209     public List<Phone> getAllPhones() {
210         return Collections.unmodifiableList(mPhones);
211     }
212 
213     /**
214      * get Phone object corresponds to subId
215      * @return Phone
216      */
getPhone(int subId)217     private Phone getPhone(int subId) {
218         Phone p = null;
219         for (Phone phone : mPhones) {
220             if (phone.getSubId() == subId &&
221                     phone.getPhoneType() != PhoneConstants.PHONE_TYPE_IMS) {
222                 p = phone;
223                 break;
224             }
225         }
226         return p;
227     }
228 
229     /**
230      * Get current coarse-grained voice call state.
231      * If the Call Manager has an active call and call waiting occurs,
232      * then the phone state is RINGING not OFFHOOK
233      *
234      */
getState()235     public PhoneConstants.State getState() {
236         PhoneConstants.State s = PhoneConstants.State.IDLE;
237 
238         for (Phone phone : mPhones) {
239             if (phone.getState() == PhoneConstants.State.RINGING) {
240                 s = PhoneConstants.State.RINGING;
241             } else if (phone.getState() == PhoneConstants.State.OFFHOOK) {
242                 if (s == PhoneConstants.State.IDLE) s = PhoneConstants.State.OFFHOOK;
243             }
244         }
245         return s;
246     }
247 
248     /**
249      * Get current coarse-grained voice call state on a subId.
250      * If the Call Manager has an active call and call waiting occurs,
251      * then the phone state is RINGING not OFFHOOK
252      *
253      */
getState(int subId)254     public PhoneConstants.State getState(int subId) {
255         PhoneConstants.State s = PhoneConstants.State.IDLE;
256 
257         for (Phone phone : mPhones) {
258             if (phone.getSubId() == subId) {
259                 if (phone.getState() == PhoneConstants.State.RINGING) {
260                     s = PhoneConstants.State.RINGING;
261                 } else if (phone.getState() == PhoneConstants.State.OFFHOOK) {
262                     if (s == PhoneConstants.State.IDLE) s = PhoneConstants.State.OFFHOOK;
263                 }
264             }
265         }
266         return s;
267     }
268 
269     /**
270      * @return the service state of CallManager, which represents the
271      * highest priority state of all the service states of phones
272      *
273      * The priority is defined as
274      *
275      * STATE_IN_SERIVCE > STATE_OUT_OF_SERIVCE > STATE_EMERGENCY > STATE_POWER_OFF
276      *
277      */
278 
getServiceState()279     public int getServiceState() {
280         int resultState = ServiceState.STATE_OUT_OF_SERVICE;
281 
282         for (Phone phone : mPhones) {
283             int serviceState = phone.getServiceState().getState();
284             if (serviceState == ServiceState.STATE_IN_SERVICE) {
285                 // IN_SERVICE has the highest priority
286                 resultState = serviceState;
287                 break;
288             } else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE) {
289                 // OUT_OF_SERVICE replaces EMERGENCY_ONLY and POWER_OFF
290                 // Note: EMERGENCY_ONLY is not in use at this moment
291                 if ( resultState == ServiceState.STATE_EMERGENCY_ONLY ||
292                         resultState == ServiceState.STATE_POWER_OFF) {
293                     resultState = serviceState;
294                 }
295             } else if (serviceState == ServiceState.STATE_EMERGENCY_ONLY) {
296                 if (resultState == ServiceState.STATE_POWER_OFF) {
297                     resultState = serviceState;
298                 }
299             }
300         }
301         return resultState;
302     }
303 
304     /**
305      * @return the Phone service state corresponds to subId
306      */
getServiceState(int subId)307     public int getServiceState(int subId) {
308         int resultState = ServiceState.STATE_OUT_OF_SERVICE;
309 
310         for (Phone phone : mPhones) {
311             if (phone.getSubId() == subId) {
312                 int serviceState = phone.getServiceState().getState();
313                 if (serviceState == ServiceState.STATE_IN_SERVICE) {
314                     // IN_SERVICE has the highest priority
315                     resultState = serviceState;
316                     break;
317                 } else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE) {
318                     // OUT_OF_SERVICE replaces EMERGENCY_ONLY and POWER_OFF
319                     // Note: EMERGENCY_ONLY is not in use at this moment
320                     if ( resultState == ServiceState.STATE_EMERGENCY_ONLY ||
321                             resultState == ServiceState.STATE_POWER_OFF) {
322                         resultState = serviceState;
323                     }
324                 } else if (serviceState == ServiceState.STATE_EMERGENCY_ONLY) {
325                     if (resultState == ServiceState.STATE_POWER_OFF) {
326                         resultState = serviceState;
327                     }
328                 }
329             }
330         }
331         return resultState;
332     }
333 
334     /**
335      * @return the phone associated with any call
336      */
getPhoneInCall()337     public Phone getPhoneInCall() {
338         Phone phone = null;
339         if (!getFirstActiveRingingCall().isIdle()) {
340             phone = getFirstActiveRingingCall().getPhone();
341         } else if (!getActiveFgCall().isIdle()) {
342             phone = getActiveFgCall().getPhone();
343         } else {
344             // If BG call is idle, we return default phone
345             phone = getFirstActiveBgCall().getPhone();
346         }
347         return phone;
348     }
349 
getPhoneInCall(int subId)350     public Phone getPhoneInCall(int subId) {
351         Phone phone = null;
352         if (!getFirstActiveRingingCall(subId).isIdle()) {
353             phone = getFirstActiveRingingCall(subId).getPhone();
354         } else if (!getActiveFgCall(subId).isIdle()) {
355             phone = getActiveFgCall(subId).getPhone();
356         } else {
357             // If BG call is idle, we return default phone
358             phone = getFirstActiveBgCall(subId).getPhone();
359         }
360         return phone;
361     }
362 
363     /**
364      * Register phone to CallManager
365      * @param phone to be registered
366      * @return true if register successfully
367      */
registerPhone(Phone phone)368     public boolean registerPhone(Phone phone) {
369         if (phone != null && !mPhones.contains(phone)) {
370 
371             if (DBG) {
372                 Rlog.d(LOG_TAG, "registerPhone(" +
373                         phone.getPhoneName() + " " + phone + ")");
374             }
375 
376             if (mPhones.isEmpty()) {
377                 mDefaultPhone = phone;
378             }
379             mPhones.add(phone);
380             mRingingCalls.add(phone.getRingingCall());
381             mBackgroundCalls.add(phone.getBackgroundCall());
382             mForegroundCalls.add(phone.getForegroundCall());
383             registerForPhoneStates(phone);
384             return true;
385         }
386         return false;
387     }
388 
389     /**
390      * unregister phone from CallManager
391      * @param phone to be unregistered
392      */
unregisterPhone(Phone phone)393     public void unregisterPhone(Phone phone) {
394         if (phone != null && mPhones.contains(phone)) {
395 
396             if (DBG) {
397                 Rlog.d(LOG_TAG, "unregisterPhone(" +
398                         phone.getPhoneName() + " " + phone + ")");
399             }
400 
401             Phone imsPhone = phone.getImsPhone();
402             if (imsPhone != null) {
403                 unregisterPhone(imsPhone);
404             }
405 
406             mPhones.remove(phone);
407             mRingingCalls.remove(phone.getRingingCall());
408             mBackgroundCalls.remove(phone.getBackgroundCall());
409             mForegroundCalls.remove(phone.getForegroundCall());
410             unregisterForPhoneStates(phone);
411             if (phone == mDefaultPhone) {
412                 if (mPhones.isEmpty()) {
413                     mDefaultPhone = null;
414                 } else {
415                     mDefaultPhone = mPhones.get(0);
416                 }
417             }
418         }
419     }
420 
421     /**
422      * return the default phone or null if no phone available
423      */
getDefaultPhone()424     public Phone getDefaultPhone() {
425         return mDefaultPhone;
426     }
427 
428     /**
429      * @return the phone associated with the foreground call
430      */
getFgPhone()431     public Phone getFgPhone() {
432         return getActiveFgCall().getPhone();
433     }
434 
435     /**
436      * @return the phone associated with the foreground call
437      * of a particular subId
438      */
getFgPhone(int subId)439     public Phone getFgPhone(int subId) {
440         return getActiveFgCall(subId).getPhone();
441     }
442 
443     /**
444      * @return the phone associated with the background call
445      */
getBgPhone()446     public Phone getBgPhone() {
447         return getFirstActiveBgCall().getPhone();
448     }
449 
450     /**
451      * @return the phone associated with the background call
452      * of a particular subId
453      */
getBgPhone(int subId)454     public Phone getBgPhone(int subId) {
455         return getFirstActiveBgCall(subId).getPhone();
456     }
457 
458     /**
459      * @return the phone associated with the ringing call
460      */
getRingingPhone()461     public Phone getRingingPhone() {
462         return getFirstActiveRingingCall().getPhone();
463     }
464 
465     /**
466      * @return the phone associated with the ringing call
467      * of a particular subId
468      */
getRingingPhone(int subId)469     public Phone getRingingPhone(int subId) {
470         return getFirstActiveRingingCall(subId).getPhone();
471     }
472 
473     /* FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
474     public void setAudioMode() {
475         Context context = getContext();
476         if (context == null) return;
477         AudioManager audioManager = (AudioManager)
478                 context.getSystemService(Context.AUDIO_SERVICE);
479 
480         if (!isServiceStateInService() && !mIsEccDialing) {
481             if (audioManager.getMode() != AudioManager.MODE_NORMAL) {
482                 if (VDBG) Rlog.d(LOG_TAG, "abandonAudioFocus");
483                 // abandon audio focus after the mode has been set back to normal
484                 audioManager.abandonAudioFocusForCall();
485                 audioManager.setMode(AudioManager.MODE_NORMAL);
486             }
487             return;
488         }
489 
490         // change the audio mode and request/abandon audio focus according to phone state,
491         // but only on audio mode transitions
492         switch (getState()) {
493             case RINGING:
494                 int curAudioMode = audioManager.getMode();
495                 if (curAudioMode != AudioManager.MODE_RINGTONE) {
496                     if (VDBG) Rlog.d(LOG_TAG, "requestAudioFocus on STREAM_RING");
497                     audioManager.requestAudioFocusForCall(AudioManager.STREAM_RING,
498                             AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
499                     if(!mSpeedUpAudioForMtCall) {
500                         audioManager.setMode(AudioManager.MODE_RINGTONE);
501                     }
502                 }
503 
504                 if (mSpeedUpAudioForMtCall && (curAudioMode != AudioManager.MODE_IN_CALL)) {
505                     audioManager.setMode(AudioManager.MODE_IN_CALL);
506                 }
507                 break;
508             case OFFHOOK:
509                 Phone offhookPhone = getFgPhone();
510                 if (getActiveFgCallState() == Call.State.IDLE) {
511                     // There is no active Fg calls, the OFFHOOK state
512                     // is set by the Bg call. So set the phone to bgPhone.
513                     offhookPhone = getBgPhone();
514                 }
515 
516                 int newAudioMode = AudioManager.MODE_IN_CALL;
517                 if (offhookPhone instanceof SipPhone) {
518                     Rlog.d(LOG_TAG, "setAudioMode Set audio mode for SIP call!");
519                     // enable IN_COMMUNICATION audio mode instead for sipPhone
520                     newAudioMode = AudioManager.MODE_IN_COMMUNICATION;
521                 }
522                 int currMode = audioManager.getMode();
523                 if (currMode != newAudioMode || mSpeedUpAudioForMtCall) {
524                     // request audio focus before setting the new mode
525                     if (VDBG) Rlog.d(LOG_TAG, "requestAudioFocus on STREAM_VOICE_CALL");
526                     audioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL,
527                             AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
528                     Rlog.d(LOG_TAG, "setAudioMode Setting audio mode from "
529                             + currMode + " to " + newAudioMode);
530                     audioManager.setMode(newAudioMode);
531                 }
532                 mSpeedUpAudioForMtCall = false;
533                 break;
534             case IDLE:
535                 if (audioManager.getMode() != AudioManager.MODE_NORMAL) {
536                     audioManager.setMode(AudioManager.MODE_NORMAL);
537                     if (VDBG) Rlog.d(LOG_TAG, "abandonAudioFocus");
538                     // abandon audio focus after the mode has been set back to normal
539                     audioManager.abandonAudioFocusForCall();
540                 }
541                 mSpeedUpAudioForMtCall = false;
542                 break;
543         }
544         Rlog.d(LOG_TAG, "setAudioMode state = " + getState());
545     }
546     */
547 
getContext()548     private Context getContext() {
549         Phone defaultPhone = getDefaultPhone();
550         return ((defaultPhone == null) ? null : defaultPhone.getContext());
551     }
552 
getRegistrantIdentifier()553     public Object getRegistrantIdentifier() {
554         return mRegistrantidentifier;
555     }
556 
registerForPhoneStates(Phone phone)557     private void registerForPhoneStates(Phone phone) {
558         // We need to keep a mapping of handler to Phone for proper unregistration.
559         // TODO: Clean up this solution as it is just a work around for each Phone instance
560         // using the same Handler to register with the RIL. When time permits, we should consider
561         // moving the handler (or the reference ot the handler) into the Phone object.
562         // See b/17414427.
563         CallManagerHandler handler = mHandlerMap.get(phone);
564         if (handler != null) {
565             Rlog.d(LOG_TAG, "This phone has already been registered.");
566             return;
567         }
568 
569         // New registration, create a new handler instance and register the phone.
570         handler = new CallManagerHandler();
571         mHandlerMap.put(phone, handler);
572 
573         // for common events supported by all phones
574         // The mRegistrantIdentifier passed here, is to identify in the Phone
575         // that the registrants are coming from the CallManager.
576         phone.registerForPreciseCallStateChanged(handler, EVENT_PRECISE_CALL_STATE_CHANGED,
577                 mRegistrantidentifier);
578         phone.registerForDisconnect(handler, EVENT_DISCONNECT,
579                 mRegistrantidentifier);
580         phone.registerForNewRingingConnection(handler, EVENT_NEW_RINGING_CONNECTION,
581                 mRegistrantidentifier);
582         phone.registerForUnknownConnection(handler, EVENT_UNKNOWN_CONNECTION,
583                 mRegistrantidentifier);
584         phone.registerForIncomingRing(handler, EVENT_INCOMING_RING,
585                 mRegistrantidentifier);
586         phone.registerForRingbackTone(handler, EVENT_RINGBACK_TONE,
587                 mRegistrantidentifier);
588         phone.registerForInCallVoicePrivacyOn(handler, EVENT_IN_CALL_VOICE_PRIVACY_ON,
589                 mRegistrantidentifier);
590         phone.registerForInCallVoicePrivacyOff(handler, EVENT_IN_CALL_VOICE_PRIVACY_OFF,
591                 mRegistrantidentifier);
592         phone.registerForDisplayInfo(handler, EVENT_DISPLAY_INFO,
593                 mRegistrantidentifier);
594         phone.registerForSignalInfo(handler, EVENT_SIGNAL_INFO,
595                 mRegistrantidentifier);
596         phone.registerForResendIncallMute(handler, EVENT_RESEND_INCALL_MUTE,
597                 mRegistrantidentifier);
598         phone.registerForMmiInitiate(handler, EVENT_MMI_INITIATE,
599                 mRegistrantidentifier);
600         phone.registerForMmiComplete(handler, EVENT_MMI_COMPLETE,
601                 mRegistrantidentifier);
602         phone.registerForSuppServiceFailed(handler, EVENT_SUPP_SERVICE_FAILED,
603                 mRegistrantidentifier);
604         phone.registerForServiceStateChanged(handler, EVENT_SERVICE_STATE_CHANGED,
605                 mRegistrantidentifier);
606 
607         // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
608         //phone.registerForRadioOffOrNotAvailable(handler, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
609 
610         // for events supported only by GSM, CDMA and IMS phone
611         phone.setOnPostDialCharacter(handler, EVENT_POST_DIAL_CHARACTER, null);
612 
613         // for events supported only by CDMA phone
614         phone.registerForCdmaOtaStatusChange(handler, EVENT_CDMA_OTA_STATUS_CHANGE, null);
615         phone.registerForSubscriptionInfoReady(handler, EVENT_SUBSCRIPTION_INFO_READY, null);
616         phone.registerForCallWaiting(handler, EVENT_CALL_WAITING, null);
617         phone.registerForEcmTimerReset(handler, EVENT_ECM_TIMER_RESET, null);
618 
619         // for events supported only by IMS phone
620         phone.registerForOnHoldTone(handler, EVENT_ONHOLD_TONE, null);
621         phone.registerForSuppServiceFailed(handler, EVENT_SUPP_SERVICE_FAILED, null);
622         phone.registerForTtyModeReceived(handler, EVENT_TTY_MODE_RECEIVED, null);
623     }
624 
unregisterForPhoneStates(Phone phone)625     private void unregisterForPhoneStates(Phone phone) {
626         // Make sure that we clean up our map of handlers to Phones.
627         CallManagerHandler handler = mHandlerMap.get(phone);
628         if (handler == null) {
629             Rlog.e(LOG_TAG, "Could not find Phone handler for unregistration");
630             return;
631         }
632         mHandlerMap.remove(phone);
633 
634         //  for common events supported by all phones
635         phone.unregisterForPreciseCallStateChanged(handler);
636         phone.unregisterForDisconnect(handler);
637         phone.unregisterForNewRingingConnection(handler);
638         phone.unregisterForUnknownConnection(handler);
639         phone.unregisterForIncomingRing(handler);
640         phone.unregisterForRingbackTone(handler);
641         phone.unregisterForInCallVoicePrivacyOn(handler);
642         phone.unregisterForInCallVoicePrivacyOff(handler);
643         phone.unregisterForDisplayInfo(handler);
644         phone.unregisterForSignalInfo(handler);
645         phone.unregisterForResendIncallMute(handler);
646         phone.unregisterForMmiInitiate(handler);
647         phone.unregisterForMmiComplete(handler);
648         phone.unregisterForSuppServiceFailed(handler);
649         phone.unregisterForServiceStateChanged(handler);
650         phone.unregisterForTtyModeReceived(handler);
651         // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
652         //phone.unregisterForRadioOffOrNotAvailable(handler);
653 
654         // for events supported only by GSM, CDMA and IMS phone
655         phone.setOnPostDialCharacter(null, EVENT_POST_DIAL_CHARACTER, null);
656 
657         // for events supported only by CDMA phone
658         phone.unregisterForCdmaOtaStatusChange(handler);
659         phone.unregisterForSubscriptionInfoReady(handler);
660         phone.unregisterForCallWaiting(handler);
661         phone.unregisterForEcmTimerReset(handler);
662 
663         // for events supported only by IMS phone
664         phone.unregisterForOnHoldTone(handler);
665         phone.unregisterForSuppServiceFailed(handler);
666     }
667 
668     /**
669      * Answers a ringing or waiting call.
670      *
671      * Active call, if any, go on hold.
672      * If active call can't be held, i.e., a background call of the same channel exists,
673      * the active call will be hang up.
674      *
675      * Answering occurs asynchronously, and final notification occurs via
676      * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,
677      * java.lang.Object) registerForPreciseCallStateChanged()}.
678      *
679      * @exception CallStateException when call is not ringing or waiting
680      */
acceptCall(Call ringingCall)681     public void acceptCall(Call ringingCall) throws CallStateException {
682         Phone ringingPhone = ringingCall.getPhone();
683 
684         if (VDBG) {
685             Rlog.d(LOG_TAG, "acceptCall(" +ringingCall + " from " + ringingCall.getPhone() + ")");
686             Rlog.d(LOG_TAG, toString());
687         }
688 
689         if ( hasActiveFgCall() ) {
690             Phone activePhone = getActiveFgCall().getPhone();
691             boolean hasBgCall = ! (activePhone.getBackgroundCall().isIdle());
692             boolean sameChannel = (activePhone == ringingPhone);
693 
694             if (VDBG) {
695                 Rlog.d(LOG_TAG, "hasBgCall: "+ hasBgCall + "sameChannel:" + sameChannel);
696             }
697 
698             if (sameChannel && hasBgCall) {
699                 getActiveFgCall().hangup();
700             } else if (!sameChannel && !hasBgCall) {
701                 activePhone.switchHoldingAndActive();
702             } else if (!sameChannel && hasBgCall) {
703                 getActiveFgCall().hangup();
704             }
705         }
706 
707         // We only support the AUDIO_ONLY video state in this scenario.
708         ringingPhone.acceptCall(VideoProfile.STATE_AUDIO_ONLY);
709 
710         if (VDBG) {
711             Rlog.d(LOG_TAG, "End acceptCall(" +ringingCall + ")");
712             Rlog.d(LOG_TAG, toString());
713         }
714     }
715 
716     /**
717      * Reject (ignore) a ringing call. In GSM, this means UDUB
718      * (User Determined User Busy). Reject occurs asynchronously,
719      * and final notification occurs via
720      * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,
721      * java.lang.Object) registerForPreciseCallStateChanged()}.
722      *
723      * @exception CallStateException when no call is ringing or waiting
724      */
rejectCall(Call ringingCall)725     public void rejectCall(Call ringingCall) throws CallStateException {
726         if (VDBG) {
727             Rlog.d(LOG_TAG, "rejectCall(" +ringingCall + ")");
728             Rlog.d(LOG_TAG, toString());
729         }
730 
731         Phone ringingPhone = ringingCall.getPhone();
732 
733         ringingPhone.rejectCall();
734 
735         if (VDBG) {
736             Rlog.d(LOG_TAG, "End rejectCall(" +ringingCall + ")");
737             Rlog.d(LOG_TAG, toString());
738         }
739     }
740 
741     /**
742      * Places active call on hold, and makes held call active.
743      * Switch occurs asynchronously and may fail.
744      *
745      * There are 4 scenarios
746      * 1. only active call but no held call, aka, hold
747      * 2. no active call but only held call, aka, unhold
748      * 3. both active and held calls from same phone, aka, swap
749      * 4. active and held calls from different phones, aka, phone swap
750      *
751      * Final notification occurs via
752      * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,
753      * java.lang.Object) registerForPreciseCallStateChanged()}.
754      *
755      * @exception CallStateException if active call is ringing, waiting, or
756      * dialing/alerting, or heldCall can't be active.
757      * In these cases, this operation may not be performed.
758      */
switchHoldingAndActive(Call heldCall)759     public void switchHoldingAndActive(Call heldCall) throws CallStateException {
760         Phone activePhone = null;
761         Phone heldPhone = null;
762 
763         if (VDBG) {
764             Rlog.d(LOG_TAG, "switchHoldingAndActive(" +heldCall + ")");
765             Rlog.d(LOG_TAG, toString());
766         }
767 
768         if (hasActiveFgCall()) {
769             activePhone = getActiveFgCall().getPhone();
770         }
771 
772         if (heldCall != null) {
773             heldPhone = heldCall.getPhone();
774         }
775 
776         if (activePhone != null) {
777             activePhone.switchHoldingAndActive();
778         }
779 
780         if (heldPhone != null && heldPhone != activePhone) {
781             heldPhone.switchHoldingAndActive();
782         }
783 
784         if (VDBG) {
785             Rlog.d(LOG_TAG, "End switchHoldingAndActive(" +heldCall + ")");
786             Rlog.d(LOG_TAG, toString());
787         }
788     }
789 
790     /**
791      * Hangup foreground call and resume the specific background call
792      *
793      * Note: this is noop if there is no foreground call or the heldCall is null
794      *
795      * @param heldCall to become foreground
796      * @throws CallStateException
797      */
hangupForegroundResumeBackground(Call heldCall)798     public void hangupForegroundResumeBackground(Call heldCall) throws CallStateException {
799         Phone foregroundPhone = null;
800         Phone backgroundPhone = null;
801 
802         if (VDBG) {
803             Rlog.d(LOG_TAG, "hangupForegroundResumeBackground(" +heldCall + ")");
804             Rlog.d(LOG_TAG, toString());
805         }
806 
807         if (hasActiveFgCall()) {
808             foregroundPhone = getFgPhone();
809             if (heldCall != null) {
810                 backgroundPhone = heldCall.getPhone();
811                 if (foregroundPhone == backgroundPhone) {
812                     getActiveFgCall().hangup();
813                 } else {
814                 // the call to be hangup and resumed belongs to different phones
815                     getActiveFgCall().hangup();
816                     switchHoldingAndActive(heldCall);
817                 }
818             }
819         }
820 
821         if (VDBG) {
822             Rlog.d(LOG_TAG, "End hangupForegroundResumeBackground(" +heldCall + ")");
823             Rlog.d(LOG_TAG, toString());
824         }
825     }
826 
827     /**
828      * Whether or not the phone can conference in the current phone
829      * state--that is, one call holding and one call active.
830      * @return true if the phone can conference; false otherwise.
831      */
canConference(Call heldCall)832     public boolean canConference(Call heldCall) {
833         Phone activePhone = null;
834         Phone heldPhone = null;
835 
836         if (hasActiveFgCall()) {
837             activePhone = getActiveFgCall().getPhone();
838         }
839 
840         if (heldCall != null) {
841             heldPhone = heldCall.getPhone();
842         }
843 
844         return heldPhone.getClass().equals(activePhone.getClass());
845     }
846 
847     /**
848      * Whether or not the phone can conference in the current phone
849      * state--that is, one call holding and one call active.
850      * This method consider the phone object which is specific
851      * to the provided subId.
852      * @return true if the phone can conference; false otherwise.
853      */
canConference(Call heldCall, int subId)854     public boolean canConference(Call heldCall, int subId) {
855         Phone activePhone = null;
856         Phone heldPhone = null;
857 
858         if (hasActiveFgCall(subId)) {
859             activePhone = getActiveFgCall(subId).getPhone();
860         }
861 
862         if (heldCall != null) {
863             heldPhone = heldCall.getPhone();
864         }
865 
866         return heldPhone.getClass().equals(activePhone.getClass());
867     }
868 
869     /**
870      * Conferences holding and active. Conference occurs asynchronously
871      * and may fail. Final notification occurs via
872      * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,
873      * java.lang.Object) registerForPreciseCallStateChanged()}.
874      *
875      * @exception CallStateException if canConference() would return false.
876      * In these cases, this operation may not be performed.
877      */
conference(Call heldCall)878     public void conference(Call heldCall) throws CallStateException {
879         int subId  = heldCall.getPhone().getSubId();
880 
881         if (VDBG) {
882             Rlog.d(LOG_TAG, "conference(" +heldCall + ")");
883             Rlog.d(LOG_TAG, toString());
884         }
885 
886         Phone fgPhone = getFgPhone(subId);
887         if (fgPhone != null) {
888             if (fgPhone instanceof SipPhone) {
889                 ((SipPhone) fgPhone).conference(heldCall);
890             } else if (canConference(heldCall)) {
891                 fgPhone.conference();
892             } else {
893                 throw(new CallStateException("Can't conference foreground and selected background call"));
894             }
895         } else {
896             Rlog.d(LOG_TAG, "conference: fgPhone=null");
897         }
898 
899         if (VDBG) {
900             Rlog.d(LOG_TAG, "End conference(" +heldCall + ")");
901             Rlog.d(LOG_TAG, toString());
902         }
903 
904     }
905 
906     /**
907      * Initiate a new voice connection. This happens asynchronously, so you
908      * cannot assume the audio path is connected (or a call index has been
909      * assigned) until PhoneStateChanged notification has occurred.
910      *
911      * @exception CallStateException if a new outgoing call is not currently
912      * possible because no more call slots exist or a call exists that is
913      * dialing, alerting, ringing, or waiting.  Other errors are
914      * handled asynchronously.
915      */
dial(Phone phone, String dialString, int videoState)916     public Connection dial(Phone phone, String dialString, int videoState)
917             throws CallStateException {
918         int subId = phone.getSubId();
919         Connection result;
920 
921         if (VDBG) {
922             Rlog.d(LOG_TAG, " dial(" + phone + ", "+ dialString + ")" +
923                     " subId = " + subId);
924             Rlog.d(LOG_TAG, toString());
925         }
926 
927         if (!canDial(phone)) {
928             /*
929              * canDial function only checks whether the phone can make a new call.
930              * InCall MMI commmands are basically supplementary services
931              * within a call eg: call hold, call deflection, explicit call transfer etc.
932              */
933             String newDialString = PhoneNumberUtils.stripSeparators(dialString);
934             if (phone.handleInCallMmiCommands(newDialString)) {
935                 return null;
936             } else {
937                 throw new CallStateException("cannot dial in current state");
938             }
939         }
940 
941         if ( hasActiveFgCall(subId) ) {
942             Phone activePhone = getActiveFgCall(subId).getPhone();
943             boolean hasBgCall = !(activePhone.getBackgroundCall().isIdle());
944 
945             if (DBG) {
946                 Rlog.d(LOG_TAG, "hasBgCall: "+ hasBgCall + " sameChannel:" + (activePhone == phone));
947             }
948 
949             // Manipulation between IMS phone and its owner
950             // will be treated in GSM/CDMA phone.
951             Phone imsPhone = phone.getImsPhone();
952             if (activePhone != phone
953                     && (imsPhone == null || imsPhone != activePhone)) {
954                 if (hasBgCall) {
955                     Rlog.d(LOG_TAG, "Hangup");
956                     getActiveFgCall(subId).hangup();
957                 } else {
958                     Rlog.d(LOG_TAG, "Switch");
959                     activePhone.switchHoldingAndActive();
960                 }
961             }
962         }
963 
964         // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
965         //mIsEccDialing = PhoneNumberUtils.isEmergencyNumber(dialString);
966 
967         result = phone.dial(dialString, videoState);
968 
969         if (VDBG) {
970             Rlog.d(LOG_TAG, "End dial(" + phone + ", "+ dialString + ")");
971             Rlog.d(LOG_TAG, toString());
972         }
973 
974         return result;
975     }
976 
977     /**
978      * Initiate a new voice connection. This happens asynchronously, so you
979      * cannot assume the audio path is connected (or a call index has been
980      * assigned) until PhoneStateChanged notification has occurred.
981      *
982      * @exception CallStateException if a new outgoing call is not currently
983      * possible because no more call slots exist or a call exists that is
984      * dialing, alerting, ringing, or waiting.  Other errors are
985      * handled asynchronously.
986      */
dial(Phone phone, String dialString, UUSInfo uusInfo, int videoState)987     public Connection dial(Phone phone, String dialString, UUSInfo uusInfo, int videoState)
988             throws CallStateException {
989         return phone.dial(dialString, uusInfo, videoState, null);
990     }
991 
992     /**
993      * clear disconnect connection for each phone
994      */
clearDisconnected()995     public void clearDisconnected() {
996         for(Phone phone : mPhones) {
997             phone.clearDisconnected();
998         }
999     }
1000 
1001     /**
1002      * clear disconnect connection for a phone specific
1003      * to the provided subId
1004      */
clearDisconnected(int subId)1005     public void clearDisconnected(int subId) {
1006         for(Phone phone : mPhones) {
1007             if (phone.getSubId() == subId) {
1008                 phone.clearDisconnected();
1009             }
1010         }
1011     }
1012 
1013     /**
1014      * Phone can make a call only if ALL of the following are true:
1015      *        - Phone is not powered off
1016      *        - There's no incoming or waiting call
1017      *        - The foreground call is ACTIVE or IDLE or DISCONNECTED.
1018      *          (We mainly need to make sure it *isn't* DIALING or ALERTING.)
1019      * @param phone
1020      * @return true if the phone can make a new call
1021      */
canDial(Phone phone)1022     private boolean canDial(Phone phone) {
1023         int serviceState = phone.getServiceState().getState();
1024         int subId = phone.getSubId();
1025         boolean hasRingingCall = hasActiveRingingCall();
1026         Call.State fgCallState = getActiveFgCallState(subId);
1027 
1028         boolean result = (serviceState != ServiceState.STATE_POWER_OFF
1029                 && !hasRingingCall
1030                 && ((fgCallState == Call.State.ACTIVE)
1031                     || (fgCallState == Call.State.IDLE)
1032                     || (fgCallState == Call.State.DISCONNECTED)
1033                     /*As per 3GPP TS 51.010-1 section 31.13.1.4
1034                     call should be alowed when the foreground
1035                     call is in ALERTING state*/
1036                     || (fgCallState == Call.State.ALERTING)));
1037 
1038         if (result == false) {
1039             Rlog.d(LOG_TAG, "canDial serviceState=" + serviceState
1040                             + " hasRingingCall=" + hasRingingCall
1041                             + " fgCallState=" + fgCallState);
1042         }
1043         return result;
1044     }
1045 
1046     /**
1047      * Whether or not the phone can do explicit call transfer in the current
1048      * phone state--that is, one call holding and one call active.
1049      * @return true if the phone can do explicit call transfer; false otherwise.
1050      */
canTransfer(Call heldCall)1051     public boolean canTransfer(Call heldCall) {
1052         Phone activePhone = null;
1053         Phone heldPhone = null;
1054 
1055         if (hasActiveFgCall()) {
1056             activePhone = getActiveFgCall().getPhone();
1057         }
1058 
1059         if (heldCall != null) {
1060             heldPhone = heldCall.getPhone();
1061         }
1062 
1063         return (heldPhone == activePhone && activePhone.canTransfer());
1064     }
1065 
1066     /**
1067      * Whether or not the phone specific to subId can do explicit call transfer
1068      * in the current phone state--that is, one call holding and one call active.
1069      * @return true if the phone can do explicit call transfer; false otherwise.
1070      */
canTransfer(Call heldCall, int subId)1071     public boolean canTransfer(Call heldCall, int subId) {
1072         Phone activePhone = null;
1073         Phone heldPhone = null;
1074 
1075         if (hasActiveFgCall(subId)) {
1076             activePhone = getActiveFgCall(subId).getPhone();
1077         }
1078 
1079         if (heldCall != null) {
1080             heldPhone = heldCall.getPhone();
1081         }
1082 
1083         return (heldPhone == activePhone && activePhone.canTransfer());
1084     }
1085 
1086     /**
1087      * Connects the held call and active call
1088      * Disconnects the subscriber from both calls
1089      *
1090      * Explicit Call Transfer occurs asynchronously
1091      * and may fail. Final notification occurs via
1092      * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,
1093      * java.lang.Object) registerForPreciseCallStateChanged()}.
1094      *
1095      * @exception CallStateException if canTransfer() would return false.
1096      * In these cases, this operation may not be performed.
1097      */
explicitCallTransfer(Call heldCall)1098     public void explicitCallTransfer(Call heldCall) throws CallStateException {
1099         if (VDBG) {
1100             Rlog.d(LOG_TAG, " explicitCallTransfer(" + heldCall + ")");
1101             Rlog.d(LOG_TAG, toString());
1102         }
1103 
1104         if (canTransfer(heldCall)) {
1105             heldCall.getPhone().explicitCallTransfer();
1106         }
1107 
1108         if (VDBG) {
1109             Rlog.d(LOG_TAG, "End explicitCallTransfer(" + heldCall + ")");
1110             Rlog.d(LOG_TAG, toString());
1111         }
1112 
1113     }
1114 
1115     /**
1116      * Returns a list of MMI codes that are pending for a phone. (They have initiated
1117      * but have not yet completed).
1118      * Presently there is only ever one.
1119      *
1120      * Use <code>registerForMmiInitiate</code>
1121      * and <code>registerForMmiComplete</code> for change notification.
1122      * @return null if phone doesn't have or support mmi code
1123      */
getPendingMmiCodes(Phone phone)1124     public List<? extends MmiCode> getPendingMmiCodes(Phone phone) {
1125         Rlog.e(LOG_TAG, "getPendingMmiCodes not implemented");
1126         return null;
1127     }
1128 
1129     /**
1130      * Sends user response to a USSD REQUEST message.  An MmiCode instance
1131      * representing this response is sent to handlers registered with
1132      * registerForMmiInitiate.
1133      *
1134      * @param ussdMessge    Message to send in the response.
1135      * @return false if phone doesn't support ussd service
1136      */
sendUssdResponse(Phone phone, String ussdMessge)1137     public boolean sendUssdResponse(Phone phone, String ussdMessge) {
1138         Rlog.e(LOG_TAG, "sendUssdResponse not implemented");
1139         return false;
1140     }
1141 
1142     /**
1143      * Mutes or unmutes the microphone for the active call. The microphone
1144      * is automatically unmuted if a call is answered, dialed, or resumed
1145      * from a holding state.
1146      *
1147      * @param muted true to mute the microphone,
1148      * false to activate the microphone.
1149      */
1150 
setMute(boolean muted)1151     public void setMute(boolean muted) {
1152         if (VDBG) {
1153             Rlog.d(LOG_TAG, " setMute(" + muted + ")");
1154             Rlog.d(LOG_TAG, toString());
1155         }
1156 
1157         if (hasActiveFgCall()) {
1158             getActiveFgCall().getPhone().setMute(muted);
1159         }
1160 
1161         if (VDBG) {
1162             Rlog.d(LOG_TAG, "End setMute(" + muted + ")");
1163             Rlog.d(LOG_TAG, toString());
1164         }
1165     }
1166 
1167     /**
1168      * Gets current mute status. Use
1169      * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,
1170      * java.lang.Object) registerForPreciseCallStateChanged()}
1171      * as a change notifcation, although presently phone state changed is not
1172      * fired when setMute() is called.
1173      *
1174      * @return true is muting, false is unmuting
1175      */
getMute()1176     public boolean getMute() {
1177         if (hasActiveFgCall()) {
1178             return getActiveFgCall().getPhone().getMute();
1179         } else if (hasActiveBgCall()) {
1180             return getFirstActiveBgCall().getPhone().getMute();
1181         }
1182         return false;
1183     }
1184 
1185     /**
1186      * Enables or disables echo suppression.
1187      */
setEchoSuppressionEnabled()1188     public void setEchoSuppressionEnabled() {
1189         if (VDBG) {
1190             Rlog.d(LOG_TAG, " setEchoSuppression()");
1191             Rlog.d(LOG_TAG, toString());
1192         }
1193 
1194         if (hasActiveFgCall()) {
1195             getActiveFgCall().getPhone().setEchoSuppressionEnabled();
1196         }
1197 
1198         if (VDBG) {
1199             Rlog.d(LOG_TAG, "End setEchoSuppression()");
1200             Rlog.d(LOG_TAG, toString());
1201         }
1202     }
1203 
1204     /**
1205      * Play a DTMF tone on the active call.
1206      *
1207      * @param c should be one of 0-9, '*' or '#'. Other values will be
1208      * silently ignored.
1209      * @return false if no active call or the active call doesn't support
1210      *         dtmf tone
1211      */
sendDtmf(char c)1212     public boolean sendDtmf(char c) {
1213         boolean result = false;
1214 
1215         if (VDBG) {
1216             Rlog.d(LOG_TAG, " sendDtmf(" + c + ")");
1217             Rlog.d(LOG_TAG, toString());
1218         }
1219 
1220         if (hasActiveFgCall()) {
1221             getActiveFgCall().getPhone().sendDtmf(c);
1222             result = true;
1223         }
1224 
1225         if (VDBG) {
1226             Rlog.d(LOG_TAG, "End sendDtmf(" + c + ")");
1227             Rlog.d(LOG_TAG, toString());
1228         }
1229         return result;
1230     }
1231 
1232     /**
1233      * Start to paly a DTMF tone on the active call.
1234      * or there is a playing DTMF tone.
1235      * @param c should be one of 0-9, '*' or '#'. Other values will be
1236      * silently ignored.
1237      *
1238      * @return false if no active call or the active call doesn't support
1239      *         dtmf tone
1240      */
startDtmf(char c)1241     public boolean startDtmf(char c) {
1242         boolean result = false;
1243 
1244         if (VDBG) {
1245             Rlog.d(LOG_TAG, " startDtmf(" + c + ")");
1246             Rlog.d(LOG_TAG, toString());
1247         }
1248 
1249         if (hasActiveFgCall()) {
1250             getActiveFgCall().getPhone().startDtmf(c);
1251             result = true;
1252         }
1253 
1254         if (VDBG) {
1255             Rlog.d(LOG_TAG, "End startDtmf(" + c + ")");
1256             Rlog.d(LOG_TAG, toString());
1257         }
1258 
1259         return result;
1260     }
1261 
1262     /**
1263      * Stop the playing DTMF tone. Ignored if there is no playing DTMF
1264      * tone or no active call.
1265      */
stopDtmf()1266     public void stopDtmf() {
1267         if (VDBG) {
1268             Rlog.d(LOG_TAG, " stopDtmf()" );
1269             Rlog.d(LOG_TAG, toString());
1270         }
1271 
1272         if (hasActiveFgCall()) getFgPhone().stopDtmf();
1273 
1274         if (VDBG) {
1275             Rlog.d(LOG_TAG, "End stopDtmf()");
1276             Rlog.d(LOG_TAG, toString());
1277         }
1278     }
1279 
1280     /**
1281      * send burst DTMF tone, it can send the string as single character or multiple character
1282      * ignore if there is no active call or not valid digits string.
1283      * Valid digit means only includes characters ISO-LATIN characters 0-9, *, #
1284      * The difference between sendDtmf and sendBurstDtmf is sendDtmf only sends one character,
1285      * this api can send single character and multiple character, also, this api has response
1286      * back to caller.
1287      *
1288      * @param dtmfString is string representing the dialing digit(s) in the active call
1289      * @param on the DTMF ON length in milliseconds, or 0 for default
1290      * @param off the DTMF OFF length in milliseconds, or 0 for default
1291      * @param onComplete is the callback message when the action is processed by BP
1292      *
1293      */
sendBurstDtmf(String dtmfString, int on, int off, Message onComplete)1294     public boolean sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) {
1295         if (hasActiveFgCall()) {
1296             getActiveFgCall().getPhone().sendBurstDtmf(dtmfString, on, off, onComplete);
1297             return true;
1298         }
1299         return false;
1300     }
1301 
1302     /**
1303      * Notifies when a voice connection has disconnected, either due to local
1304      * or remote hangup or error.
1305      *
1306      *  Messages received from this will have the following members:<p>
1307      *  <ul><li>Message.obj will be an AsyncResult</li>
1308      *  <li>AsyncResult.userObj = obj</li>
1309      *  <li>AsyncResult.result = a Connection object that is
1310      *  no longer connected.</li></ul>
1311      */
registerForDisconnect(Handler h, int what, Object obj)1312     public void registerForDisconnect(Handler h, int what, Object obj) {
1313         mDisconnectRegistrants.addUnique(h, what, obj);
1314     }
1315 
1316     /**
1317      * Unregisters for voice disconnection notification.
1318      * Extraneous calls are tolerated silently
1319      */
unregisterForDisconnect(Handler h)1320     public void unregisterForDisconnect(Handler h){
1321         mDisconnectRegistrants.remove(h);
1322     }
1323 
1324     /**
1325      * Register for getting notifications for change in the Call State {@link Call.State}
1326      * This is called PreciseCallState because the call state is more precise than what
1327      * can be obtained using the {@link PhoneStateListener}
1328      *
1329      * Resulting events will have an AsyncResult in <code>Message.obj</code>.
1330      * AsyncResult.userData will be set to the obj argument here.
1331      * The <em>h</em> parameter is held only by a weak reference.
1332      */
registerForPreciseCallStateChanged(Handler h, int what, Object obj)1333     public void registerForPreciseCallStateChanged(Handler h, int what, Object obj){
1334         mPreciseCallStateRegistrants.addUnique(h, what, obj);
1335     }
1336 
1337     /**
1338      * Unregisters for voice call state change notifications.
1339      * Extraneous calls are tolerated silently.
1340      */
unregisterForPreciseCallStateChanged(Handler h)1341     public void unregisterForPreciseCallStateChanged(Handler h){
1342         mPreciseCallStateRegistrants.remove(h);
1343     }
1344 
1345     /**
1346      * Notifies when a previously untracked non-ringing/waiting connection has appeared.
1347      * This is likely due to some other entity (eg, SIM card application) initiating a call.
1348      */
registerForUnknownConnection(Handler h, int what, Object obj)1349     public void registerForUnknownConnection(Handler h, int what, Object obj){
1350         mUnknownConnectionRegistrants.addUnique(h, what, obj);
1351     }
1352 
1353     /**
1354      * Unregisters for unknown connection notifications.
1355      */
unregisterForUnknownConnection(Handler h)1356     public void unregisterForUnknownConnection(Handler h){
1357         mUnknownConnectionRegistrants.remove(h);
1358     }
1359 
1360 
1361     /**
1362      * Notifies when a new ringing or waiting connection has appeared.<p>
1363      *
1364      *  Messages received from this:
1365      *  Message.obj will be an AsyncResult
1366      *  AsyncResult.userObj = obj
1367      *  AsyncResult.result = a Connection. <p>
1368      *  Please check Connection.isRinging() to make sure the Connection
1369      *  has not dropped since this message was posted.
1370      *  If Connection.isRinging() is true, then
1371      *   Connection.getCall() == Phone.getRingingCall()
1372      */
registerForNewRingingConnection(Handler h, int what, Object obj)1373     public void registerForNewRingingConnection(Handler h, int what, Object obj){
1374         mNewRingingConnectionRegistrants.addUnique(h, what, obj);
1375     }
1376 
1377     /**
1378      * Unregisters for new ringing connection notification.
1379      * Extraneous calls are tolerated silently
1380      */
1381 
unregisterForNewRingingConnection(Handler h)1382     public void unregisterForNewRingingConnection(Handler h){
1383         mNewRingingConnectionRegistrants.remove(h);
1384     }
1385 
1386     /**
1387      * Notifies when an incoming call rings.<p>
1388      *
1389      *  Messages received from this:
1390      *  Message.obj will be an AsyncResult
1391      *  AsyncResult.userObj = obj
1392      *  AsyncResult.result = a Connection. <p>
1393      */
registerForIncomingRing(Handler h, int what, Object obj)1394     public void registerForIncomingRing(Handler h, int what, Object obj){
1395         mIncomingRingRegistrants.addUnique(h, what, obj);
1396     }
1397 
1398     /**
1399      * Unregisters for ring notification.
1400      * Extraneous calls are tolerated silently
1401      */
1402 
unregisterForIncomingRing(Handler h)1403     public void unregisterForIncomingRing(Handler h){
1404         mIncomingRingRegistrants.remove(h);
1405     }
1406 
1407     /**
1408      * Notifies when out-band ringback tone is needed.<p>
1409      *
1410      *  Messages received from this:
1411      *  Message.obj will be an AsyncResult
1412      *  AsyncResult.userObj = obj
1413      *  AsyncResult.result = boolean, true to start play ringback tone
1414      *                       and false to stop. <p>
1415      */
registerForRingbackTone(Handler h, int what, Object obj)1416     public void registerForRingbackTone(Handler h, int what, Object obj){
1417         mRingbackToneRegistrants.addUnique(h, what, obj);
1418     }
1419 
1420     /**
1421      * Unregisters for ringback tone notification.
1422      */
1423 
unregisterForRingbackTone(Handler h)1424     public void unregisterForRingbackTone(Handler h){
1425         mRingbackToneRegistrants.remove(h);
1426     }
1427 
1428     /**
1429      * Notifies when out-band on-hold tone is needed.<p>
1430      *
1431      *  Messages received from this:
1432      *  Message.obj will be an AsyncResult
1433      *  AsyncResult.userObj = obj
1434      *  AsyncResult.result = boolean, true to start play on-hold tone
1435      *                       and false to stop. <p>
1436      */
registerForOnHoldTone(Handler h, int what, Object obj)1437     public void registerForOnHoldTone(Handler h, int what, Object obj){
1438         mOnHoldToneRegistrants.addUnique(h, what, obj);
1439     }
1440 
1441     /**
1442      * Unregisters for on-hold tone notification.
1443      */
1444 
unregisterForOnHoldTone(Handler h)1445     public void unregisterForOnHoldTone(Handler h){
1446         mOnHoldToneRegistrants.remove(h);
1447     }
1448 
1449     /**
1450      * Registers the handler to reset the uplink mute state to get
1451      * uplink audio.
1452      */
registerForResendIncallMute(Handler h, int what, Object obj)1453     public void registerForResendIncallMute(Handler h, int what, Object obj){
1454         mResendIncallMuteRegistrants.addUnique(h, what, obj);
1455     }
1456 
1457     /**
1458      * Unregisters for resend incall mute notifications.
1459      */
unregisterForResendIncallMute(Handler h)1460     public void unregisterForResendIncallMute(Handler h){
1461         mResendIncallMuteRegistrants.remove(h);
1462     }
1463 
1464     /**
1465      * Register for notifications of initiation of a new MMI code request.
1466      * MMI codes for GSM are discussed in 3GPP TS 22.030.<p>
1467      *
1468      * Example: If Phone.dial is called with "*#31#", then the app will
1469      * be notified here.<p>
1470      *
1471      * The returned <code>Message.obj</code> will contain an AsyncResult.
1472      *
1473      * <code>obj.result</code> will be an "MmiCode" object.
1474      */
registerForMmiInitiate(Handler h, int what, Object obj)1475     public void registerForMmiInitiate(Handler h, int what, Object obj){
1476         mMmiInitiateRegistrants.addUnique(h, what, obj);
1477     }
1478 
1479     /**
1480      * Unregisters for new MMI initiate notification.
1481      * Extraneous calls are tolerated silently
1482      */
unregisterForMmiInitiate(Handler h)1483     public void unregisterForMmiInitiate(Handler h){
1484         mMmiInitiateRegistrants.remove(h);
1485     }
1486 
1487     /**
1488      * Register for notifications that an MMI request has completed
1489      * its network activity and is in its final state. This may mean a state
1490      * of COMPLETE, FAILED, or CANCELLED.
1491      *
1492      * <code>Message.obj</code> will contain an AsyncResult.
1493      * <code>obj.result</code> will be an "MmiCode" object
1494      */
registerForMmiComplete(Handler h, int what, Object obj)1495     public void registerForMmiComplete(Handler h, int what, Object obj){
1496         mMmiCompleteRegistrants.addUnique(h, what, obj);
1497     }
1498 
1499     /**
1500      * Unregisters for MMI complete notification.
1501      * Extraneous calls are tolerated silently
1502      */
unregisterForMmiComplete(Handler h)1503     public void unregisterForMmiComplete(Handler h){
1504         mMmiCompleteRegistrants.remove(h);
1505     }
1506 
1507     /**
1508      * Registration point for Ecm timer reset
1509      * @param h handler to notify
1510      * @param what user-defined message code
1511      * @param obj placed in Message.obj
1512      */
registerForEcmTimerReset(Handler h, int what, Object obj)1513     public void registerForEcmTimerReset(Handler h, int what, Object obj){
1514         mEcmTimerResetRegistrants.addUnique(h, what, obj);
1515     }
1516 
1517     /**
1518      * Unregister for notification for Ecm timer reset
1519      * @param h Handler to be removed from the registrant list.
1520      */
unregisterForEcmTimerReset(Handler h)1521     public void unregisterForEcmTimerReset(Handler h){
1522         mEcmTimerResetRegistrants.remove(h);
1523     }
1524 
1525     /**
1526      * Register for ServiceState changed.
1527      * Message.obj will contain an AsyncResult.
1528      * AsyncResult.result will be a ServiceState instance
1529      */
registerForServiceStateChanged(Handler h, int what, Object obj)1530     public void registerForServiceStateChanged(Handler h, int what, Object obj){
1531         mServiceStateChangedRegistrants.addUnique(h, what, obj);
1532     }
1533 
1534     /**
1535      * Unregisters for ServiceStateChange notification.
1536      * Extraneous calls are tolerated silently
1537      */
unregisterForServiceStateChanged(Handler h)1538     public void unregisterForServiceStateChanged(Handler h){
1539         mServiceStateChangedRegistrants.remove(h);
1540     }
1541 
1542     /**
1543      * Register for notifications when a supplementary service attempt fails.
1544      * Message.obj will contain an AsyncResult.
1545      *
1546      * @param h Handler that receives the notification message.
1547      * @param what User-defined message code.
1548      * @param obj User object.
1549      */
registerForSuppServiceFailed(Handler h, int what, Object obj)1550     public void registerForSuppServiceFailed(Handler h, int what, Object obj){
1551         mSuppServiceFailedRegistrants.addUnique(h, what, obj);
1552     }
1553 
1554     /**
1555      * Unregister for notifications when a supplementary service attempt fails.
1556      * Extraneous calls are tolerated silently
1557      *
1558      * @param h Handler to be removed from the registrant list.
1559      */
unregisterForSuppServiceFailed(Handler h)1560     public void unregisterForSuppServiceFailed(Handler h){
1561         mSuppServiceFailedRegistrants.remove(h);
1562     }
1563 
1564     /**
1565      * Register for notifications when a sInCall VoicePrivacy is enabled
1566      *
1567      * @param h Handler that receives the notification message.
1568      * @param what User-defined message code.
1569      * @param obj User object.
1570      */
registerForInCallVoicePrivacyOn(Handler h, int what, Object obj)1571     public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj){
1572         mInCallVoicePrivacyOnRegistrants.addUnique(h, what, obj);
1573     }
1574 
1575     /**
1576      * Unregister for notifications when a sInCall VoicePrivacy is enabled
1577      *
1578      * @param h Handler to be removed from the registrant list.
1579      */
unregisterForInCallVoicePrivacyOn(Handler h)1580     public void unregisterForInCallVoicePrivacyOn(Handler h){
1581         mInCallVoicePrivacyOnRegistrants.remove(h);
1582     }
1583 
1584     /**
1585      * Register for notifications when a sInCall VoicePrivacy is disabled
1586      *
1587      * @param h Handler that receives the notification message.
1588      * @param what User-defined message code.
1589      * @param obj User object.
1590      */
registerForInCallVoicePrivacyOff(Handler h, int what, Object obj)1591     public void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj){
1592         mInCallVoicePrivacyOffRegistrants.addUnique(h, what, obj);
1593     }
1594 
1595     /**
1596      * Unregister for notifications when a sInCall VoicePrivacy is disabled
1597      *
1598      * @param h Handler to be removed from the registrant list.
1599      */
unregisterForInCallVoicePrivacyOff(Handler h)1600     public void unregisterForInCallVoicePrivacyOff(Handler h){
1601         mInCallVoicePrivacyOffRegistrants.remove(h);
1602     }
1603 
1604     /**
1605      * Register for notifications when CDMA call waiting comes
1606      *
1607      * @param h Handler that receives the notification message.
1608      * @param what User-defined message code.
1609      * @param obj User object.
1610      */
registerForCallWaiting(Handler h, int what, Object obj)1611     public void registerForCallWaiting(Handler h, int what, Object obj){
1612         mCallWaitingRegistrants.addUnique(h, what, obj);
1613     }
1614 
1615     /**
1616      * Unregister for notifications when CDMA Call waiting comes
1617      * @param h Handler to be removed from the registrant list.
1618      */
unregisterForCallWaiting(Handler h)1619     public void unregisterForCallWaiting(Handler h){
1620         mCallWaitingRegistrants.remove(h);
1621     }
1622 
1623 
1624     /**
1625      * Register for signal information notifications from the network.
1626      * Message.obj will contain an AsyncResult.
1627      * AsyncResult.result will be a SuppServiceNotification instance.
1628      *
1629      * @param h Handler that receives the notification message.
1630      * @param what User-defined message code.
1631      * @param obj User object.
1632      */
1633 
registerForSignalInfo(Handler h, int what, Object obj)1634     public void registerForSignalInfo(Handler h, int what, Object obj){
1635         mSignalInfoRegistrants.addUnique(h, what, obj);
1636     }
1637 
1638     /**
1639      * Unregisters for signal information notifications.
1640      * Extraneous calls are tolerated silently
1641      *
1642      * @param h Handler to be removed from the registrant list.
1643      */
unregisterForSignalInfo(Handler h)1644     public void unregisterForSignalInfo(Handler h){
1645         mSignalInfoRegistrants.remove(h);
1646     }
1647 
1648     /**
1649      * Register for display information notifications from the network.
1650      * Message.obj will contain an AsyncResult.
1651      * AsyncResult.result will be a SuppServiceNotification instance.
1652      *
1653      * @param h Handler that receives the notification message.
1654      * @param what User-defined message code.
1655      * @param obj User object.
1656      */
registerForDisplayInfo(Handler h, int what, Object obj)1657     public void registerForDisplayInfo(Handler h, int what, Object obj){
1658         mDisplayInfoRegistrants.addUnique(h, what, obj);
1659     }
1660 
1661     /**
1662      * Unregisters for display information notifications.
1663      * Extraneous calls are tolerated silently
1664      *
1665      * @param h Handler to be removed from the registrant list.
1666      */
unregisterForDisplayInfo(Handler h)1667     public void unregisterForDisplayInfo(Handler h) {
1668         mDisplayInfoRegistrants.remove(h);
1669     }
1670 
1671     /**
1672      * Register for notifications when CDMA OTA Provision status change
1673      *
1674      * @param h Handler that receives the notification message.
1675      * @param what User-defined message code.
1676      * @param obj User object.
1677      */
registerForCdmaOtaStatusChange(Handler h, int what, Object obj)1678     public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj){
1679         mCdmaOtaStatusChangeRegistrants.addUnique(h, what, obj);
1680     }
1681 
1682     /**
1683      * Unregister for notifications when CDMA OTA Provision status change
1684      * @param h Handler to be removed from the registrant list.
1685      */
unregisterForCdmaOtaStatusChange(Handler h)1686     public void unregisterForCdmaOtaStatusChange(Handler h){
1687         mCdmaOtaStatusChangeRegistrants.remove(h);
1688     }
1689 
1690     /**
1691      * Registration point for subscription info ready
1692      * @param h handler to notify
1693      * @param what what code of message when delivered
1694      * @param obj placed in Message.obj
1695      */
registerForSubscriptionInfoReady(Handler h, int what, Object obj)1696     public void registerForSubscriptionInfoReady(Handler h, int what, Object obj){
1697         mSubscriptionInfoReadyRegistrants.addUnique(h, what, obj);
1698     }
1699 
1700     /**
1701      * Unregister for notifications for subscription info
1702      * @param h Handler to be removed from the registrant list.
1703      */
unregisterForSubscriptionInfoReady(Handler h)1704     public void unregisterForSubscriptionInfoReady(Handler h){
1705         mSubscriptionInfoReadyRegistrants.remove(h);
1706     }
1707 
1708     /**
1709      * Sets an event to be fired when the telephony system processes
1710      * a post-dial character on an outgoing call.<p>
1711      *
1712      * Messages of type <code>what</code> will be sent to <code>h</code>.
1713      * The <code>obj</code> field of these Message's will be instances of
1714      * <code>AsyncResult</code>. <code>Message.obj.result</code> will be
1715      * a Connection object.<p>
1716      *
1717      * Message.arg1 will be the post dial character being processed,
1718      * or 0 ('\0') if end of string.<p>
1719      *
1720      * If Connection.getPostDialState() == WAIT,
1721      * the application must call
1722      * {@link com.android.internal.telephony.Connection#proceedAfterWaitChar()
1723      * Connection.proceedAfterWaitChar()} or
1724      * {@link com.android.internal.telephony.Connection#cancelPostDial()
1725      * Connection.cancelPostDial()}
1726      * for the telephony system to continue playing the post-dial
1727      * DTMF sequence.<p>
1728      *
1729      * If Connection.getPostDialState() == WILD,
1730      * the application must call
1731      * {@link com.android.internal.telephony.Connection#proceedAfterWildChar
1732      * Connection.proceedAfterWildChar()}
1733      * or
1734      * {@link com.android.internal.telephony.Connection#cancelPostDial()
1735      * Connection.cancelPostDial()}
1736      * for the telephony system to continue playing the
1737      * post-dial DTMF sequence.<p>
1738      *
1739      */
registerForPostDialCharacter(Handler h, int what, Object obj)1740     public void registerForPostDialCharacter(Handler h, int what, Object obj){
1741         mPostDialCharacterRegistrants.addUnique(h, what, obj);
1742     }
1743 
unregisterForPostDialCharacter(Handler h)1744     public void unregisterForPostDialCharacter(Handler h){
1745         mPostDialCharacterRegistrants.remove(h);
1746     }
1747 
1748     /**
1749      * Register for TTY mode change notifications from the network.
1750      * Message.obj will contain an AsyncResult.
1751      * AsyncResult.result will be an Integer containing new mode.
1752      *
1753      * @param h Handler that receives the notification message.
1754      * @param what User-defined message code.
1755      * @param obj User object.
1756      */
registerForTtyModeReceived(Handler h, int what, Object obj)1757     public void registerForTtyModeReceived(Handler h, int what, Object obj){
1758         mTtyModeReceivedRegistrants.addUnique(h, what, obj);
1759     }
1760 
1761     /**
1762      * Unregisters for TTY mode change notifications.
1763      * Extraneous calls are tolerated silently
1764      *
1765      * @param h Handler to be removed from the registrant list.
1766      */
unregisterForTtyModeReceived(Handler h)1767     public void unregisterForTtyModeReceived(Handler h) {
1768         mTtyModeReceivedRegistrants.remove(h);
1769     }
1770 
1771     /* APIs to access foregroudCalls, backgroudCalls, and ringingCalls
1772      * 1. APIs to access list of calls
1773      * 2. APIs to check if any active call, which has connection other than
1774      * disconnected ones, pleaser refer to Call.isIdle()
1775      * 3. APIs to return first active call
1776      * 4. APIs to return the connections of first active call
1777      * 5. APIs to return other property of first active call
1778      */
1779 
1780     /**
1781      * @return list of all ringing calls
1782      */
getRingingCalls()1783     public List<Call> getRingingCalls() {
1784         return Collections.unmodifiableList(mRingingCalls);
1785     }
1786 
1787     /**
1788      * @return list of all foreground calls
1789      */
getForegroundCalls()1790     public List<Call> getForegroundCalls() {
1791         return Collections.unmodifiableList(mForegroundCalls);
1792     }
1793 
1794     /**
1795      * @return list of all background calls
1796      */
getBackgroundCalls()1797     public List<Call> getBackgroundCalls() {
1798         return Collections.unmodifiableList(mBackgroundCalls);
1799     }
1800 
1801     /**
1802      * Return true if there is at least one active foreground call
1803      */
hasActiveFgCall()1804     public boolean hasActiveFgCall() {
1805         return (getFirstActiveCall(mForegroundCalls) != null);
1806     }
1807 
1808     /**
1809      * Return true if there is at least one active foreground call
1810      * on a particular subId or an active sip call
1811      */
hasActiveFgCall(int subId)1812     public boolean hasActiveFgCall(int subId) {
1813         return (getFirstActiveCall(mForegroundCalls, subId) != null);
1814     }
1815 
1816     /**
1817      * Return true if there is at least one active background call
1818      */
hasActiveBgCall()1819     public boolean hasActiveBgCall() {
1820         // TODO since hasActiveBgCall may get called often
1821         // better to cache it to improve performance
1822         return (getFirstActiveCall(mBackgroundCalls) != null);
1823     }
1824 
1825     /**
1826      * Return true if there is at least one active background call
1827      * on a particular subId or an active sip call
1828      */
hasActiveBgCall(int subId)1829     public boolean hasActiveBgCall(int subId) {
1830         // TODO since hasActiveBgCall may get called often
1831         // better to cache it to improve performance
1832         return (getFirstActiveCall(mBackgroundCalls, subId) != null);
1833     }
1834 
1835     /**
1836      * Return true if there is at least one active ringing call
1837      *
1838      */
hasActiveRingingCall()1839     public boolean hasActiveRingingCall() {
1840         return (getFirstActiveCall(mRingingCalls) != null);
1841     }
1842 
1843     /**
1844      * Return true if there is at least one active ringing call
1845      */
hasActiveRingingCall(int subId)1846     public boolean hasActiveRingingCall(int subId) {
1847         return (getFirstActiveCall(mRingingCalls, subId) != null);
1848     }
1849 
1850     /**
1851      * return the active foreground call from foreground calls
1852      *
1853      * Active call means the call is NOT in Call.State.IDLE
1854      *
1855      * 1. If there is active foreground call, return it
1856      * 2. If there is no active foreground call, return the
1857      *    foreground call associated with default phone, which state is IDLE.
1858      * 3. If there is no phone registered at all, return null.
1859      *
1860      */
getActiveFgCall()1861     public Call getActiveFgCall() {
1862         Call call = getFirstNonIdleCall(mForegroundCalls);
1863         if (call == null) {
1864             call = (mDefaultPhone == null)
1865                     ? null
1866                     : mDefaultPhone.getForegroundCall();
1867         }
1868         return call;
1869     }
1870 
getActiveFgCall(int subId)1871     public Call getActiveFgCall(int subId) {
1872         Call call = getFirstNonIdleCall(mForegroundCalls, subId);
1873         if (call == null) {
1874             Phone phone = getPhone(subId);
1875             call = (phone == null)
1876                     ? null
1877                     : phone.getForegroundCall();
1878         }
1879         return call;
1880     }
1881 
1882     // Returns the first call that is not in IDLE state. If both active calls
1883     // and disconnecting/disconnected calls exist, return the first active call.
getFirstNonIdleCall(List<Call> calls)1884     private Call getFirstNonIdleCall(List<Call> calls) {
1885         Call result = null;
1886         for (Call call : calls) {
1887             if (!call.isIdle()) {
1888                 return call;
1889             } else if (call.getState() != Call.State.IDLE) {
1890                 if (result == null) result = call;
1891             }
1892         }
1893         return result;
1894     }
1895 
1896     // Returns the first call that is not in IDLE state. If both active calls
1897     // and disconnecting/disconnected calls exist, return the first active call.
getFirstNonIdleCall(List<Call> calls, int subId)1898     private Call getFirstNonIdleCall(List<Call> calls, int subId) {
1899         Call result = null;
1900         for (Call call : calls) {
1901             if ((call.getPhone().getSubId() == subId) ||
1902                     (call.getPhone() instanceof SipPhone)) {
1903                 if (!call.isIdle()) {
1904                     return call;
1905                 } else if (call.getState() != Call.State.IDLE) {
1906                     if (result == null) result = call;
1907                 }
1908             }
1909         }
1910         return result;
1911     }
1912 
1913     /**
1914      * return one active background call from background calls
1915      *
1916      * Active call means the call is NOT idle defined by Call.isIdle()
1917      *
1918      * 1. If there is only one active background call, return it
1919      * 2. If there is more than one active background call, return the first one
1920      * 3. If there is no active background call, return the background call
1921      *    associated with default phone, which state is IDLE.
1922      * 4. If there is no background call at all, return null.
1923      *
1924      * Complete background calls list can be get by getBackgroundCalls()
1925      */
getFirstActiveBgCall()1926     public Call getFirstActiveBgCall() {
1927         Call call = getFirstNonIdleCall(mBackgroundCalls);
1928         if (call == null) {
1929             call = (mDefaultPhone == null)
1930                     ? null
1931                     : mDefaultPhone.getBackgroundCall();
1932         }
1933         return call;
1934     }
1935 
1936     /**
1937      * return one active background call from background calls of the
1938      * requested subId.
1939      *
1940      * Active call means the call is NOT idle defined by Call.isIdle()
1941      *
1942      * 1. If there is only one active background call on given sub or
1943      *    on SIP Phone, return it
1944      * 2. If there is more than one active background call, return the background call
1945      *    associated with the active sub.
1946      * 3. If there is no background call at all, return null.
1947      *
1948      * Complete background calls list can be get by getBackgroundCalls()
1949      */
getFirstActiveBgCall(int subId)1950     public Call getFirstActiveBgCall(int subId) {
1951         Phone phone = getPhone(subId);
1952         if (hasMoreThanOneHoldingCall(subId)) {
1953             return phone.getBackgroundCall();
1954         } else {
1955             Call call = getFirstNonIdleCall(mBackgroundCalls, subId);
1956             if (call == null) {
1957                 call = (phone == null)
1958                         ? null
1959                         : phone.getBackgroundCall();
1960             }
1961             return call;
1962         }
1963     }
1964 
1965     /**
1966      * return one active ringing call from ringing calls
1967      *
1968      * Active call means the call is NOT idle defined by Call.isIdle()
1969      *
1970      * 1. If there is only one active ringing call, return it
1971      * 2. If there is more than one active ringing call, return the first one
1972      * 3. If there is no active ringing call, return the ringing call
1973      *    associated with default phone, which state is IDLE.
1974      * 4. If there is no ringing call at all, return null.
1975      *
1976      * Complete ringing calls list can be get by getRingingCalls()
1977      */
getFirstActiveRingingCall()1978     public Call getFirstActiveRingingCall() {
1979         Call call = getFirstNonIdleCall(mRingingCalls);
1980         if (call == null) {
1981             call = (mDefaultPhone == null)
1982                     ? null
1983                     : mDefaultPhone.getRingingCall();
1984         }
1985         return call;
1986     }
1987 
getFirstActiveRingingCall(int subId)1988     public Call getFirstActiveRingingCall(int subId) {
1989         Phone phone = getPhone(subId);
1990         Call call = getFirstNonIdleCall(mRingingCalls, subId);
1991         if (call == null) {
1992             call = (phone == null)
1993                     ? null
1994                     : phone.getRingingCall();
1995         }
1996         return call;
1997     }
1998 
1999     /**
2000      * @return the state of active foreground call
2001      * return IDLE if there is no active foreground call
2002      */
getActiveFgCallState()2003     public Call.State getActiveFgCallState() {
2004         Call fgCall = getActiveFgCall();
2005 
2006         if (fgCall != null) {
2007             return fgCall.getState();
2008         }
2009 
2010         return Call.State.IDLE;
2011     }
2012 
getActiveFgCallState(int subId)2013     public Call.State getActiveFgCallState(int subId) {
2014         Call fgCall = getActiveFgCall(subId);
2015 
2016         if (fgCall != null) {
2017             return fgCall.getState();
2018         }
2019 
2020         return Call.State.IDLE;
2021     }
2022 
2023     /**
2024      * @return the connections of active foreground call
2025      * return empty list if there is no active foreground call
2026      */
getFgCallConnections()2027     public List<Connection> getFgCallConnections() {
2028         Call fgCall = getActiveFgCall();
2029         if ( fgCall != null) {
2030             return fgCall.getConnections();
2031         }
2032         return mEmptyConnections;
2033     }
2034 
2035     /**
2036      * @return the connections of active foreground call
2037      * return empty list if there is no active foreground call
2038      */
getFgCallConnections(int subId)2039     public List<Connection> getFgCallConnections(int subId) {
2040         Call fgCall = getActiveFgCall(subId);
2041         if ( fgCall != null) {
2042             return fgCall.getConnections();
2043         }
2044         return mEmptyConnections;
2045     }
2046 
2047     /**
2048      * @return the connections of active background call
2049      * return empty list if there is no active background call
2050      */
getBgCallConnections()2051     public List<Connection> getBgCallConnections() {
2052         Call bgCall = getFirstActiveBgCall();
2053         if ( bgCall != null) {
2054             return bgCall.getConnections();
2055         }
2056         return mEmptyConnections;
2057     }
2058 
2059     /**
2060      * @return the connections of active background call
2061      * return empty list if there is no active background call
2062      */
getBgCallConnections(int subId)2063     public List<Connection> getBgCallConnections(int subId) {
2064         Call bgCall = getFirstActiveBgCall(subId);
2065         if ( bgCall != null) {
2066             return bgCall.getConnections();
2067         }
2068         return mEmptyConnections;
2069     }
2070 
2071     /**
2072      * @return the latest connection of active foreground call
2073      * return null if there is no active foreground call
2074      */
getFgCallLatestConnection()2075     public Connection getFgCallLatestConnection() {
2076         Call fgCall = getActiveFgCall();
2077         if ( fgCall != null) {
2078             return fgCall.getLatestConnection();
2079         }
2080         return null;
2081     }
2082 
2083     /**
2084      * @return the latest connection of active foreground call
2085      * return null if there is no active foreground call
2086      */
getFgCallLatestConnection(int subId)2087     public Connection getFgCallLatestConnection(int subId) {
2088         Call fgCall = getActiveFgCall(subId);
2089         if ( fgCall != null) {
2090             return fgCall.getLatestConnection();
2091         }
2092         return null;
2093     }
2094 
2095     /**
2096      * @return true if there is at least one Foreground call in disconnected state
2097      */
hasDisconnectedFgCall()2098     public boolean hasDisconnectedFgCall() {
2099         return (getFirstCallOfState(mForegroundCalls, Call.State.DISCONNECTED) != null);
2100     }
2101 
2102     /**
2103      * @return true if there is at least one Foreground call in disconnected state
2104      */
hasDisconnectedFgCall(int subId)2105     public boolean hasDisconnectedFgCall(int subId) {
2106         return (getFirstCallOfState(mForegroundCalls, Call.State.DISCONNECTED,
2107                 subId) != null);
2108     }
2109 
2110     /**
2111      * @return true if there is at least one background call in disconnected state
2112      */
hasDisconnectedBgCall()2113     public boolean hasDisconnectedBgCall() {
2114         return (getFirstCallOfState(mBackgroundCalls, Call.State.DISCONNECTED) != null);
2115     }
2116 
2117     /**
2118      * @return true if there is at least one background call in disconnected state
2119      */
hasDisconnectedBgCall(int subId)2120     public boolean hasDisconnectedBgCall(int subId) {
2121         return (getFirstCallOfState(mBackgroundCalls, Call.State.DISCONNECTED,
2122                 subId) != null);
2123     }
2124 
2125 
2126     /**
2127      * @return the first active call from a call list
2128      */
getFirstActiveCall(ArrayList<Call> calls)2129     private  Call getFirstActiveCall(ArrayList<Call> calls) {
2130         for (Call call : calls) {
2131             if (!call.isIdle()) {
2132                 return call;
2133             }
2134         }
2135         return null;
2136     }
2137 
2138     /**
2139      * @return the first active call from a call list
2140      */
getFirstActiveCall(ArrayList<Call> calls, int subId)2141     private  Call getFirstActiveCall(ArrayList<Call> calls, int subId) {
2142         for (Call call : calls) {
2143             if ((!call.isIdle()) && ((call.getPhone().getSubId() == subId) ||
2144                     (call.getPhone() instanceof SipPhone))) {
2145                 return call;
2146             }
2147         }
2148         return null;
2149     }
2150 
2151     /**
2152      * @return the first call in a the Call.state from a call list
2153      */
getFirstCallOfState(ArrayList<Call> calls, Call.State state)2154     private Call getFirstCallOfState(ArrayList<Call> calls, Call.State state) {
2155         for (Call call : calls) {
2156             if (call.getState() == state) {
2157                 return call;
2158             }
2159         }
2160         return null;
2161     }
2162 
2163     /**
2164      * @return the first call in a the Call.state from a call list
2165      */
getFirstCallOfState(ArrayList<Call> calls, Call.State state, int subId)2166     private Call getFirstCallOfState(ArrayList<Call> calls, Call.State state,
2167             int subId) {
2168         for (Call call : calls) {
2169             if ((call.getState() == state) ||
2170                 ((call.getPhone().getSubId() == subId) ||
2171                 (call.getPhone() instanceof SipPhone))) {
2172                 return call;
2173             }
2174         }
2175         return null;
2176     }
2177 
hasMoreThanOneRingingCall()2178     private boolean hasMoreThanOneRingingCall() {
2179         int count = 0;
2180         for (Call call : mRingingCalls) {
2181             if (call.getState().isRinging()) {
2182                 if (++count > 1) return true;
2183             }
2184         }
2185         return false;
2186     }
2187 
2188     /**
2189      * @return true if more than one active ringing call exists on
2190      * the active subId.
2191      * This checks for the active calls on provided
2192      * subId and also active calls on SIP Phone.
2193      *
2194      */
hasMoreThanOneRingingCall(int subId)2195     private boolean hasMoreThanOneRingingCall(int subId) {
2196         int count = 0;
2197         for (Call call : mRingingCalls) {
2198             if ((call.getState().isRinging()) &&
2199                 ((call.getPhone().getSubId() == subId) ||
2200                 (call.getPhone() instanceof SipPhone))) {
2201                 if (++count > 1) return true;
2202             }
2203         }
2204         return false;
2205     }
2206 
2207     /**
2208      * @return true if more than one active background call exists on
2209      * the provided subId.
2210      * This checks for the background calls on provided
2211      * subId and also background calls on SIP Phone.
2212      *
2213      */
hasMoreThanOneHoldingCall(int subId)2214     private boolean hasMoreThanOneHoldingCall(int subId) {
2215         int count = 0;
2216         for (Call call : mBackgroundCalls) {
2217             if ((call.getState() == Call.State.HOLDING) &&
2218                 ((call.getPhone().getSubId() == subId) ||
2219                 (call.getPhone() instanceof SipPhone))) {
2220                 if (++count > 1) return true;
2221             }
2222         }
2223         return false;
2224     }
2225 
2226     /* FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
2227     private boolean isServiceStateInService() {
2228         boolean bInService = false;
2229 
2230         for (Phone phone : mPhones) {
2231             bInService = (phone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE);
2232             if (bInService) {
2233                 break;
2234             }
2235         }
2236 
2237         if (VDBG) Rlog.d(LOG_TAG, "[isServiceStateInService] bInService = " + bInService);
2238         return bInService;
2239     }
2240     */
2241 
2242     private class CallManagerHandler extends Handler {
2243         @Override
handleMessage(Message msg)2244         public void handleMessage(Message msg) {
2245 
2246             switch (msg.what) {
2247                 case EVENT_DISCONNECT:
2248                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_DISCONNECT)");
2249                     mDisconnectRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2250                     // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
2251                     //mIsEccDialing = false;
2252                     break;
2253                 case EVENT_PRECISE_CALL_STATE_CHANGED:
2254                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_PRECISE_CALL_STATE_CHANGED)");
2255                     mPreciseCallStateRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2256                     break;
2257                 case EVENT_NEW_RINGING_CONNECTION:
2258                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_NEW_RINGING_CONNECTION)");
2259                     Connection c = (Connection) ((AsyncResult) msg.obj).result;
2260                     int subId = c.getCall().getPhone().getSubId();
2261                     if (getActiveFgCallState(subId).isDialing() || hasMoreThanOneRingingCall()) {
2262                         try {
2263                             Rlog.d(LOG_TAG, "silently drop incoming call: " + c.getCall());
2264                             c.getCall().hangup();
2265                         } catch (CallStateException e) {
2266                             Rlog.w(LOG_TAG, "new ringing connection", e);
2267                         }
2268                     } else {
2269                         mNewRingingConnectionRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2270                     }
2271                     break;
2272                 case EVENT_UNKNOWN_CONNECTION:
2273                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_UNKNOWN_CONNECTION)");
2274                     mUnknownConnectionRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2275                     break;
2276                 case EVENT_INCOMING_RING:
2277                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_INCOMING_RING)");
2278                     // The event may come from RIL who's not aware of an ongoing fg call
2279                     if (!hasActiveFgCall()) {
2280                         mIncomingRingRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2281                     }
2282                     break;
2283                 case EVENT_RINGBACK_TONE:
2284                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_RINGBACK_TONE)");
2285                     mRingbackToneRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2286                     break;
2287                 case EVENT_IN_CALL_VOICE_PRIVACY_ON:
2288                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_IN_CALL_VOICE_PRIVACY_ON)");
2289                     mInCallVoicePrivacyOnRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2290                     break;
2291                 case EVENT_IN_CALL_VOICE_PRIVACY_OFF:
2292                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_IN_CALL_VOICE_PRIVACY_OFF)");
2293                     mInCallVoicePrivacyOffRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2294                     break;
2295                 case EVENT_CALL_WAITING:
2296                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_CALL_WAITING)");
2297                     mCallWaitingRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2298                     break;
2299                 case EVENT_DISPLAY_INFO:
2300                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_DISPLAY_INFO)");
2301                     mDisplayInfoRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2302                     break;
2303                 case EVENT_SIGNAL_INFO:
2304                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SIGNAL_INFO)");
2305                     mSignalInfoRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2306                     break;
2307                 case EVENT_CDMA_OTA_STATUS_CHANGE:
2308                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_CDMA_OTA_STATUS_CHANGE)");
2309                     mCdmaOtaStatusChangeRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2310                     break;
2311                 case EVENT_RESEND_INCALL_MUTE:
2312                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_RESEND_INCALL_MUTE)");
2313                     mResendIncallMuteRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2314                     break;
2315                 case EVENT_MMI_INITIATE:
2316                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_MMI_INITIATE)");
2317                     mMmiInitiateRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2318                     break;
2319                 case EVENT_MMI_COMPLETE:
2320                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_MMI_COMPLETE)");
2321                     mMmiCompleteRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2322                     break;
2323                 case EVENT_ECM_TIMER_RESET:
2324                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_ECM_TIMER_RESET)");
2325                     mEcmTimerResetRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2326                     break;
2327                 case EVENT_SUBSCRIPTION_INFO_READY:
2328                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SUBSCRIPTION_INFO_READY)");
2329                     mSubscriptionInfoReadyRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2330                     break;
2331                 case EVENT_SUPP_SERVICE_FAILED:
2332                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SUPP_SERVICE_FAILED)");
2333                     mSuppServiceFailedRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2334                     break;
2335                 case EVENT_SERVICE_STATE_CHANGED:
2336                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SERVICE_STATE_CHANGED)");
2337                     mServiceStateChangedRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2338                     // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
2339                     //setAudioMode();
2340                     break;
2341                 case EVENT_POST_DIAL_CHARACTER:
2342                     // we need send the character that is being processed in msg.arg1
2343                     // so can't use notifyRegistrants()
2344                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_POST_DIAL_CHARACTER)");
2345                     for(int i=0; i < mPostDialCharacterRegistrants.size(); i++) {
2346                         Message notifyMsg;
2347                         notifyMsg = ((Registrant)mPostDialCharacterRegistrants.get(i)).messageForRegistrant();
2348                         notifyMsg.obj = msg.obj;
2349                         notifyMsg.arg1 = msg.arg1;
2350                         notifyMsg.sendToTarget();
2351                     }
2352                     break;
2353                 case EVENT_ONHOLD_TONE:
2354                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_ONHOLD_TONE)");
2355                     mOnHoldToneRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2356                     break;
2357                 case EVENT_TTY_MODE_RECEIVED:
2358                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_TTY_MODE_RECEIVED)");
2359                     mTtyModeReceivedRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2360                     break;
2361                 /* FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
2362                 case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
2363                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_RADIO_OFF_OR_NOT_AVAILABLE)");
2364                     setAudioMode();
2365                     break;
2366                 */
2367             }
2368         }
2369     };
2370 
2371     @Override
toString()2372     public String toString() {
2373         Call call;
2374         StringBuilder b = new StringBuilder();
2375         for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
2376             b.append("CallManager {");
2377             b.append("\nstate = " + getState(i));
2378             call = getActiveFgCall(i);
2379             if (call != null) {
2380                 b.append("\n- Foreground: " + getActiveFgCallState(i));
2381                 b.append(" from " + call.getPhone());
2382                 b.append("\n  Conn: ").append(getFgCallConnections(i));
2383             }
2384             call = getFirstActiveBgCall(i);
2385             if (call != null) {
2386                 b.append("\n- Background: " + call.getState());
2387                 b.append(" from " + call.getPhone());
2388                 b.append("\n  Conn: ").append(getBgCallConnections(i));
2389             }
2390             call = getFirstActiveRingingCall(i);
2391             if (call != null) {
2392                 b.append("\n- Ringing: " +call.getState());
2393                 b.append(" from " + call.getPhone());
2394             }
2395         }
2396 
2397         for (Phone phone : getAllPhones()) {
2398             if (phone != null) {
2399                 b.append("\nPhone: " + phone + ", name = " + phone.getPhoneName()
2400                         + ", state = " + phone.getState());
2401                 call = phone.getForegroundCall();
2402                 if (call != null) {
2403                     b.append("\n- Foreground: ").append(call);
2404                 }
2405                 call = phone.getBackgroundCall();
2406                 if (call != null) {
2407                     b.append(" Background: ").append(call);
2408                 }
2409                 call = phone.getRingingCall();
2410                 if (call != null) {
2411                     b.append(" Ringing: ").append(call);
2412                 }
2413             }
2414         }
2415         b.append("\n}");
2416         return b.toString();
2417     }
2418 }
2419