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