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, new PhoneInternalInterface.DialArgs.Builder<>()
968                 .setVideoState(videoState).build());
969 
970         if (VDBG) {
971             Rlog.d(LOG_TAG, "End dial(" + phone + ", "+ dialString + ")");
972             Rlog.d(LOG_TAG, toString());
973         }
974 
975         return result;
976     }
977 
978     /**
979      * Initiate a new voice connection. This happens asynchronously, so you
980      * cannot assume the audio path is connected (or a call index has been
981      * assigned) until PhoneStateChanged notification has occurred.
982      *
983      * @exception CallStateException if a new outgoing call is not currently
984      * possible because no more call slots exist or a call exists that is
985      * dialing, alerting, ringing, or waiting.  Other errors are
986      * handled asynchronously.
987      */
dial(Phone phone, String dialString, UUSInfo uusInfo, int videoState)988     public Connection dial(Phone phone, String dialString, UUSInfo uusInfo, int videoState)
989             throws CallStateException {
990         return phone.dial(dialString,
991                 new PhoneInternalInterface.DialArgs.Builder<>()
992                         .setUusInfo(uusInfo)
993                         .setVideoState(videoState).build());
994     }
995 
996     /**
997      * clear disconnect connection for each phone
998      */
clearDisconnected()999     public void clearDisconnected() {
1000         for(Phone phone : mPhones) {
1001             phone.clearDisconnected();
1002         }
1003     }
1004 
1005     /**
1006      * clear disconnect connection for a phone specific
1007      * to the provided subId
1008      */
clearDisconnected(int subId)1009     public void clearDisconnected(int subId) {
1010         for(Phone phone : mPhones) {
1011             if (phone.getSubId() == subId) {
1012                 phone.clearDisconnected();
1013             }
1014         }
1015     }
1016 
1017     /**
1018      * Phone can make a call only if ALL of the following are true:
1019      *        - Phone is not powered off
1020      *        - There's no incoming or waiting call
1021      *        - The foreground call is ACTIVE or IDLE or DISCONNECTED.
1022      *          (We mainly need to make sure it *isn't* DIALING or ALERTING.)
1023      * @param phone
1024      * @return true if the phone can make a new call
1025      */
canDial(Phone phone)1026     private boolean canDial(Phone phone) {
1027         int serviceState = phone.getServiceState().getState();
1028         int subId = phone.getSubId();
1029         boolean hasRingingCall = hasActiveRingingCall();
1030         Call.State fgCallState = getActiveFgCallState(subId);
1031 
1032         boolean result = (serviceState != ServiceState.STATE_POWER_OFF
1033                 && !hasRingingCall
1034                 && ((fgCallState == Call.State.ACTIVE)
1035                     || (fgCallState == Call.State.IDLE)
1036                     || (fgCallState == Call.State.DISCONNECTED)
1037                     /*As per 3GPP TS 51.010-1 section 31.13.1.4
1038                     call should be alowed when the foreground
1039                     call is in ALERTING state*/
1040                     || (fgCallState == Call.State.ALERTING)));
1041 
1042         if (result == false) {
1043             Rlog.d(LOG_TAG, "canDial serviceState=" + serviceState
1044                             + " hasRingingCall=" + hasRingingCall
1045                             + " fgCallState=" + fgCallState);
1046         }
1047         return result;
1048     }
1049 
1050     /**
1051      * Whether or not the phone can do explicit call transfer in the current
1052      * phone state--that is, one call holding and one call active.
1053      * @return true if the phone can do explicit call transfer; false otherwise.
1054      */
canTransfer(Call heldCall)1055     public boolean canTransfer(Call heldCall) {
1056         Phone activePhone = null;
1057         Phone heldPhone = null;
1058 
1059         if (hasActiveFgCall()) {
1060             activePhone = getActiveFgCall().getPhone();
1061         }
1062 
1063         if (heldCall != null) {
1064             heldPhone = heldCall.getPhone();
1065         }
1066 
1067         return (heldPhone == activePhone && activePhone.canTransfer());
1068     }
1069 
1070     /**
1071      * Whether or not the phone specific to subId can do explicit call transfer
1072      * in the current phone state--that is, one call holding and one call active.
1073      * @return true if the phone can do explicit call transfer; false otherwise.
1074      */
canTransfer(Call heldCall, int subId)1075     public boolean canTransfer(Call heldCall, int subId) {
1076         Phone activePhone = null;
1077         Phone heldPhone = null;
1078 
1079         if (hasActiveFgCall(subId)) {
1080             activePhone = getActiveFgCall(subId).getPhone();
1081         }
1082 
1083         if (heldCall != null) {
1084             heldPhone = heldCall.getPhone();
1085         }
1086 
1087         return (heldPhone == activePhone && activePhone.canTransfer());
1088     }
1089 
1090     /**
1091      * Connects the held call and active call
1092      * Disconnects the subscriber from both calls
1093      *
1094      * Explicit Call Transfer occurs asynchronously
1095      * and may fail. Final notification occurs via
1096      * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,
1097      * java.lang.Object) registerForPreciseCallStateChanged()}.
1098      *
1099      * @exception CallStateException if canTransfer() would return false.
1100      * In these cases, this operation may not be performed.
1101      */
explicitCallTransfer(Call heldCall)1102     public void explicitCallTransfer(Call heldCall) throws CallStateException {
1103         if (VDBG) {
1104             Rlog.d(LOG_TAG, " explicitCallTransfer(" + heldCall + ")");
1105             Rlog.d(LOG_TAG, toString());
1106         }
1107 
1108         if (canTransfer(heldCall)) {
1109             heldCall.getPhone().explicitCallTransfer();
1110         }
1111 
1112         if (VDBG) {
1113             Rlog.d(LOG_TAG, "End explicitCallTransfer(" + heldCall + ")");
1114             Rlog.d(LOG_TAG, toString());
1115         }
1116 
1117     }
1118 
1119     /**
1120      * Returns a list of MMI codes that are pending for a phone. (They have initiated
1121      * but have not yet completed).
1122      * Presently there is only ever one.
1123      *
1124      * Use <code>registerForMmiInitiate</code>
1125      * and <code>registerForMmiComplete</code> for change notification.
1126      * @return null if phone doesn't have or support mmi code
1127      */
getPendingMmiCodes(Phone phone)1128     public List<? extends MmiCode> getPendingMmiCodes(Phone phone) {
1129         Rlog.e(LOG_TAG, "getPendingMmiCodes not implemented");
1130         return null;
1131     }
1132 
1133     /**
1134      * Sends user response to a USSD REQUEST message.  An MmiCode instance
1135      * representing this response is sent to handlers registered with
1136      * registerForMmiInitiate.
1137      *
1138      * @param ussdMessge    Message to send in the response.
1139      * @return false if phone doesn't support ussd service
1140      */
sendUssdResponse(Phone phone, String ussdMessge)1141     public boolean sendUssdResponse(Phone phone, String ussdMessge) {
1142         Rlog.e(LOG_TAG, "sendUssdResponse not implemented");
1143         return false;
1144     }
1145 
1146     /**
1147      * Mutes or unmutes the microphone for the active call. The microphone
1148      * is automatically unmuted if a call is answered, dialed, or resumed
1149      * from a holding state.
1150      *
1151      * @param muted true to mute the microphone,
1152      * false to activate the microphone.
1153      */
1154 
setMute(boolean muted)1155     public void setMute(boolean muted) {
1156         if (VDBG) {
1157             Rlog.d(LOG_TAG, " setMute(" + muted + ")");
1158             Rlog.d(LOG_TAG, toString());
1159         }
1160 
1161         if (hasActiveFgCall()) {
1162             getActiveFgCall().getPhone().setMute(muted);
1163         }
1164 
1165         if (VDBG) {
1166             Rlog.d(LOG_TAG, "End setMute(" + muted + ")");
1167             Rlog.d(LOG_TAG, toString());
1168         }
1169     }
1170 
1171     /**
1172      * Gets current mute status. Use
1173      * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,
1174      * java.lang.Object) registerForPreciseCallStateChanged()}
1175      * as a change notifcation, although presently phone state changed is not
1176      * fired when setMute() is called.
1177      *
1178      * @return true is muting, false is unmuting
1179      */
getMute()1180     public boolean getMute() {
1181         if (hasActiveFgCall()) {
1182             return getActiveFgCall().getPhone().getMute();
1183         } else if (hasActiveBgCall()) {
1184             return getFirstActiveBgCall().getPhone().getMute();
1185         }
1186         return false;
1187     }
1188 
1189     /**
1190      * Enables or disables echo suppression.
1191      */
setEchoSuppressionEnabled()1192     public void setEchoSuppressionEnabled() {
1193         if (VDBG) {
1194             Rlog.d(LOG_TAG, " setEchoSuppression()");
1195             Rlog.d(LOG_TAG, toString());
1196         }
1197 
1198         if (hasActiveFgCall()) {
1199             getActiveFgCall().getPhone().setEchoSuppressionEnabled();
1200         }
1201 
1202         if (VDBG) {
1203             Rlog.d(LOG_TAG, "End setEchoSuppression()");
1204             Rlog.d(LOG_TAG, toString());
1205         }
1206     }
1207 
1208     /**
1209      * Play a DTMF tone on the active call.
1210      *
1211      * @param c should be one of 0-9, '*' or '#'. Other values will be
1212      * silently ignored.
1213      * @return false if no active call or the active call doesn't support
1214      *         dtmf tone
1215      */
sendDtmf(char c)1216     public boolean sendDtmf(char c) {
1217         boolean result = false;
1218 
1219         if (VDBG) {
1220             Rlog.d(LOG_TAG, " sendDtmf(" + c + ")");
1221             Rlog.d(LOG_TAG, toString());
1222         }
1223 
1224         if (hasActiveFgCall()) {
1225             getActiveFgCall().getPhone().sendDtmf(c);
1226             result = true;
1227         }
1228 
1229         if (VDBG) {
1230             Rlog.d(LOG_TAG, "End sendDtmf(" + c + ")");
1231             Rlog.d(LOG_TAG, toString());
1232         }
1233         return result;
1234     }
1235 
1236     /**
1237      * Start to paly a DTMF tone on the active call.
1238      * or there is a playing DTMF tone.
1239      * @param c should be one of 0-9, '*' or '#'. Other values will be
1240      * silently ignored.
1241      *
1242      * @return false if no active call or the active call doesn't support
1243      *         dtmf tone
1244      */
startDtmf(char c)1245     public boolean startDtmf(char c) {
1246         boolean result = false;
1247 
1248         if (VDBG) {
1249             Rlog.d(LOG_TAG, " startDtmf(" + c + ")");
1250             Rlog.d(LOG_TAG, toString());
1251         }
1252 
1253         if (hasActiveFgCall()) {
1254             getActiveFgCall().getPhone().startDtmf(c);
1255             result = true;
1256         }
1257 
1258         if (VDBG) {
1259             Rlog.d(LOG_TAG, "End startDtmf(" + c + ")");
1260             Rlog.d(LOG_TAG, toString());
1261         }
1262 
1263         return result;
1264     }
1265 
1266     /**
1267      * Stop the playing DTMF tone. Ignored if there is no playing DTMF
1268      * tone or no active call.
1269      */
stopDtmf()1270     public void stopDtmf() {
1271         if (VDBG) {
1272             Rlog.d(LOG_TAG, " stopDtmf()" );
1273             Rlog.d(LOG_TAG, toString());
1274         }
1275 
1276         if (hasActiveFgCall()) getFgPhone().stopDtmf();
1277 
1278         if (VDBG) {
1279             Rlog.d(LOG_TAG, "End stopDtmf()");
1280             Rlog.d(LOG_TAG, toString());
1281         }
1282     }
1283 
1284     /**
1285      * send burst DTMF tone, it can send the string as single character or multiple character
1286      * ignore if there is no active call or not valid digits string.
1287      * Valid digit means only includes characters ISO-LATIN characters 0-9, *, #
1288      * The difference between sendDtmf and sendBurstDtmf is sendDtmf only sends one character,
1289      * this api can send single character and multiple character, also, this api has response
1290      * back to caller.
1291      *
1292      * @param dtmfString is string representing the dialing digit(s) in the active call
1293      * @param on the DTMF ON length in milliseconds, or 0 for default
1294      * @param off the DTMF OFF length in milliseconds, or 0 for default
1295      * @param onComplete is the callback message when the action is processed by BP
1296      *
1297      */
sendBurstDtmf(String dtmfString, int on, int off, Message onComplete)1298     public boolean sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) {
1299         if (hasActiveFgCall()) {
1300             getActiveFgCall().getPhone().sendBurstDtmf(dtmfString, on, off, onComplete);
1301             return true;
1302         }
1303         return false;
1304     }
1305 
1306     /**
1307      * Notifies when a voice connection has disconnected, either due to local
1308      * or remote hangup or error.
1309      *
1310      *  Messages received from this will have the following members:<p>
1311      *  <ul><li>Message.obj will be an AsyncResult</li>
1312      *  <li>AsyncResult.userObj = obj</li>
1313      *  <li>AsyncResult.result = a Connection object that is
1314      *  no longer connected.</li></ul>
1315      */
registerForDisconnect(Handler h, int what, Object obj)1316     public void registerForDisconnect(Handler h, int what, Object obj) {
1317         mDisconnectRegistrants.addUnique(h, what, obj);
1318     }
1319 
1320     /**
1321      * Unregisters for voice disconnection notification.
1322      * Extraneous calls are tolerated silently
1323      */
unregisterForDisconnect(Handler h)1324     public void unregisterForDisconnect(Handler h){
1325         mDisconnectRegistrants.remove(h);
1326     }
1327 
1328     /**
1329      * Register for getting notifications for change in the Call State {@link Call.State}
1330      * This is called PreciseCallState because the call state is more precise than what
1331      * can be obtained using the {@link PhoneStateListener}
1332      *
1333      * Resulting events will have an AsyncResult in <code>Message.obj</code>.
1334      * AsyncResult.userData will be set to the obj argument here.
1335      * The <em>h</em> parameter is held only by a weak reference.
1336      */
registerForPreciseCallStateChanged(Handler h, int what, Object obj)1337     public void registerForPreciseCallStateChanged(Handler h, int what, Object obj){
1338         mPreciseCallStateRegistrants.addUnique(h, what, obj);
1339     }
1340 
1341     /**
1342      * Unregisters for voice call state change notifications.
1343      * Extraneous calls are tolerated silently.
1344      */
unregisterForPreciseCallStateChanged(Handler h)1345     public void unregisterForPreciseCallStateChanged(Handler h){
1346         mPreciseCallStateRegistrants.remove(h);
1347     }
1348 
1349     /**
1350      * Notifies when a previously untracked non-ringing/waiting connection has appeared.
1351      * This is likely due to some other entity (eg, SIM card application) initiating a call.
1352      */
registerForUnknownConnection(Handler h, int what, Object obj)1353     public void registerForUnknownConnection(Handler h, int what, Object obj){
1354         mUnknownConnectionRegistrants.addUnique(h, what, obj);
1355     }
1356 
1357     /**
1358      * Unregisters for unknown connection notifications.
1359      */
unregisterForUnknownConnection(Handler h)1360     public void unregisterForUnknownConnection(Handler h){
1361         mUnknownConnectionRegistrants.remove(h);
1362     }
1363 
1364 
1365     /**
1366      * Notifies when a new ringing or waiting connection has appeared.<p>
1367      *
1368      *  Messages received from this:
1369      *  Message.obj will be an AsyncResult
1370      *  AsyncResult.userObj = obj
1371      *  AsyncResult.result = a Connection. <p>
1372      *  Please check Connection.isRinging() to make sure the Connection
1373      *  has not dropped since this message was posted.
1374      *  If Connection.isRinging() is true, then
1375      *   Connection.getCall() == Phone.getRingingCall()
1376      */
registerForNewRingingConnection(Handler h, int what, Object obj)1377     public void registerForNewRingingConnection(Handler h, int what, Object obj){
1378         mNewRingingConnectionRegistrants.addUnique(h, what, obj);
1379     }
1380 
1381     /**
1382      * Unregisters for new ringing connection notification.
1383      * Extraneous calls are tolerated silently
1384      */
1385 
unregisterForNewRingingConnection(Handler h)1386     public void unregisterForNewRingingConnection(Handler h){
1387         mNewRingingConnectionRegistrants.remove(h);
1388     }
1389 
1390     /**
1391      * Notifies when an incoming call rings.<p>
1392      *
1393      *  Messages received from this:
1394      *  Message.obj will be an AsyncResult
1395      *  AsyncResult.userObj = obj
1396      *  AsyncResult.result = a Connection. <p>
1397      */
registerForIncomingRing(Handler h, int what, Object obj)1398     public void registerForIncomingRing(Handler h, int what, Object obj){
1399         mIncomingRingRegistrants.addUnique(h, what, obj);
1400     }
1401 
1402     /**
1403      * Unregisters for ring notification.
1404      * Extraneous calls are tolerated silently
1405      */
1406 
unregisterForIncomingRing(Handler h)1407     public void unregisterForIncomingRing(Handler h){
1408         mIncomingRingRegistrants.remove(h);
1409     }
1410 
1411     /**
1412      * Notifies when out-band ringback tone is needed.<p>
1413      *
1414      *  Messages received from this:
1415      *  Message.obj will be an AsyncResult
1416      *  AsyncResult.userObj = obj
1417      *  AsyncResult.result = boolean, true to start play ringback tone
1418      *                       and false to stop. <p>
1419      */
registerForRingbackTone(Handler h, int what, Object obj)1420     public void registerForRingbackTone(Handler h, int what, Object obj){
1421         mRingbackToneRegistrants.addUnique(h, what, obj);
1422     }
1423 
1424     /**
1425      * Unregisters for ringback tone notification.
1426      */
1427 
unregisterForRingbackTone(Handler h)1428     public void unregisterForRingbackTone(Handler h){
1429         mRingbackToneRegistrants.remove(h);
1430     }
1431 
1432     /**
1433      * Notifies when out-band on-hold tone is needed.<p>
1434      *
1435      *  Messages received from this:
1436      *  Message.obj will be an AsyncResult
1437      *  AsyncResult.userObj = obj
1438      *  AsyncResult.result = boolean, true to start play on-hold tone
1439      *                       and false to stop. <p>
1440      */
registerForOnHoldTone(Handler h, int what, Object obj)1441     public void registerForOnHoldTone(Handler h, int what, Object obj){
1442         mOnHoldToneRegistrants.addUnique(h, what, obj);
1443     }
1444 
1445     /**
1446      * Unregisters for on-hold tone notification.
1447      */
1448 
unregisterForOnHoldTone(Handler h)1449     public void unregisterForOnHoldTone(Handler h){
1450         mOnHoldToneRegistrants.remove(h);
1451     }
1452 
1453     /**
1454      * Registers the handler to reset the uplink mute state to get
1455      * uplink audio.
1456      */
registerForResendIncallMute(Handler h, int what, Object obj)1457     public void registerForResendIncallMute(Handler h, int what, Object obj){
1458         mResendIncallMuteRegistrants.addUnique(h, what, obj);
1459     }
1460 
1461     /**
1462      * Unregisters for resend incall mute notifications.
1463      */
unregisterForResendIncallMute(Handler h)1464     public void unregisterForResendIncallMute(Handler h){
1465         mResendIncallMuteRegistrants.remove(h);
1466     }
1467 
1468     /**
1469      * Register for notifications of initiation of a new MMI code request.
1470      * MMI codes for GSM are discussed in 3GPP TS 22.030.<p>
1471      *
1472      * Example: If Phone.dial is called with "*#31#", then the app will
1473      * be notified here.<p>
1474      *
1475      * The returned <code>Message.obj</code> will contain an AsyncResult.
1476      *
1477      * <code>obj.result</code> will be an "MmiCode" object.
1478      */
registerForMmiInitiate(Handler h, int what, Object obj)1479     public void registerForMmiInitiate(Handler h, int what, Object obj){
1480         mMmiInitiateRegistrants.addUnique(h, what, obj);
1481     }
1482 
1483     /**
1484      * Unregisters for new MMI initiate notification.
1485      * Extraneous calls are tolerated silently
1486      */
unregisterForMmiInitiate(Handler h)1487     public void unregisterForMmiInitiate(Handler h){
1488         mMmiInitiateRegistrants.remove(h);
1489     }
1490 
1491     /**
1492      * Register for notifications that an MMI request has completed
1493      * its network activity and is in its final state. This may mean a state
1494      * of COMPLETE, FAILED, or CANCELLED.
1495      *
1496      * <code>Message.obj</code> will contain an AsyncResult.
1497      * <code>obj.result</code> will be an "MmiCode" object
1498      */
registerForMmiComplete(Handler h, int what, Object obj)1499     public void registerForMmiComplete(Handler h, int what, Object obj){
1500         Rlog.d(LOG_TAG, "registerForMmiComplete");
1501         mMmiCompleteRegistrants.addUnique(h, what, obj);
1502     }
1503 
1504     /**
1505      * Unregisters for MMI complete notification.
1506      * Extraneous calls are tolerated silently
1507      */
unregisterForMmiComplete(Handler h)1508     public void unregisterForMmiComplete(Handler h){
1509         mMmiCompleteRegistrants.remove(h);
1510     }
1511 
1512     /**
1513      * Registration point for Ecm timer reset
1514      * @param h handler to notify
1515      * @param what user-defined message code
1516      * @param obj placed in Message.obj
1517      */
registerForEcmTimerReset(Handler h, int what, Object obj)1518     public void registerForEcmTimerReset(Handler h, int what, Object obj){
1519         mEcmTimerResetRegistrants.addUnique(h, what, obj);
1520     }
1521 
1522     /**
1523      * Unregister for notification for Ecm timer reset
1524      * @param h Handler to be removed from the registrant list.
1525      */
unregisterForEcmTimerReset(Handler h)1526     public void unregisterForEcmTimerReset(Handler h){
1527         mEcmTimerResetRegistrants.remove(h);
1528     }
1529 
1530     /**
1531      * Register for ServiceState changed.
1532      * Message.obj will contain an AsyncResult.
1533      * AsyncResult.result will be a ServiceState instance
1534      */
registerForServiceStateChanged(Handler h, int what, Object obj)1535     public void registerForServiceStateChanged(Handler h, int what, Object obj){
1536         mServiceStateChangedRegistrants.addUnique(h, what, obj);
1537     }
1538 
1539     /**
1540      * Unregisters for ServiceStateChange notification.
1541      * Extraneous calls are tolerated silently
1542      */
unregisterForServiceStateChanged(Handler h)1543     public void unregisterForServiceStateChanged(Handler h){
1544         mServiceStateChangedRegistrants.remove(h);
1545     }
1546 
1547     /**
1548      * Register for notifications when a supplementary service attempt fails.
1549      * Message.obj will contain an AsyncResult.
1550      *
1551      * @param h Handler that receives the notification message.
1552      * @param what User-defined message code.
1553      * @param obj User object.
1554      */
registerForSuppServiceFailed(Handler h, int what, Object obj)1555     public void registerForSuppServiceFailed(Handler h, int what, Object obj){
1556         mSuppServiceFailedRegistrants.addUnique(h, what, obj);
1557     }
1558 
1559     /**
1560      * Unregister for notifications when a supplementary service attempt fails.
1561      * Extraneous calls are tolerated silently
1562      *
1563      * @param h Handler to be removed from the registrant list.
1564      */
unregisterForSuppServiceFailed(Handler h)1565     public void unregisterForSuppServiceFailed(Handler h){
1566         mSuppServiceFailedRegistrants.remove(h);
1567     }
1568 
1569     /**
1570      * Register for notifications when a sInCall VoicePrivacy is enabled
1571      *
1572      * @param h Handler that receives the notification message.
1573      * @param what User-defined message code.
1574      * @param obj User object.
1575      */
registerForInCallVoicePrivacyOn(Handler h, int what, Object obj)1576     public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj){
1577         mInCallVoicePrivacyOnRegistrants.addUnique(h, what, obj);
1578     }
1579 
1580     /**
1581      * Unregister for notifications when a sInCall VoicePrivacy is enabled
1582      *
1583      * @param h Handler to be removed from the registrant list.
1584      */
unregisterForInCallVoicePrivacyOn(Handler h)1585     public void unregisterForInCallVoicePrivacyOn(Handler h){
1586         mInCallVoicePrivacyOnRegistrants.remove(h);
1587     }
1588 
1589     /**
1590      * Register for notifications when a sInCall VoicePrivacy is disabled
1591      *
1592      * @param h Handler that receives the notification message.
1593      * @param what User-defined message code.
1594      * @param obj User object.
1595      */
registerForInCallVoicePrivacyOff(Handler h, int what, Object obj)1596     public void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj){
1597         mInCallVoicePrivacyOffRegistrants.addUnique(h, what, obj);
1598     }
1599 
1600     /**
1601      * Unregister for notifications when a sInCall VoicePrivacy is disabled
1602      *
1603      * @param h Handler to be removed from the registrant list.
1604      */
unregisterForInCallVoicePrivacyOff(Handler h)1605     public void unregisterForInCallVoicePrivacyOff(Handler h){
1606         mInCallVoicePrivacyOffRegistrants.remove(h);
1607     }
1608 
1609     /**
1610      * Register for notifications when CDMA call waiting comes
1611      *
1612      * @param h Handler that receives the notification message.
1613      * @param what User-defined message code.
1614      * @param obj User object.
1615      */
registerForCallWaiting(Handler h, int what, Object obj)1616     public void registerForCallWaiting(Handler h, int what, Object obj){
1617         mCallWaitingRegistrants.addUnique(h, what, obj);
1618     }
1619 
1620     /**
1621      * Unregister for notifications when CDMA Call waiting comes
1622      * @param h Handler to be removed from the registrant list.
1623      */
unregisterForCallWaiting(Handler h)1624     public void unregisterForCallWaiting(Handler h){
1625         mCallWaitingRegistrants.remove(h);
1626     }
1627 
1628 
1629     /**
1630      * Register for signal information notifications from the network.
1631      * Message.obj will contain an AsyncResult.
1632      * AsyncResult.result will be a SuppServiceNotification instance.
1633      *
1634      * @param h Handler that receives the notification message.
1635      * @param what User-defined message code.
1636      * @param obj User object.
1637      */
1638 
registerForSignalInfo(Handler h, int what, Object obj)1639     public void registerForSignalInfo(Handler h, int what, Object obj){
1640         mSignalInfoRegistrants.addUnique(h, what, obj);
1641     }
1642 
1643     /**
1644      * Unregisters for signal information notifications.
1645      * Extraneous calls are tolerated silently
1646      *
1647      * @param h Handler to be removed from the registrant list.
1648      */
unregisterForSignalInfo(Handler h)1649     public void unregisterForSignalInfo(Handler h){
1650         mSignalInfoRegistrants.remove(h);
1651     }
1652 
1653     /**
1654      * Register for display information notifications from the network.
1655      * Message.obj will contain an AsyncResult.
1656      * AsyncResult.result will be a SuppServiceNotification instance.
1657      *
1658      * @param h Handler that receives the notification message.
1659      * @param what User-defined message code.
1660      * @param obj User object.
1661      */
registerForDisplayInfo(Handler h, int what, Object obj)1662     public void registerForDisplayInfo(Handler h, int what, Object obj){
1663         mDisplayInfoRegistrants.addUnique(h, what, obj);
1664     }
1665 
1666     /**
1667      * Unregisters for display information notifications.
1668      * Extraneous calls are tolerated silently
1669      *
1670      * @param h Handler to be removed from the registrant list.
1671      */
unregisterForDisplayInfo(Handler h)1672     public void unregisterForDisplayInfo(Handler h) {
1673         mDisplayInfoRegistrants.remove(h);
1674     }
1675 
1676     /**
1677      * Register for notifications when CDMA OTA Provision status change
1678      *
1679      * @param h Handler that receives the notification message.
1680      * @param what User-defined message code.
1681      * @param obj User object.
1682      */
registerForCdmaOtaStatusChange(Handler h, int what, Object obj)1683     public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj){
1684         mCdmaOtaStatusChangeRegistrants.addUnique(h, what, obj);
1685     }
1686 
1687     /**
1688      * Unregister for notifications when CDMA OTA Provision status change
1689      * @param h Handler to be removed from the registrant list.
1690      */
unregisterForCdmaOtaStatusChange(Handler h)1691     public void unregisterForCdmaOtaStatusChange(Handler h){
1692         mCdmaOtaStatusChangeRegistrants.remove(h);
1693     }
1694 
1695     /**
1696      * Registration point for subscription info ready
1697      * @param h handler to notify
1698      * @param what what code of message when delivered
1699      * @param obj placed in Message.obj
1700      */
registerForSubscriptionInfoReady(Handler h, int what, Object obj)1701     public void registerForSubscriptionInfoReady(Handler h, int what, Object obj){
1702         mSubscriptionInfoReadyRegistrants.addUnique(h, what, obj);
1703     }
1704 
1705     /**
1706      * Unregister for notifications for subscription info
1707      * @param h Handler to be removed from the registrant list.
1708      */
unregisterForSubscriptionInfoReady(Handler h)1709     public void unregisterForSubscriptionInfoReady(Handler h){
1710         mSubscriptionInfoReadyRegistrants.remove(h);
1711     }
1712 
1713     /**
1714      * Sets an event to be fired when the telephony system processes
1715      * a post-dial character on an outgoing call.<p>
1716      *
1717      * Messages of type <code>what</code> will be sent to <code>h</code>.
1718      * The <code>obj</code> field of these Message's will be instances of
1719      * <code>AsyncResult</code>. <code>Message.obj.result</code> will be
1720      * a Connection object.<p>
1721      *
1722      * Message.arg1 will be the post dial character being processed,
1723      * or 0 ('\0') if end of string.<p>
1724      *
1725      * If Connection.getPostDialState() == WAIT,
1726      * the application must call
1727      * {@link com.android.internal.telephony.Connection#proceedAfterWaitChar()
1728      * Connection.proceedAfterWaitChar()} or
1729      * {@link com.android.internal.telephony.Connection#cancelPostDial()
1730      * Connection.cancelPostDial()}
1731      * for the telephony system to continue playing the post-dial
1732      * DTMF sequence.<p>
1733      *
1734      * If Connection.getPostDialState() == WILD,
1735      * the application must call
1736      * {@link com.android.internal.telephony.Connection#proceedAfterWildChar
1737      * Connection.proceedAfterWildChar()}
1738      * or
1739      * {@link com.android.internal.telephony.Connection#cancelPostDial()
1740      * Connection.cancelPostDial()}
1741      * for the telephony system to continue playing the
1742      * post-dial DTMF sequence.<p>
1743      *
1744      */
registerForPostDialCharacter(Handler h, int what, Object obj)1745     public void registerForPostDialCharacter(Handler h, int what, Object obj){
1746         mPostDialCharacterRegistrants.addUnique(h, what, obj);
1747     }
1748 
unregisterForPostDialCharacter(Handler h)1749     public void unregisterForPostDialCharacter(Handler h){
1750         mPostDialCharacterRegistrants.remove(h);
1751     }
1752 
1753     /**
1754      * Register for TTY mode change notifications from the network.
1755      * Message.obj will contain an AsyncResult.
1756      * AsyncResult.result will be an Integer containing new mode.
1757      *
1758      * @param h Handler that receives the notification message.
1759      * @param what User-defined message code.
1760      * @param obj User object.
1761      */
registerForTtyModeReceived(Handler h, int what, Object obj)1762     public void registerForTtyModeReceived(Handler h, int what, Object obj){
1763         mTtyModeReceivedRegistrants.addUnique(h, what, obj);
1764     }
1765 
1766     /**
1767      * Unregisters for TTY mode change notifications.
1768      * Extraneous calls are tolerated silently
1769      *
1770      * @param h Handler to be removed from the registrant list.
1771      */
unregisterForTtyModeReceived(Handler h)1772     public void unregisterForTtyModeReceived(Handler h) {
1773         mTtyModeReceivedRegistrants.remove(h);
1774     }
1775 
1776     /* APIs to access foregroudCalls, backgroudCalls, and ringingCalls
1777      * 1. APIs to access list of calls
1778      * 2. APIs to check if any active call, which has connection other than
1779      * disconnected ones, pleaser refer to Call.isIdle()
1780      * 3. APIs to return first active call
1781      * 4. APIs to return the connections of first active call
1782      * 5. APIs to return other property of first active call
1783      */
1784 
1785     /**
1786      * @return list of all ringing calls
1787      */
getRingingCalls()1788     public List<Call> getRingingCalls() {
1789         return Collections.unmodifiableList(mRingingCalls);
1790     }
1791 
1792     /**
1793      * @return list of all foreground calls
1794      */
getForegroundCalls()1795     public List<Call> getForegroundCalls() {
1796         return Collections.unmodifiableList(mForegroundCalls);
1797     }
1798 
1799     /**
1800      * @return list of all background calls
1801      */
getBackgroundCalls()1802     public List<Call> getBackgroundCalls() {
1803         return Collections.unmodifiableList(mBackgroundCalls);
1804     }
1805 
1806     /**
1807      * Return true if there is at least one active foreground call
1808      */
hasActiveFgCall()1809     public boolean hasActiveFgCall() {
1810         return (getFirstActiveCall(mForegroundCalls) != null);
1811     }
1812 
1813     /**
1814      * Return true if there is at least one active foreground call
1815      * on a particular subId or an active sip call
1816      */
hasActiveFgCall(int subId)1817     public boolean hasActiveFgCall(int subId) {
1818         return (getFirstActiveCall(mForegroundCalls, subId) != null);
1819     }
1820 
1821     /**
1822      * Return true if there is at least one active background call
1823      */
hasActiveBgCall()1824     public boolean hasActiveBgCall() {
1825         // TODO since hasActiveBgCall may get called often
1826         // better to cache it to improve performance
1827         return (getFirstActiveCall(mBackgroundCalls) != null);
1828     }
1829 
1830     /**
1831      * Return true if there is at least one active background call
1832      * on a particular subId or an active sip call
1833      */
hasActiveBgCall(int subId)1834     public boolean hasActiveBgCall(int subId) {
1835         // TODO since hasActiveBgCall may get called often
1836         // better to cache it to improve performance
1837         return (getFirstActiveCall(mBackgroundCalls, subId) != null);
1838     }
1839 
1840     /**
1841      * Return true if there is at least one active ringing call
1842      *
1843      */
hasActiveRingingCall()1844     public boolean hasActiveRingingCall() {
1845         return (getFirstActiveCall(mRingingCalls) != null);
1846     }
1847 
1848     /**
1849      * Return true if there is at least one active ringing call
1850      */
hasActiveRingingCall(int subId)1851     public boolean hasActiveRingingCall(int subId) {
1852         return (getFirstActiveCall(mRingingCalls, subId) != null);
1853     }
1854 
1855     /**
1856      * return the active foreground call from foreground calls
1857      *
1858      * Active call means the call is NOT in Call.State.IDLE
1859      *
1860      * 1. If there is active foreground call, return it
1861      * 2. If there is no active foreground call, return the
1862      *    foreground call associated with default phone, which state is IDLE.
1863      * 3. If there is no phone registered at all, return null.
1864      *
1865      */
getActiveFgCall()1866     public Call getActiveFgCall() {
1867         Call call = getFirstNonIdleCall(mForegroundCalls);
1868         if (call == null) {
1869             call = (mDefaultPhone == null)
1870                     ? null
1871                     : mDefaultPhone.getForegroundCall();
1872         }
1873         return call;
1874     }
1875 
getActiveFgCall(int subId)1876     public Call getActiveFgCall(int subId) {
1877         Call call = getFirstNonIdleCall(mForegroundCalls, subId);
1878         if (call == null) {
1879             Phone phone = getPhone(subId);
1880             call = (phone == null)
1881                     ? null
1882                     : phone.getForegroundCall();
1883         }
1884         return call;
1885     }
1886 
1887     // Returns the first call that is not in IDLE state. If both active calls
1888     // and disconnecting/disconnected calls exist, return the first active call.
getFirstNonIdleCall(List<Call> calls)1889     private Call getFirstNonIdleCall(List<Call> calls) {
1890         Call result = null;
1891         for (Call call : calls) {
1892             if (!call.isIdle()) {
1893                 return call;
1894             } else if (call.getState() != Call.State.IDLE) {
1895                 if (result == null) result = call;
1896             }
1897         }
1898         return result;
1899     }
1900 
1901     // Returns the first call that is not in IDLE state. If both active calls
1902     // and disconnecting/disconnected calls exist, return the first active call.
getFirstNonIdleCall(List<Call> calls, int subId)1903     private Call getFirstNonIdleCall(List<Call> calls, int subId) {
1904         Call result = null;
1905         for (Call call : calls) {
1906             if ((call.getPhone().getSubId() == subId) ||
1907                     (call.getPhone() instanceof SipPhone)) {
1908                 if (!call.isIdle()) {
1909                     return call;
1910                 } else if (call.getState() != Call.State.IDLE) {
1911                     if (result == null) result = call;
1912                 }
1913             }
1914         }
1915         return result;
1916     }
1917 
1918     /**
1919      * return one active background call from background calls
1920      *
1921      * Active call means the call is NOT idle defined by Call.isIdle()
1922      *
1923      * 1. If there is only one active background call, return it
1924      * 2. If there is more than one active background call, return the first one
1925      * 3. If there is no active background call, return the background call
1926      *    associated with default phone, which state is IDLE.
1927      * 4. If there is no background call at all, return null.
1928      *
1929      * Complete background calls list can be get by getBackgroundCalls()
1930      */
getFirstActiveBgCall()1931     public Call getFirstActiveBgCall() {
1932         Call call = getFirstNonIdleCall(mBackgroundCalls);
1933         if (call == null) {
1934             call = (mDefaultPhone == null)
1935                     ? null
1936                     : mDefaultPhone.getBackgroundCall();
1937         }
1938         return call;
1939     }
1940 
1941     /**
1942      * return one active background call from background calls of the
1943      * requested subId.
1944      *
1945      * Active call means the call is NOT idle defined by Call.isIdle()
1946      *
1947      * 1. If there is only one active background call on given sub or
1948      *    on SIP Phone, return it
1949      * 2. If there is more than one active background call, return the background call
1950      *    associated with the active sub.
1951      * 3. If there is no background call at all, return null.
1952      *
1953      * Complete background calls list can be get by getBackgroundCalls()
1954      */
getFirstActiveBgCall(int subId)1955     public Call getFirstActiveBgCall(int subId) {
1956         Phone phone = getPhone(subId);
1957         if (hasMoreThanOneHoldingCall(subId)) {
1958             return phone.getBackgroundCall();
1959         } else {
1960             Call call = getFirstNonIdleCall(mBackgroundCalls, subId);
1961             if (call == null) {
1962                 call = (phone == null)
1963                         ? null
1964                         : phone.getBackgroundCall();
1965             }
1966             return call;
1967         }
1968     }
1969 
1970     /**
1971      * return one active ringing call from ringing calls
1972      *
1973      * Active call means the call is NOT idle defined by Call.isIdle()
1974      *
1975      * 1. If there is only one active ringing call, return it
1976      * 2. If there is more than one active ringing call, return the first one
1977      * 3. If there is no active ringing call, return the ringing call
1978      *    associated with default phone, which state is IDLE.
1979      * 4. If there is no ringing call at all, return null.
1980      *
1981      * Complete ringing calls list can be get by getRingingCalls()
1982      */
getFirstActiveRingingCall()1983     public Call getFirstActiveRingingCall() {
1984         Call call = getFirstNonIdleCall(mRingingCalls);
1985         if (call == null) {
1986             call = (mDefaultPhone == null)
1987                     ? null
1988                     : mDefaultPhone.getRingingCall();
1989         }
1990         return call;
1991     }
1992 
getFirstActiveRingingCall(int subId)1993     public Call getFirstActiveRingingCall(int subId) {
1994         Phone phone = getPhone(subId);
1995         Call call = getFirstNonIdleCall(mRingingCalls, subId);
1996         if (call == null) {
1997             call = (phone == null)
1998                     ? null
1999                     : phone.getRingingCall();
2000         }
2001         return call;
2002     }
2003 
2004     /**
2005      * @return the state of active foreground call
2006      * return IDLE if there is no active foreground call
2007      */
getActiveFgCallState()2008     public Call.State getActiveFgCallState() {
2009         Call fgCall = getActiveFgCall();
2010 
2011         if (fgCall != null) {
2012             return fgCall.getState();
2013         }
2014 
2015         return Call.State.IDLE;
2016     }
2017 
getActiveFgCallState(int subId)2018     public Call.State getActiveFgCallState(int subId) {
2019         Call fgCall = getActiveFgCall(subId);
2020 
2021         if (fgCall != null) {
2022             return fgCall.getState();
2023         }
2024 
2025         return Call.State.IDLE;
2026     }
2027 
2028     /**
2029      * @return the connections of active foreground call
2030      * return empty list if there is no active foreground call
2031      */
getFgCallConnections()2032     public List<Connection> getFgCallConnections() {
2033         Call fgCall = getActiveFgCall();
2034         if ( fgCall != null) {
2035             return fgCall.getConnections();
2036         }
2037         return mEmptyConnections;
2038     }
2039 
2040     /**
2041      * @return the connections of active foreground call
2042      * return empty list if there is no active foreground call
2043      */
getFgCallConnections(int subId)2044     public List<Connection> getFgCallConnections(int subId) {
2045         Call fgCall = getActiveFgCall(subId);
2046         if ( fgCall != null) {
2047             return fgCall.getConnections();
2048         }
2049         return mEmptyConnections;
2050     }
2051 
2052     /**
2053      * @return the connections of active background call
2054      * return empty list if there is no active background call
2055      */
getBgCallConnections()2056     public List<Connection> getBgCallConnections() {
2057         Call bgCall = getFirstActiveBgCall();
2058         if ( bgCall != null) {
2059             return bgCall.getConnections();
2060         }
2061         return mEmptyConnections;
2062     }
2063 
2064     /**
2065      * @return the connections of active background call
2066      * return empty list if there is no active background call
2067      */
getBgCallConnections(int subId)2068     public List<Connection> getBgCallConnections(int subId) {
2069         Call bgCall = getFirstActiveBgCall(subId);
2070         if ( bgCall != null) {
2071             return bgCall.getConnections();
2072         }
2073         return mEmptyConnections;
2074     }
2075 
2076     /**
2077      * @return the latest connection of active foreground call
2078      * return null if there is no active foreground call
2079      */
getFgCallLatestConnection()2080     public Connection getFgCallLatestConnection() {
2081         Call fgCall = getActiveFgCall();
2082         if ( fgCall != null) {
2083             return fgCall.getLatestConnection();
2084         }
2085         return null;
2086     }
2087 
2088     /**
2089      * @return the latest connection of active foreground call
2090      * return null if there is no active foreground call
2091      */
getFgCallLatestConnection(int subId)2092     public Connection getFgCallLatestConnection(int subId) {
2093         Call fgCall = getActiveFgCall(subId);
2094         if ( fgCall != null) {
2095             return fgCall.getLatestConnection();
2096         }
2097         return null;
2098     }
2099 
2100     /**
2101      * @return true if there is at least one Foreground call in disconnected state
2102      */
hasDisconnectedFgCall()2103     public boolean hasDisconnectedFgCall() {
2104         return (getFirstCallOfState(mForegroundCalls, Call.State.DISCONNECTED) != null);
2105     }
2106 
2107     /**
2108      * @return true if there is at least one Foreground call in disconnected state
2109      */
hasDisconnectedFgCall(int subId)2110     public boolean hasDisconnectedFgCall(int subId) {
2111         return (getFirstCallOfState(mForegroundCalls, Call.State.DISCONNECTED,
2112                 subId) != null);
2113     }
2114 
2115     /**
2116      * @return true if there is at least one background call in disconnected state
2117      */
hasDisconnectedBgCall()2118     public boolean hasDisconnectedBgCall() {
2119         return (getFirstCallOfState(mBackgroundCalls, Call.State.DISCONNECTED) != null);
2120     }
2121 
2122     /**
2123      * @return true if there is at least one background call in disconnected state
2124      */
hasDisconnectedBgCall(int subId)2125     public boolean hasDisconnectedBgCall(int subId) {
2126         return (getFirstCallOfState(mBackgroundCalls, Call.State.DISCONNECTED,
2127                 subId) != null);
2128     }
2129 
2130 
2131     /**
2132      * @return the first active call from a call list
2133      */
getFirstActiveCall(ArrayList<Call> calls)2134     private  Call getFirstActiveCall(ArrayList<Call> calls) {
2135         for (Call call : calls) {
2136             if (!call.isIdle()) {
2137                 return call;
2138             }
2139         }
2140         return null;
2141     }
2142 
2143     /**
2144      * @return the first active call from a call list
2145      */
getFirstActiveCall(ArrayList<Call> calls, int subId)2146     private  Call getFirstActiveCall(ArrayList<Call> calls, int subId) {
2147         for (Call call : calls) {
2148             if ((!call.isIdle()) && ((call.getPhone().getSubId() == subId) ||
2149                     (call.getPhone() instanceof SipPhone))) {
2150                 return call;
2151             }
2152         }
2153         return null;
2154     }
2155 
2156     /**
2157      * @return the first call in a the Call.state from a call list
2158      */
getFirstCallOfState(ArrayList<Call> calls, Call.State state)2159     private Call getFirstCallOfState(ArrayList<Call> calls, Call.State state) {
2160         for (Call call : calls) {
2161             if (call.getState() == state) {
2162                 return call;
2163             }
2164         }
2165         return null;
2166     }
2167 
2168     /**
2169      * @return the first call in a the Call.state from a call list
2170      */
getFirstCallOfState(ArrayList<Call> calls, Call.State state, int subId)2171     private Call getFirstCallOfState(ArrayList<Call> calls, Call.State state,
2172             int subId) {
2173         for (Call call : calls) {
2174             if ((call.getState() == state) ||
2175                 ((call.getPhone().getSubId() == subId) ||
2176                 (call.getPhone() instanceof SipPhone))) {
2177                 return call;
2178             }
2179         }
2180         return null;
2181     }
2182 
hasMoreThanOneRingingCall()2183     private boolean hasMoreThanOneRingingCall() {
2184         int count = 0;
2185         for (Call call : mRingingCalls) {
2186             if (call.getState().isRinging()) {
2187                 if (++count > 1) return true;
2188             }
2189         }
2190         return false;
2191     }
2192 
2193     /**
2194      * @return true if more than one active ringing call exists on
2195      * the active subId.
2196      * This checks for the active calls on provided
2197      * subId and also active calls on SIP Phone.
2198      *
2199      */
hasMoreThanOneRingingCall(int subId)2200     private boolean hasMoreThanOneRingingCall(int subId) {
2201         int count = 0;
2202         for (Call call : mRingingCalls) {
2203             if ((call.getState().isRinging()) &&
2204                 ((call.getPhone().getSubId() == subId) ||
2205                 (call.getPhone() instanceof SipPhone))) {
2206                 if (++count > 1) return true;
2207             }
2208         }
2209         return false;
2210     }
2211 
2212     /**
2213      * @return true if more than one active background call exists on
2214      * the provided subId.
2215      * This checks for the background calls on provided
2216      * subId and also background calls on SIP Phone.
2217      *
2218      */
hasMoreThanOneHoldingCall(int subId)2219     private boolean hasMoreThanOneHoldingCall(int subId) {
2220         int count = 0;
2221         for (Call call : mBackgroundCalls) {
2222             if ((call.getState() == Call.State.HOLDING) &&
2223                 ((call.getPhone().getSubId() == subId) ||
2224                 (call.getPhone() instanceof SipPhone))) {
2225                 if (++count > 1) return true;
2226             }
2227         }
2228         return false;
2229     }
2230 
2231     /* FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
2232     private boolean isServiceStateInService() {
2233         boolean bInService = false;
2234 
2235         for (Phone phone : mPhones) {
2236             bInService = (phone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE);
2237             if (bInService) {
2238                 break;
2239             }
2240         }
2241 
2242         if (VDBG) Rlog.d(LOG_TAG, "[isServiceStateInService] bInService = " + bInService);
2243         return bInService;
2244     }
2245     */
2246 
2247     private class CallManagerHandler extends Handler {
2248         @Override
handleMessage(Message msg)2249         public void handleMessage(Message msg) {
2250 
2251             switch (msg.what) {
2252                 case EVENT_DISCONNECT:
2253                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_DISCONNECT)");
2254                     mDisconnectRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2255                     // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
2256                     //mIsEccDialing = false;
2257                     break;
2258                 case EVENT_PRECISE_CALL_STATE_CHANGED:
2259                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_PRECISE_CALL_STATE_CHANGED)");
2260                     mPreciseCallStateRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2261                     break;
2262                 case EVENT_NEW_RINGING_CONNECTION:
2263                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_NEW_RINGING_CONNECTION)");
2264                     Connection c = (Connection) ((AsyncResult) msg.obj).result;
2265                     int subId = c.getCall().getPhone().getSubId();
2266                     if (getActiveFgCallState(subId).isDialing() || hasMoreThanOneRingingCall()) {
2267                         try {
2268                             Rlog.d(LOG_TAG, "silently drop incoming call: " + c.getCall());
2269                             c.getCall().hangup();
2270                         } catch (CallStateException e) {
2271                             Rlog.w(LOG_TAG, "new ringing connection", e);
2272                         }
2273                     } else {
2274                         mNewRingingConnectionRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2275                     }
2276                     break;
2277                 case EVENT_UNKNOWN_CONNECTION:
2278                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_UNKNOWN_CONNECTION)");
2279                     mUnknownConnectionRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2280                     break;
2281                 case EVENT_INCOMING_RING:
2282                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_INCOMING_RING)");
2283                     // The event may come from RIL who's not aware of an ongoing fg call
2284                     if (!hasActiveFgCall()) {
2285                         mIncomingRingRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2286                     }
2287                     break;
2288                 case EVENT_RINGBACK_TONE:
2289                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_RINGBACK_TONE)");
2290                     mRingbackToneRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2291                     break;
2292                 case EVENT_IN_CALL_VOICE_PRIVACY_ON:
2293                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_IN_CALL_VOICE_PRIVACY_ON)");
2294                     mInCallVoicePrivacyOnRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2295                     break;
2296                 case EVENT_IN_CALL_VOICE_PRIVACY_OFF:
2297                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_IN_CALL_VOICE_PRIVACY_OFF)");
2298                     mInCallVoicePrivacyOffRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2299                     break;
2300                 case EVENT_CALL_WAITING:
2301                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_CALL_WAITING)");
2302                     mCallWaitingRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2303                     break;
2304                 case EVENT_DISPLAY_INFO:
2305                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_DISPLAY_INFO)");
2306                     mDisplayInfoRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2307                     break;
2308                 case EVENT_SIGNAL_INFO:
2309                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SIGNAL_INFO)");
2310                     mSignalInfoRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2311                     break;
2312                 case EVENT_CDMA_OTA_STATUS_CHANGE:
2313                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_CDMA_OTA_STATUS_CHANGE)");
2314                     mCdmaOtaStatusChangeRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2315                     break;
2316                 case EVENT_RESEND_INCALL_MUTE:
2317                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_RESEND_INCALL_MUTE)");
2318                     mResendIncallMuteRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2319                     break;
2320                 case EVENT_MMI_INITIATE:
2321                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_MMI_INITIATE)");
2322                     mMmiInitiateRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2323                     break;
2324                 case EVENT_MMI_COMPLETE:
2325                     Rlog.d(LOG_TAG, "CallManager: handleMessage (EVENT_MMI_COMPLETE)");
2326                     mMmiCompleteRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2327                     break;
2328                 case EVENT_ECM_TIMER_RESET:
2329                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_ECM_TIMER_RESET)");
2330                     mEcmTimerResetRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2331                     break;
2332                 case EVENT_SUBSCRIPTION_INFO_READY:
2333                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SUBSCRIPTION_INFO_READY)");
2334                     mSubscriptionInfoReadyRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2335                     break;
2336                 case EVENT_SUPP_SERVICE_FAILED:
2337                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SUPP_SERVICE_FAILED)");
2338                     mSuppServiceFailedRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2339                     break;
2340                 case EVENT_SERVICE_STATE_CHANGED:
2341                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SERVICE_STATE_CHANGED)");
2342                     mServiceStateChangedRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2343                     // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
2344                     //setAudioMode();
2345                     break;
2346                 case EVENT_POST_DIAL_CHARACTER:
2347                     // we need send the character that is being processed in msg.arg1
2348                     // so can't use notifyRegistrants()
2349                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_POST_DIAL_CHARACTER)");
2350                     for(int i=0; i < mPostDialCharacterRegistrants.size(); i++) {
2351                         Message notifyMsg;
2352                         notifyMsg = ((Registrant)mPostDialCharacterRegistrants.get(i)).messageForRegistrant();
2353                         notifyMsg.obj = msg.obj;
2354                         notifyMsg.arg1 = msg.arg1;
2355                         notifyMsg.sendToTarget();
2356                     }
2357                     break;
2358                 case EVENT_ONHOLD_TONE:
2359                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_ONHOLD_TONE)");
2360                     mOnHoldToneRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2361                     break;
2362                 case EVENT_TTY_MODE_RECEIVED:
2363                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_TTY_MODE_RECEIVED)");
2364                     mTtyModeReceivedRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2365                     break;
2366                 /* FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
2367                 case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
2368                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_RADIO_OFF_OR_NOT_AVAILABLE)");
2369                     setAudioMode();
2370                     break;
2371                 */
2372             }
2373         }
2374     };
2375 
2376     @Override
toString()2377     public String toString() {
2378         Call call;
2379         StringBuilder b = new StringBuilder();
2380         for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
2381             b.append("CallManager {");
2382             b.append("\nstate = " + getState(i));
2383             call = getActiveFgCall(i);
2384             if (call != null) {
2385                 b.append("\n- Foreground: " + getActiveFgCallState(i));
2386                 b.append(" from " + call.getPhone());
2387                 b.append("\n  Conn: ").append(getFgCallConnections(i));
2388             }
2389             call = getFirstActiveBgCall(i);
2390             if (call != null) {
2391                 b.append("\n- Background: " + call.getState());
2392                 b.append(" from " + call.getPhone());
2393                 b.append("\n  Conn: ").append(getBgCallConnections(i));
2394             }
2395             call = getFirstActiveRingingCall(i);
2396             if (call != null) {
2397                 b.append("\n- Ringing: " +call.getState());
2398                 b.append(" from " + call.getPhone());
2399             }
2400         }
2401 
2402         for (Phone phone : getAllPhones()) {
2403             if (phone != null) {
2404                 b.append("\nPhone: " + phone + ", name = " + phone.getPhoneName()
2405                         + ", state = " + phone.getState());
2406                 call = phone.getForegroundCall();
2407                 if (call != null) {
2408                     b.append("\n- Foreground: ").append(call);
2409                 }
2410                 call = phone.getBackgroundCall();
2411                 if (call != null) {
2412                     b.append(" Background: ").append(call);
2413                 }
2414                 call = phone.getRingingCall();
2415                 if (call != null) {
2416                     b.append(" Ringing: ").append(call);
2417                 }
2418             }
2419         }
2420         b.append("\n}");
2421         return b.toString();
2422     }
2423 }
2424