ImsPhone.java revision 6bc4098827f3070a44b5e51508b455d7c7be9c07
1edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project/*
2edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Copyright (C) 2013 The Android Open Source Project
3edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
4edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * you may not use this file except in compliance with the License.
6edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * You may obtain a copy of the License at
7edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
8edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
10edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * See the License for the specific language governing permissions and
14edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * limitations under the License.
15edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project */
16edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
17edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectpackage com.android.internal.telephony.imsphone;
18edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
19edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectimport android.app.ActivityManagerNative;
20edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectimport android.content.Context;
21edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectimport android.content.Intent;
22076b1cc3a9b90aa5b381a1ed268ca0b548444c9bMathias Agopianimport android.os.AsyncResult;
23edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectimport android.os.Handler;
24edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectimport android.os.Message;
25edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectimport android.os.PowerManager;
26edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectimport android.os.Registrant;
27edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectimport android.os.RegistrantList;
283330b203039dea366d4981db1408a460134b2d2cMathias Agopianimport android.os.PowerManager.WakeLock;
29edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectimport android.os.SystemProperties;
309cce325fae8adcf7560a28eef394489f09bad74dMathias Agopianimport android.os.UserHandle;
319cce325fae8adcf7560a28eef394489f09bad74dMathias Agopian
32edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectimport android.telephony.PhoneNumberUtils;
33edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectimport android.telephony.ServiceState;
34edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectimport android.telephony.Rlog;
35edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectimport android.telephony.SubscriptionManager;
36edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectimport android.text.TextUtils;
37edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
38edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectimport com.android.ims.ImsCallForwardInfo;
39edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectimport com.android.ims.ImsCallProfile;
40edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectimport com.android.ims.ImsEcbm;
41edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectimport com.android.ims.ImsEcbmStateListener;
42edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectimport com.android.ims.ImsException;
43edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectimport com.android.ims.ImsReasonInfo;
44ca99fb8f65f3ea249c56fb6dccefffb54e87696eMathias Agopianimport com.android.ims.ImsSsInfo;
45ca99fb8f65f3ea249c56fb6dccefffb54e87696eMathias Agopianimport com.android.ims.ImsUtInterface;
46ca99fb8f65f3ea249c56fb6dccefffb54e87696eMathias Agopian
47ca99fb8f65f3ea249c56fb6dccefffb54e87696eMathias Agopianimport static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BAOC;
48edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectimport static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BAOIC;
49edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectimport static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BAOICxH;
5096f0819f81293076e652792794a961543e6750d7Mathias Agopianimport static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BAIC;
5196f0819f81293076e652792794a961543e6750d7Mathias Agopianimport static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BAICr;
5296f0819f81293076e652792794a961543e6750d7Mathias Agopianimport static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BA_ALL;
53d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopianimport static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BA_MO;
54edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectimport static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BA_MT;
55401c257fba770a267f637184b1f532b4e03bed20Mathias Agopian
56d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopianimport static com.android.internal.telephony.CommandsInterface.CF_ACTION_DISABLE;
57d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopianimport static com.android.internal.telephony.CommandsInterface.CF_ACTION_ENABLE;
58a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopianimport static com.android.internal.telephony.CommandsInterface.CF_ACTION_ERASURE;
59a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopianimport static com.android.internal.telephony.CommandsInterface.CF_ACTION_REGISTRATION;
60edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectimport static com.android.internal.telephony.CommandsInterface.CF_REASON_ALL;
61edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectimport static com.android.internal.telephony.CommandsInterface.CF_REASON_ALL_CONDITIONAL;
62edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectimport static com.android.internal.telephony.CommandsInterface.CF_REASON_NO_REPLY;
63edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectimport static com.android.internal.telephony.CommandsInterface.CF_REASON_NOT_REACHABLE;
64edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectimport static com.android.internal.telephony.CommandsInterface.CF_REASON_BUSY;
65bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopianimport static com.android.internal.telephony.CommandsInterface.CF_REASON_UNCONDITIONAL;
66bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopianimport static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_VOICE;
67bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopianimport static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_NONE;
68bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian
690aa758d64ac530833ce9a311b164c9175a7a054cMathias Agopianimport com.android.internal.telephony.Call;
70d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopianimport com.android.internal.telephony.CallForwardInfo;
71d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopianimport com.android.internal.telephony.CallStateException;
72d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopianimport com.android.internal.telephony.CallTracker;
7396f0819f81293076e652792794a961543e6750d7Mathias Agopianimport com.android.internal.telephony.CommandException;
7496f0819f81293076e652792794a961543e6750d7Mathias Agopianimport com.android.internal.telephony.CommandsInterface;
7596f0819f81293076e652792794a961543e6750d7Mathias Agopianimport com.android.internal.telephony.Connection;
7696f0819f81293076e652792794a961543e6750d7Mathias Agopianimport com.android.internal.telephony.Phone;
7796f0819f81293076e652792794a961543e6750d7Mathias Agopianimport com.android.internal.telephony.PhoneBase;
7896f0819f81293076e652792794a961543e6750d7Mathias Agopianimport com.android.internal.telephony.PhoneConstants;
7996f0819f81293076e652792794a961543e6750d7Mathias Agopianimport com.android.internal.telephony.PhoneNotifier;
8096f0819f81293076e652792794a961543e6750d7Mathias Agopianimport com.android.internal.telephony.TelephonyIntents;
8196f0819f81293076e652792794a961543e6750d7Mathias Agopianimport com.android.internal.telephony.TelephonyProperties;
8296f0819f81293076e652792794a961543e6750d7Mathias Agopianimport com.android.internal.telephony.cdma.CDMAPhone;
8396f0819f81293076e652792794a961543e6750d7Mathias Agopianimport com.android.internal.telephony.gsm.GSMPhone;
8496f0819f81293076e652792794a961543e6750d7Mathias Agopianimport com.android.internal.telephony.uicc.IccRecords;
8596f0819f81293076e652792794a961543e6750d7Mathias Agopian
8696f0819f81293076e652792794a961543e6750d7Mathias Agopianimport java.util.ArrayList;
8796f0819f81293076e652792794a961543e6750d7Mathias Agopianimport java.util.List;
8896f0819f81293076e652792794a961543e6750d7Mathias Agopian
89d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian/**
90d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian * {@hide}
91d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian */
92d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopianpublic class ImsPhone extends ImsPhoneBase {
9396f0819f81293076e652792794a961543e6750d7Mathias Agopian    private static final String LOG_TAG = "ImsPhone";
9496f0819f81293076e652792794a961543e6750d7Mathias Agopian    private static final boolean DBG = true;
9596f0819f81293076e652792794a961543e6750d7Mathias Agopian    private static final boolean VDBG = false; // STOPSHIP if true
9696f0819f81293076e652792794a961543e6750d7Mathias Agopian
9796f0819f81293076e652792794a961543e6750d7Mathias Agopian    protected static final int EVENT_SET_CALL_BARRING_DONE          = EVENT_LAST + 1;
9848d819a1315f7d1b5abfec9d4fd34fb5aed27b1dMathias Agopian    protected static final int EVENT_GET_CALL_BARRING_DONE          = EVENT_LAST + 2;
99cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian    protected static final int EVENT_SET_CALL_WAITING_DONE          = EVENT_LAST + 3;
100076b1cc3a9b90aa5b381a1ed268ca0b548444c9bMathias Agopian    protected static final int EVENT_GET_CALL_WAITING_DONE          = EVENT_LAST + 4;
101edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
102edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    public static final String CS_FALLBACK = "cs_fallback";
103edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
104edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    static final int RESTART_ECM_TIMER = 0; // restart Ecm timer
1059a11206fe793363c0e8897b478cbe6ef8c52b543Mathias Agopian    static final int CANCEL_ECM_TIMER = 1; // cancel Ecm timer
1069a11206fe793363c0e8897b478cbe6ef8c52b543Mathias Agopian
107bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian    // Default Emergency Callback Mode exit timer
108bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian    private static final int DEFAULT_ECM_EXIT_TIMER_VALUE = 300000;
1090aa758d64ac530833ce9a311b164c9175a7a054cMathias Agopian
110f5430db059be3e771c004d0ada594bf8820d0517Mathias Agopian    // Instance Variables
111bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian    PhoneBase mDefaultPhone;
112bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian    ImsPhoneCallTracker mCT;
113bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian    ArrayList <ImsPhoneMmiCode> mPendingMMIs = new ArrayList<ImsPhoneMmiCode>();
114bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian
115bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian    Registrant mPostDialHandler;
116bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian    ServiceState mSS = new ServiceState();
117bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian
1189a11206fe793363c0e8897b478cbe6ef8c52b543Mathias Agopian    // To redial silently through GSM or CDMA when dialing through IMS fails
1199a11206fe793363c0e8897b478cbe6ef8c52b543Mathias Agopian    private String mLastDialString;
1209a11206fe793363c0e8897b478cbe6ef8c52b543Mathias Agopian
121f9d932774e06d5122c48b47d8cabd791783f56d2Mathias Agopian    WakeLock mWakeLock;
122edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    protected boolean mIsPhoneInEcmState;
123edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
124401c257fba770a267f637184b1f532b4e03bed20Mathias Agopian    // mEcmExitRespRegistrant is informed after the phone has been exited the emergency
125edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    // callback mode keep track of if phone is in emergency callback mode
126edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    private Registrant mEcmExitRespRegistrant;
127edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
128edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    private final RegistrantList mSilentRedialRegistrants = new RegistrantList();
129401c257fba770a267f637184b1f532b4e03bed20Mathias Agopian
130401c257fba770a267f637184b1f532b4e03bed20Mathias Agopian    // A runnable which is used to automatically exit from Ecm after a period of time.
131ca99fb8f65f3ea249c56fb6dccefffb54e87696eMathias Agopian    private Runnable mExitEcmRunnable = new Runnable() {
132ca99fb8f65f3ea249c56fb6dccefffb54e87696eMathias Agopian        @Override
133ca99fb8f65f3ea249c56fb6dccefffb54e87696eMathias Agopian        public void run() {
134ca99fb8f65f3ea249c56fb6dccefffb54e87696eMathias Agopian            exitEmergencyCallbackMode();
135ca99fb8f65f3ea249c56fb6dccefffb54e87696eMathias Agopian        }
136ca99fb8f65f3ea249c56fb6dccefffb54e87696eMathias Agopian    };
137ca99fb8f65f3ea249c56fb6dccefffb54e87696eMathias Agopian
138ca99fb8f65f3ea249c56fb6dccefffb54e87696eMathias Agopian    // Create Cf (Call forward) so that dialling number &
139ca99fb8f65f3ea249c56fb6dccefffb54e87696eMathias Agopian    // mIsCfu (true if reason is call forward unconditional)
140401c257fba770a267f637184b1f532b4e03bed20Mathias Agopian    // mOnComplete (Message object passed by client) can be packed &
141401c257fba770a267f637184b1f532b4e03bed20Mathias Agopian    // given as a single Cf object as user data to UtInterface.
142a4b740ed89074cda898a30eb1b029b0d3a5de1a5Mathias Agopian    private static class Cf {
143a4b740ed89074cda898a30eb1b029b0d3a5de1a5Mathias Agopian        final String mSetCfNumber;
144cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian        final Message mOnComplete;
145ca99fb8f65f3ea249c56fb6dccefffb54e87696eMathias Agopian        final boolean mIsCfu;
146cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian
1473330b203039dea366d4981db1408a460134b2d2cMathias Agopian        Cf(String cfNumber, boolean isCfu, Message onComplete) {
148edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            mSetCfNumber = cfNumber;
149ca99fb8f65f3ea249c56fb6dccefffb54e87696eMathias Agopian            mIsCfu = isCfu;
150401c257fba770a267f637184b1f532b4e03bed20Mathias Agopian            mOnComplete = onComplete;
151401c257fba770a267f637184b1f532b4e03bed20Mathias Agopian        }
152401c257fba770a267f637184b1f532b4e03bed20Mathias Agopian    }
153401c257fba770a267f637184b1f532b4e03bed20Mathias Agopian
154401c257fba770a267f637184b1f532b4e03bed20Mathias Agopian    // Constructors
15596f0819f81293076e652792794a961543e6750d7Mathias Agopian
156edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    ImsPhone(Context context, PhoneNotifier notifier, Phone defaultPhone) {
157edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        super("ImsPhone", context, notifier);
158edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
159edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mDefaultPhone = (PhoneBase) defaultPhone;
160edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mCT = new ImsPhoneCallTracker(this);
161d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        mSS.setStateOff();
1628f03b47432f007b1fb3438608361ebf4e3a1310bMathias Agopian
1638f03b47432f007b1fb3438608361ebf4e3a1310bMathias Agopian        mPhoneId = mDefaultPhone.getPhoneId();
1648f03b47432f007b1fb3438608361ebf4e3a1310bMathias Agopian
1658f03b47432f007b1fb3438608361ebf4e3a1310bMathias Agopian        // This is needed to handle phone process crashes
1668f03b47432f007b1fb3438608361ebf4e3a1310bMathias Agopian        // Same property is used for both CDMA & IMS phone.
1678f03b47432f007b1fb3438608361ebf4e3a1310bMathias Agopian        mIsPhoneInEcmState = SystemProperties.getBoolean(
1688f03b47432f007b1fb3438608361ebf4e3a1310bMathias Agopian                TelephonyProperties.PROPERTY_INECM_MODE, false);
16954ba51dff21de666c5ae3bf3abd4f0634ebb0676Mathias Agopian
17057720c384af81327d327ef8b88078f11a750fd05Mathias Agopian        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
171d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG);
172d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        mWakeLock.setReferenceCounted(false);
173d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian    }
174d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian
175d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian    public void updateParentPhone(PhoneBase parentPhone) {
176076b1cc3a9b90aa5b381a1ed268ca0b548444c9bMathias Agopian        // synchronization is managed at the PhoneBase scope (which calls this function)
17754ba51dff21de666c5ae3bf3abd4f0634ebb0676Mathias Agopian        mDefaultPhone = parentPhone;
17854ba51dff21de666c5ae3bf3abd4f0634ebb0676Mathias Agopian        mPhoneId = mDefaultPhone.getPhoneId();
17954ba51dff21de666c5ae3bf3abd4f0634ebb0676Mathias Agopian    }
180fcfeb4b5970c8f361634429934a2518d7e8328ddMathias Agopian
181076b1cc3a9b90aa5b381a1ed268ca0b548444c9bMathias Agopian    @Override
1823330b203039dea366d4981db1408a460134b2d2cMathias Agopian    public void dispose() {
1830926f50664c739eaee60341f8e8c694dc9a4f3ebMathias Agopian        Rlog.d(LOG_TAG, "dispose");
1840926f50664c739eaee60341f8e8c694dc9a4f3ebMathias Agopian        // Nothing to dispose in PhoneBase
1850926f50664c739eaee60341f8e8c694dc9a4f3ebMathias Agopian        //super.dispose();
186d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        mPendingMMIs.clear();
1870926f50664c739eaee60341f8e8c694dc9a4f3ebMathias Agopian        mCT.dispose();
188076b1cc3a9b90aa5b381a1ed268ca0b548444c9bMathias Agopian
189edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        //Force all referenced classes to unregister their former registered events
190edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
191edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
192edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    @Override
193edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    public void removeReferences() {
194d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        Rlog.d(LOG_TAG, "removeReferences");
195d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        super.removeReferences();
196edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
197179169e88e05261196b76d7ddf94aa870aafaf9aMathias Agopian        mCT = null;
198179169e88e05261196b76d7ddf94aa870aafaf9aMathias Agopian        mSS = null;
199179169e88e05261196b76d7ddf94aa870aafaf9aMathias Agopian    }
200179169e88e05261196b76d7ddf94aa870aafaf9aMathias Agopian
201179169e88e05261196b76d7ddf94aa870aafaf9aMathias Agopian    @Override
202179169e88e05261196b76d7ddf94aa870aafaf9aMathias Agopian    public ServiceState
203179169e88e05261196b76d7ddf94aa870aafaf9aMathias Agopian    getServiceState() {
204179169e88e05261196b76d7ddf94aa870aafaf9aMathias Agopian        return mSS;
205179169e88e05261196b76d7ddf94aa870aafaf9aMathias Agopian    }
206179169e88e05261196b76d7ddf94aa870aafaf9aMathias Agopian
207179169e88e05261196b76d7ddf94aa870aafaf9aMathias Agopian    /* package */ void setServiceState(int state) {
208179169e88e05261196b76d7ddf94aa870aafaf9aMathias Agopian        mSS.setState(state);
209179169e88e05261196b76d7ddf94aa870aafaf9aMathias Agopian    }
210179169e88e05261196b76d7ddf94aa870aafaf9aMathias Agopian
211179169e88e05261196b76d7ddf94aa870aafaf9aMathias Agopian    @Override
212179169e88e05261196b76d7ddf94aa870aafaf9aMathias Agopian    public CallTracker getCallTracker() {
213179169e88e05261196b76d7ddf94aa870aafaf9aMathias Agopian        return mCT;
214179169e88e05261196b76d7ddf94aa870aafaf9aMathias Agopian    }
215179169e88e05261196b76d7ddf94aa870aafaf9aMathias Agopian
216179169e88e05261196b76d7ddf94aa870aafaf9aMathias Agopian    @Override
217179169e88e05261196b76d7ddf94aa870aafaf9aMathias Agopian    public List<? extends ImsPhoneMmiCode>
218179169e88e05261196b76d7ddf94aa870aafaf9aMathias Agopian    getPendingMmiCodes() {
219edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        return mPendingMMIs;
220edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
221d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian
222edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
223edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    @Override
224a7f669256f93a593c723f05784ef04d3c7d052bbMathias Agopian    public void
225a7f669256f93a593c723f05784ef04d3c7d052bbMathias Agopian    acceptCall(int videoState) throws CallStateException {
226a7f669256f93a593c723f05784ef04d3c7d052bbMathias Agopian        mCT.acceptCall(videoState);
227a7f669256f93a593c723f05784ef04d3c7d052bbMathias Agopian    }
228a7f669256f93a593c723f05784ef04d3c7d052bbMathias Agopian
229a7f669256f93a593c723f05784ef04d3c7d052bbMathias Agopian    @Override
230a7f669256f93a593c723f05784ef04d3c7d052bbMathias Agopian    public void
231a7f669256f93a593c723f05784ef04d3c7d052bbMathias Agopian    rejectCall() throws CallStateException {
232a7f669256f93a593c723f05784ef04d3c7d052bbMathias Agopian        mCT.rejectCall();
233a7f669256f93a593c723f05784ef04d3c7d052bbMathias Agopian    }
234a7f669256f93a593c723f05784ef04d3c7d052bbMathias Agopian
235a7f669256f93a593c723f05784ef04d3c7d052bbMathias Agopian    @Override
236a7f669256f93a593c723f05784ef04d3c7d052bbMathias Agopian    public void
237b5b7f260da2c1a2a82e0311e2015d49a82f43667Mathias Agopian    switchHoldingAndActive() throws CallStateException {
238b5b7f260da2c1a2a82e0311e2015d49a82f43667Mathias Agopian        mCT.switchWaitingOrHoldingAndActive();
239b5b7f260da2c1a2a82e0311e2015d49a82f43667Mathias Agopian    }
240bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian
241b5b7f260da2c1a2a82e0311e2015d49a82f43667Mathias Agopian    @Override
242b5b7f260da2c1a2a82e0311e2015d49a82f43667Mathias Agopian    public boolean canConference() {
243b5b7f260da2c1a2a82e0311e2015d49a82f43667Mathias Agopian        return mCT.canConference();
244b5b7f260da2c1a2a82e0311e2015d49a82f43667Mathias Agopian    }
245b5b7f260da2c1a2a82e0311e2015d49a82f43667Mathias Agopian
246b5b7f260da2c1a2a82e0311e2015d49a82f43667Mathias Agopian    public boolean canDial() {
247b5b7f260da2c1a2a82e0311e2015d49a82f43667Mathias Agopian        return mCT.canDial();
248bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian    }
249bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian
250bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian    @Override
251bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian    public void conference() {
252b5b7f260da2c1a2a82e0311e2015d49a82f43667Mathias Agopian        mCT.conference();
253b5b7f260da2c1a2a82e0311e2015d49a82f43667Mathias Agopian    }
254b5b7f260da2c1a2a82e0311e2015d49a82f43667Mathias Agopian
255b5b7f260da2c1a2a82e0311e2015d49a82f43667Mathias Agopian    @Override
256a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian    public void clearDisconnected() {
257a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian        mCT.clearDisconnected();
258a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian    }
259edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
2603330b203039dea366d4981db1408a460134b2d2cMathias Agopian    @Override
26148d819a1315f7d1b5abfec9d4fd34fb5aed27b1dMathias Agopian    public boolean canTransfer() {
262a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian        return mCT.canTransfer();
263a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian    }
264a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian
265a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian    @Override
266a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian    public void explicitCallTransfer() {
267a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian        mCT.explicitCallTransfer();
26848d819a1315f7d1b5abfec9d4fd34fb5aed27b1dMathias Agopian    }
26948d819a1315f7d1b5abfec9d4fd34fb5aed27b1dMathias Agopian
27048d819a1315f7d1b5abfec9d4fd34fb5aed27b1dMathias Agopian    @Override
27148d819a1315f7d1b5abfec9d4fd34fb5aed27b1dMathias Agopian    public ImsPhoneCall
27248d819a1315f7d1b5abfec9d4fd34fb5aed27b1dMathias Agopian    getForegroundCall() {
27348d819a1315f7d1b5abfec9d4fd34fb5aed27b1dMathias Agopian        return mCT.mForegroundCall;
27448d819a1315f7d1b5abfec9d4fd34fb5aed27b1dMathias Agopian    }
27548d819a1315f7d1b5abfec9d4fd34fb5aed27b1dMathias Agopian
276076b1cc3a9b90aa5b381a1ed268ca0b548444c9bMathias Agopian    @Override
277cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian    public ImsPhoneCall
278cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian    getBackgroundCall() {
279cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian        return mCT.mBackgroundCall;
280bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian    }
281cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian
282cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian    @Override
283cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian    public ImsPhoneCall
284cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian    getRingingCall() {
285076b1cc3a9b90aa5b381a1ed268ca0b548444c9bMathias Agopian        return mCT.mRingingCall;
286cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian    }
287cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian
28848d819a1315f7d1b5abfec9d4fd34fb5aed27b1dMathias Agopian    private boolean handleCallDeflectionIncallSupplementaryService(
28948d819a1315f7d1b5abfec9d4fd34fb5aed27b1dMathias Agopian            String dialString) {
29048d819a1315f7d1b5abfec9d4fd34fb5aed27b1dMathias Agopian        if (dialString.length() > 1) {
29148d819a1315f7d1b5abfec9d4fd34fb5aed27b1dMathias Agopian            return false;
29248d819a1315f7d1b5abfec9d4fd34fb5aed27b1dMathias Agopian        }
293a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian
29448d819a1315f7d1b5abfec9d4fd34fb5aed27b1dMathias Agopian        if (getRingingCall().getState() != ImsPhoneCall.State.IDLE) {
29548d819a1315f7d1b5abfec9d4fd34fb5aed27b1dMathias Agopian            if (DBG) Rlog.d(LOG_TAG, "MmiCode 0: rejectCall");
296a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian            try {
297a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian                mCT.rejectCall();
298a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian            } catch (CallStateException e) {
299a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian                if (DBG) Rlog.d(LOG_TAG, "reject failed", e);
300a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian                notifySuppServiceFailed(Phone.SuppService.REJECT);
301a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian            }
302a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian        } else if (getBackgroundCall().getState() != ImsPhoneCall.State.IDLE) {
303a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian            if (DBG) Rlog.d(LOG_TAG, "MmiCode 0: hangupWaitingOrBackground");
304a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian            try {
305d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian                mCT.hangup(getBackgroundCall());
306a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian            } catch (CallStateException e) {
307a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian                if (DBG) Rlog.d(LOG_TAG, "hangup failed", e);
308a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian            }
30948d819a1315f7d1b5abfec9d4fd34fb5aed27b1dMathias Agopian        }
31048d819a1315f7d1b5abfec9d4fd34fb5aed27b1dMathias Agopian
3113330b203039dea366d4981db1408a460134b2d2cMathias Agopian        return true;
3126d9f69843bae31b2da9a8f2869547b1ff5d0654dMathias Agopian    }
313a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian
314cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian
315cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian    private boolean handleCallWaitingIncallSupplementaryService(
316cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian            String dialString) {
317cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian        int len = dialString.length();
318cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian
319a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian        if (len > 2) {
320cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian            return false;
321076b1cc3a9b90aa5b381a1ed268ca0b548444c9bMathias Agopian        }
322cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian
323cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian        ImsPhoneCall call = getForegroundCall();
324cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian
325cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian        try {
326cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian            if (len > 1) {
327edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                if (DBG) Rlog.d(LOG_TAG, "not support 1X SEND");
328cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian                notifySuppServiceFailed(Phone.SuppService.HANGUP);
3297e4a587f6038bcf9b58ca615fce9e52fd47e30c3Mathias Agopian            } else {
3307e4a587f6038bcf9b58ca615fce9e52fd47e30c3Mathias Agopian                if (call.getState() != ImsPhoneCall.State.IDLE) {
331edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    if (DBG) Rlog.d(LOG_TAG, "MmiCode 1: hangup foreground");
332edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    mCT.hangup(call);
333cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian                } else {
33448d819a1315f7d1b5abfec9d4fd34fb5aed27b1dMathias Agopian                    if (DBG) Rlog.d(LOG_TAG, "MmiCode 1: switchWaitingOrHoldingAndActive");
335a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian                    mCT.switchWaitingOrHoldingAndActive();
336f9d932774e06d5122c48b47d8cabd791783f56d2Mathias Agopian                }
337cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian            }
338f9d932774e06d5122c48b47d8cabd791783f56d2Mathias Agopian        } catch (CallStateException e) {
339f9d932774e06d5122c48b47d8cabd791783f56d2Mathias Agopian            if (DBG) Rlog.d(LOG_TAG, "hangup failed", e);
3403330b203039dea366d4981db1408a460134b2d2cMathias Agopian            notifySuppServiceFailed(Phone.SuppService.HANGUP);
3413330b203039dea366d4981db1408a460134b2d2cMathias Agopian        }
3423330b203039dea366d4981db1408a460134b2d2cMathias Agopian
3433330b203039dea366d4981db1408a460134b2d2cMathias Agopian        return true;
3443330b203039dea366d4981db1408a460134b2d2cMathias Agopian    }
3453330b203039dea366d4981db1408a460134b2d2cMathias Agopian
3463330b203039dea366d4981db1408a460134b2d2cMathias Agopian    private boolean handleCallHoldIncallSupplementaryService(String dialString) {
3473330b203039dea366d4981db1408a460134b2d2cMathias Agopian        int len = dialString.length();
3483330b203039dea366d4981db1408a460134b2d2cMathias Agopian
3493330b203039dea366d4981db1408a460134b2d2cMathias Agopian        if (len > 2) {
3503330b203039dea366d4981db1408a460134b2d2cMathias Agopian            return false;
3513330b203039dea366d4981db1408a460134b2d2cMathias Agopian        }
3523330b203039dea366d4981db1408a460134b2d2cMathias Agopian
3533330b203039dea366d4981db1408a460134b2d2cMathias Agopian        ImsPhoneCall call = getForegroundCall();
3543330b203039dea366d4981db1408a460134b2d2cMathias Agopian
3553330b203039dea366d4981db1408a460134b2d2cMathias Agopian        if (len > 1) {
3563330b203039dea366d4981db1408a460134b2d2cMathias Agopian            if (DBG) Rlog.d(LOG_TAG, "separate not supported");
3573330b203039dea366d4981db1408a460134b2d2cMathias Agopian            notifySuppServiceFailed(Phone.SuppService.SEPARATE);
3583330b203039dea366d4981db1408a460134b2d2cMathias Agopian        } else {
3593330b203039dea366d4981db1408a460134b2d2cMathias Agopian            try {
3603330b203039dea366d4981db1408a460134b2d2cMathias Agopian                if (getRingingCall().getState() != ImsPhoneCall.State.IDLE) {
36189141f949270100d1cacecf99cc2ff25fce79087Mathias Agopian                    if (DBG) Rlog.d(LOG_TAG, "MmiCode 2: accept ringing call");
36289141f949270100d1cacecf99cc2ff25fce79087Mathias Agopian                    mCT.acceptCall(ImsCallProfile.CALL_TYPE_VOICE);
3633330b203039dea366d4981db1408a460134b2d2cMathias Agopian                } else {
3643330b203039dea366d4981db1408a460134b2d2cMathias Agopian                    if (DBG) Rlog.d(LOG_TAG, "MmiCode 2: switchWaitingOrHoldingAndActive");
3653330b203039dea366d4981db1408a460134b2d2cMathias Agopian                    mCT.switchWaitingOrHoldingAndActive();
3663330b203039dea366d4981db1408a460134b2d2cMathias Agopian                }
367edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            } catch (CallStateException e) {
368edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                if (DBG) Rlog.d(LOG_TAG, "switch failed", e);
369edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                notifySuppServiceFailed(Phone.SuppService.SWITCH);
370edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            }
371edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        }
372a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian
373a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian        return true;
374a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian    }
375a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian
376cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian    private boolean handleMultipartyIncallSupplementaryService(
377edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            String dialString) {
378a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian        if (dialString.length() > 1) {
379a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian            return false;
380a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian        }
381a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian
382a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian        if (DBG) Rlog.d(LOG_TAG, "MmiCode 3: merge calls");
383a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian        conference();
384a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian        return true;
385a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian    }
386a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian
387a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian    private boolean handleEctIncallSupplementaryService(String dialString) {
388a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian
389a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian        int len = dialString.length();
390a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian
391a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian        if (len != 1) {
392a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian            return false;
393a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian        }
394edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
395caa600c4a1af1eefd108cf2ec3d86068af35111fMathias Agopian        if (DBG) Rlog.d(LOG_TAG, "MmiCode 4: not support explicit call transfer");
396a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian        notifySuppServiceFailed(Phone.SuppService.TRANSFER);
397a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian        return true;
398a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian    }
399a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian
400a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian    private boolean handleCcbsIncallSupplementaryService(String dialString) {
401df3e0b934f2822ea0a334777e51e681f04a64d7cMathias Agopian        if (dialString.length() > 1) {
402a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian            return false;
403a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian        }
404a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian
4056656dbc81273424d9b4bf78c42a4e179dbe1cb71Mathias Agopian        Rlog.i(LOG_TAG, "MmiCode 5: CCBS not supported!");
40696f0819f81293076e652792794a961543e6750d7Mathias Agopian        // Treat it as an "unknown" service.
40796f0819f81293076e652792794a961543e6750d7Mathias Agopian        notifySuppServiceFailed(Phone.SuppService.UNKNOWN);
40896f0819f81293076e652792794a961543e6750d7Mathias Agopian        return true;
40996f0819f81293076e652792794a961543e6750d7Mathias Agopian    }
41096f0819f81293076e652792794a961543e6750d7Mathias Agopian
411a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian    @Override
412a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian    public boolean handleInCallMmiCommands(String dialString) {
413a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian        if (!isInCall()) {
414a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian            return false;
415edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        }
416cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian
417edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        if (TextUtils.isEmpty(dialString)) {
418edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            return false;
419edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        }
420edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
421edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        boolean result = false;
422edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        char ch = dialString.charAt(0);
423edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        switch (ch) {
424edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            case '0':
425edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                result = handleCallDeflectionIncallSupplementaryService(
426edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                        dialString);
427edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                break;
428a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian            case '1':
429cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian                result = handleCallWaitingIncallSupplementaryService(
430cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian                        dialString);
431cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian                break;
432edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            case '2':
433edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                result = handleCallHoldIncallSupplementaryService(dialString);
434a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian                break;
435a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian            case '3':
436a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian                result = handleMultipartyIncallSupplementaryService(dialString);
437a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian                break;
438a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian            case '4':
439edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                result = handleEctIncallSupplementaryService(dialString);
440edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                break;
441edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            case '5':
442edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                result = handleCcbsIncallSupplementaryService(dialString);
443edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                break;
444edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            default:
44596f0819f81293076e652792794a961543e6750d7Mathias Agopian                break;
44696f0819f81293076e652792794a961543e6750d7Mathias Agopian        }
44796f0819f81293076e652792794a961543e6750d7Mathias Agopian
44896f0819f81293076e652792794a961543e6750d7Mathias Agopian        return result;
44996f0819f81293076e652792794a961543e6750d7Mathias Agopian    }
45096f0819f81293076e652792794a961543e6750d7Mathias Agopian
45196f0819f81293076e652792794a961543e6750d7Mathias Agopian    boolean isInCall() {
452cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian        ImsPhoneCall.State foregroundCallState = getForegroundCall().getState();
453d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        ImsPhoneCall.State backgroundCallState = getBackgroundCall().getState();
454d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        ImsPhoneCall.State ringingCallState = getRingingCall().getState();
455d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian
456cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian       return (foregroundCallState.isAlive() ||
457edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project               backgroundCallState.isAlive() ||
458edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project               ringingCallState.isAlive());
459d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian    }
460d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian
461d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian    void notifyNewRingingConnection(Connection c) {
462d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian        mDefaultPhone.notifyNewRingingConnectionP(c);
463d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian    }
464d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian
465d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian
466cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian    @Override
467d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian    public Connection
468d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian    dial(String dialString, int videoState) throws CallStateException {
469d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        return dialInternal(dialString, videoState);
470d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian    }
471d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian
472edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    protected Connection dialInternal(String dialString, int videoState)
473cbb288bfe89f585bf48371bd31b2d4aafa32f32eMathias Agopian            throws CallStateException {
4743330b203039dea366d4981db1408a460134b2d2cMathias Agopian        // Need to make sure dialString gets parsed properly
475d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian        String newDialString = PhoneNumberUtils.stripSeparators(dialString);
476d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian
477d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian        // handle in-call MMI first if applicable
478d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian        if (handleInCallMmiCommands(newDialString)) {
479d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian            return null;
480d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian        }
481d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian
482d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian        if (mDefaultPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
483d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian            return mCT.dial(dialString, videoState);
484df3e0b934f2822ea0a334777e51e681f04a64d7cMathias Agopian        }
485d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian
486d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian        // Only look at the Network portion for mmi
487d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian        String networkPortion = PhoneNumberUtils.extractNetworkPortionAlt(newDialString);
488d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian        ImsPhoneMmiCode mmi =
489d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian                ImsPhoneMmiCode.newFromDialString(networkPortion, this);
490d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian        if (DBG) Rlog.d(LOG_TAG,
491d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian                "dialing w/ mmi '" + mmi + "'...");
492d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian
493d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian        if (mmi == null) {
494d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian            return mCT.dial(dialString, videoState);
495d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian        } else if (mmi.isTemporaryModeCLIR()) {
496d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian            return mCT.dial(mmi.getDialingNumber(), mmi.getCLIRMode(), videoState);
497d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian        } else if (!mmi.isSupportedOverImsPhone()) {
498d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian            // If the mmi is not supported by IMS service,
499d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian            // try to initiate dialing with default phone
500d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian            throw new CallStateException(CS_FALLBACK);
501d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian        } else {
502d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian            mPendingMMIs.add(mmi);
503d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian            mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
504d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian            mmi.processCode();
505d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian
506d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian            return null;
5078f2d50521653f24c2a5e77b627dc015c7fbd656aMathias Agopian        }
508d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian    }
509d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian
510d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian    @Override
511d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian    public void
512d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian    sendDtmf(char c) {
513d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian        if (!PhoneNumberUtils.is12Key(c)) {
514d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian            Rlog.e(LOG_TAG,
515d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian                    "sendDtmf called with invalid character '" + c + "'");
516d343e3d5e3177806205b9452b0b43907e28afd9aMathias Agopian        } else {
517caa600c4a1af1eefd108cf2ec3d86068af35111fMathias Agopian            if (mCT.mState ==  PhoneConstants.State.OFFHOOK) {
518caa600c4a1af1eefd108cf2ec3d86068af35111fMathias Agopian                mCT.sendDtmf(c);
519e700501d0e888ead9ac6456c0a6fd74d634aa5fbMathias Agopian            }
520e700501d0e888ead9ac6456c0a6fd74d634aa5fbMathias Agopian        }
521e700501d0e888ead9ac6456c0a6fd74d634aa5fbMathias Agopian    }
522e700501d0e888ead9ac6456c0a6fd74d634aa5fbMathias Agopian
523edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    @Override
524245e4d78c5fb304fe153c36303ec69bf8a907f65Mathias Agopian    public void
525245e4d78c5fb304fe153c36303ec69bf8a907f65Mathias Agopian    startDtmf(char c) {
526245e4d78c5fb304fe153c36303ec69bf8a907f65Mathias Agopian        if (!PhoneNumberUtils.is12Key(c)) {
527245e4d78c5fb304fe153c36303ec69bf8a907f65Mathias Agopian            Rlog.e(LOG_TAG,
528245e4d78c5fb304fe153c36303ec69bf8a907f65Mathias Agopian                    "startDtmf called with invalid character '" + c + "'");
529245e4d78c5fb304fe153c36303ec69bf8a907f65Mathias Agopian        } else {
530245e4d78c5fb304fe153c36303ec69bf8a907f65Mathias Agopian            sendDtmf(c);
531245e4d78c5fb304fe153c36303ec69bf8a907f65Mathias Agopian        }
532245e4d78c5fb304fe153c36303ec69bf8a907f65Mathias Agopian    }
533edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
534edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    @Override
535edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    public void
536edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    stopDtmf() {
537edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // no op
538edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
539edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
540edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    @Override
541edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    public void setOnPostDialCharacter(Handler h, int what, Object obj) {
542edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mPostDialHandler = new Registrant(h, what, obj);
543edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
544edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
545edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    /*package*/ void notifyIncomingRing() {
546edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        if (DBG) Rlog.d(LOG_TAG, "notifyIncomingRing");
547edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        AsyncResult ar = new AsyncResult(null, null, null);
548edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        sendMessage(obtainMessage(EVENT_CALL_RING, ar));
549edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
550edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
551edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    @Override
552edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    public void setMute(boolean muted) {
553edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mCT.setMute(muted);
554c61de17f143b5f806c5bab9cc58910a322302b70Mathias Agopian    }
555c61de17f143b5f806c5bab9cc58910a322302b70Mathias Agopian
5561b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian    @Override
557c61de17f143b5f806c5bab9cc58910a322302b70Mathias Agopian    public boolean getMute() {
558c61de17f143b5f806c5bab9cc58910a322302b70Mathias Agopian        return mCT.getMute();
559edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
560edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
561edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    @Override
562edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    public PhoneConstants.State getState() {
56396f0819f81293076e652792794a961543e6750d7Mathias Agopian        return mCT.mState;
56496f0819f81293076e652792794a961543e6750d7Mathias Agopian    }
56596f0819f81293076e652792794a961543e6750d7Mathias Agopian
56696f0819f81293076e652792794a961543e6750d7Mathias Agopian    private boolean isValidCommandInterfaceCFReason (int commandInterfaceCFReason) {
56796f0819f81293076e652792794a961543e6750d7Mathias Agopian        switch (commandInterfaceCFReason) {
56896f0819f81293076e652792794a961543e6750d7Mathias Agopian        case CF_REASON_UNCONDITIONAL:
569edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        case CF_REASON_BUSY:
570edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        case CF_REASON_NO_REPLY:
5711b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian        case CF_REASON_NOT_REACHABLE:
5721b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian        case CF_REASON_ALL:
5731b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian        case CF_REASON_ALL_CONDITIONAL:
5741b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian            return true;
5751b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian        default:
5761b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian            return false;
5771b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian        }
5781b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian    }
5791b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian
5801b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian    private boolean isValidCommandInterfaceCFAction (int commandInterfaceCFAction) {
5811b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian        switch (commandInterfaceCFAction) {
5821b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian        case CF_ACTION_DISABLE:
5831b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian        case CF_ACTION_ENABLE:
5841b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian        case CF_ACTION_REGISTRATION:
5851b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian        case CF_ACTION_ERASURE:
5861b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian            return true;
5871b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian        default:
5881b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian            return false;
5891b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian        }
5901b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian    }
5911b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian
5921b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian    private  boolean isCfEnable(int action) {
5931b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian        return (action == CF_ACTION_ENABLE) || (action == CF_ACTION_REGISTRATION);
5941b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian    }
5951b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian
5961b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian    private int getConditionFromCFReason(int reason) {
5971b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian        switch(reason) {
5981b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian            case CF_REASON_UNCONDITIONAL: return ImsUtInterface.CDIV_CF_UNCONDITIONAL;
5991b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian            case CF_REASON_BUSY: return ImsUtInterface.CDIV_CF_BUSY;
6001b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian            case CF_REASON_NO_REPLY: return ImsUtInterface.CDIV_CF_NO_REPLY;
6011b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian            case CF_REASON_NOT_REACHABLE: return ImsUtInterface.CDIV_CF_NOT_REACHABLE;
6021b5e1021b8c9b87113b70d94dfb7b50f8c5b01b8Mathias Agopian            default:
603076b1cc3a9b90aa5b381a1ed268ca0b548444c9bMathias Agopian                break;
604076b1cc3a9b90aa5b381a1ed268ca0b548444c9bMathias Agopian        }
605d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian
606bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian        return ImsUtInterface.INVALID;
607bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian    }
608bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian
609bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian    private int getCFReasonFromCondition(int condition) {
610bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian        switch(condition) {
611bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian            case ImsUtInterface.CDIV_CF_UNCONDITIONAL: return CF_REASON_UNCONDITIONAL;
612d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian            case ImsUtInterface.CDIV_CF_BUSY: return CF_REASON_BUSY;
613d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian            case ImsUtInterface.CDIV_CF_NO_REPLY: return CF_REASON_NO_REPLY;
614d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian            case ImsUtInterface.CDIV_CF_NOT_REACHABLE: return CF_REASON_NOT_REACHABLE;
615bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian            default:
616bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian                break;
617bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian        }
618bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian
619bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian        return CF_REASON_NOT_REACHABLE;
620d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian    }
621d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian
622d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian    private int getActionFromCFAction(int action) {
623d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        switch(action) {
624d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian            case CF_ACTION_DISABLE: return ImsUtInterface.ACTION_DEACTIVATION;
625d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian            case CF_ACTION_ENABLE: return ImsUtInterface.ACTION_ACTIVATION;
626d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian            case CF_ACTION_ERASURE: return ImsUtInterface.ACTION_ERASURE;
627d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian            case CF_ACTION_REGISTRATION: return ImsUtInterface.ACTION_REGISTRATION;
628d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian            default:
629d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian                break;
630d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        }
631d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian
632d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        return ImsUtInterface.INVALID;
633d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian    }
634d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian
635d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian    @Override
636d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian    public void getCallForwardingOption(int commandInterfaceCFReason,
637d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian            Message onComplete) {
638bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian        if (DBG) Rlog.d(LOG_TAG, "getCallForwardingOption reason=" + commandInterfaceCFReason);
639bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian        if (isValidCommandInterfaceCFReason(commandInterfaceCFReason)) {
640bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian            if (DBG) Rlog.d(LOG_TAG, "requesting call forwarding query.");
641bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian            Message resp;
642bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian            resp = obtainMessage(EVENT_GET_CALL_FORWARD_DONE, onComplete);
643bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian
644bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian            try {
645d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian                ImsUtInterface ut = mCT.getUtInterface();
646d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian                ut.queryCallForward(getConditionFromCFReason(commandInterfaceCFReason),null,resp);
647d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian            } catch (ImsException e) {
648bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian                sendErrorResponse(onComplete, e);
649bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian            }
650d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        } else if (onComplete != null) {
651bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian            sendErrorResponse(onComplete);
652d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        }
653d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian    }
654d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian
655d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian    @Override
656bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian    public void setCallForwardingOption(int commandInterfaceCFAction,
657d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian            int commandInterfaceCFReason,
658d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian            String dialingNumber,
659bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian            int timerSeconds,
660bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian            Message onComplete) {
661d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        if (DBG) Rlog.d(LOG_TAG, "setCallForwardingOption action=" + commandInterfaceCFAction
662d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian                + ", reason=" + commandInterfaceCFReason);
663d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        if ((isValidCommandInterfaceCFAction(commandInterfaceCFAction)) &&
664d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian                (isValidCommandInterfaceCFReason(commandInterfaceCFReason))) {
665d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian            Message resp;
666d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian            Cf cf = new Cf(dialingNumber,
667bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian                    (commandInterfaceCFReason == CF_REASON_UNCONDITIONAL ? true : false),
668d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian                    onComplete);
669bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian            resp = obtainMessage(EVENT_SET_CALL_FORWARD_DONE,
670bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian                    isCfEnable(commandInterfaceCFAction) ? 1 : 0, 0, cf);
671d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian
672d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian            try {
673d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian                ImsUtInterface ut = mCT.getUtInterface();
674d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian                ut.updateCallForward(getActionFromCFAction(commandInterfaceCFAction),
675d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian                        getConditionFromCFReason(commandInterfaceCFReason),
676bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian                        dialingNumber,
677bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian                        timerSeconds,
678bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian                        onComplete);
679bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian             } catch (ImsException e) {
680bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian                sendErrorResponse(onComplete, e);
681bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian             }
682bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian        } else if (onComplete != null) {
683bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian            sendErrorResponse(onComplete);
684bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian        }
685bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian    }
686bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian
687d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian    @Override
688d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian    public void getCallWaiting(Message onComplete) {
689d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        if (DBG) Rlog.d(LOG_TAG, "getCallWaiting");
690d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        Message resp;
691d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        resp = obtainMessage(EVENT_GET_CALL_WAITING_DONE, onComplete);
692d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian
693d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        try {
694d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian            ImsUtInterface ut = mCT.getUtInterface();
695d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian            ut.queryCallWaiting(resp);
696bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian        } catch (ImsException e) {
697d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian            sendErrorResponse(onComplete, e);
698d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        }
699d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian    }
700d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian
701d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian    @Override
702d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian    public void setCallWaiting(boolean enable, Message onComplete) {
703d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        if (DBG) Rlog.d(LOG_TAG, "setCallWaiting enable=" + enable);
704d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        Message resp;
705bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian        resp = obtainMessage(EVENT_SET_CALL_WAITING_DONE, onComplete);
706bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian
707d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        try {
708d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian            ImsUtInterface ut = mCT.getUtInterface();
709d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian            ut.updateCallWaiting(enable, resp);
710d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        } catch (ImsException e) {
711d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian            sendErrorResponse(onComplete, e);
712d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        }
713d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian    }
714d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian
715d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian    private int getCBTypeFromFacility(String facility) {
716d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        if (CB_FACILITY_BAOC.equals(facility)) {
717d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian            return ImsUtInterface.CB_BAOC;
718d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        } else if (CB_FACILITY_BAOIC.equals(facility)) {
719bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian            return ImsUtInterface.CB_BOIC;
720bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian        } else if (CB_FACILITY_BAOICxH.equals(facility)) {
721bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian            return ImsUtInterface.CB_BOIC_EXHC;
722bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian        } else if (CB_FACILITY_BAIC.equals(facility)) {
723bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian            return ImsUtInterface.CB_BAIC;
724bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian        } else if (CB_FACILITY_BAICr.equals(facility)) {
725bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian            return ImsUtInterface.CB_BIC_WR;
726bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian        } else if (CB_FACILITY_BA_ALL.equals(facility)) {
727bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian            return ImsUtInterface.CB_BA_ALL;
728bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian        } else if (CB_FACILITY_BA_MO.equals(facility)) {
729bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian            return ImsUtInterface.CB_BA_MO;
730bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian        } else if (CB_FACILITY_BA_MT.equals(facility)) {
731bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian            return ImsUtInterface.CB_BA_MT;
732d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian        }
733d606de6bb6877dc4ab93ec0be0c6bda4a8ee1ce8Mathias Agopian
7349a11206fe793363c0e8897b478cbe6ef8c52b543Mathias Agopian        return 0;
73596f0819f81293076e652792794a961543e6750d7Mathias Agopian    }
73696f0819f81293076e652792794a961543e6750d7Mathias Agopian
7379a11206fe793363c0e8897b478cbe6ef8c52b543Mathias Agopian    /* package */
7389a11206fe793363c0e8897b478cbe6ef8c52b543Mathias Agopian    void getCallBarring(String facility, Message onComplete) {
7399a11206fe793363c0e8897b478cbe6ef8c52b543Mathias Agopian        if (DBG) Rlog.d(LOG_TAG, "getCallBarring facility=" + facility);
7409a11206fe793363c0e8897b478cbe6ef8c52b543Mathias Agopian        Message resp;
741076b1cc3a9b90aa5b381a1ed268ca0b548444c9bMathias Agopian        resp = obtainMessage(EVENT_GET_CALL_BARRING_DONE, onComplete);
742076b1cc3a9b90aa5b381a1ed268ca0b548444c9bMathias Agopian
743076b1cc3a9b90aa5b381a1ed268ca0b548444c9bMathias Agopian        try {
744a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian            ImsUtInterface ut = mCT.getUtInterface();
745a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian            ut.queryCallBarring(getCBTypeFromFacility(facility), resp);
746076b1cc3a9b90aa5b381a1ed268ca0b548444c9bMathias Agopian        } catch (ImsException e) {
7473330b203039dea366d4981db1408a460134b2d2cMathias Agopian            sendErrorResponse(onComplete, e);
748076b1cc3a9b90aa5b381a1ed268ca0b548444c9bMathias Agopian        }
749076b1cc3a9b90aa5b381a1ed268ca0b548444c9bMathias Agopian    }
750bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian
751bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian    /* package */
752bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian    void setCallBarring(String facility, boolean lockState, String password, Message onComplete) {
753bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian        if (DBG) Rlog.d(LOG_TAG, "setCallBarring facility=" + facility
754bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian                + ", lockState=" + lockState);
755a138f89c5e78b7e8994823e97d6e860869762837Mathias Agopian        Message resp;
756076b1cc3a9b90aa5b381a1ed268ca0b548444c9bMathias Agopian        resp = obtainMessage(EVENT_SET_CALL_BARRING_DONE, onComplete);
757076b1cc3a9b90aa5b381a1ed268ca0b548444c9bMathias Agopian
758076b1cc3a9b90aa5b381a1ed268ca0b548444c9bMathias Agopian        try {
759edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            ImsUtInterface ut = mCT.getUtInterface();
760b5b7f260da2c1a2a82e0311e2015d49a82f43667Mathias Agopian            // password is not required with Ut interface
761b5b7f260da2c1a2a82e0311e2015d49a82f43667Mathias Agopian            ut.updateCallBarring(getCBTypeFromFacility(facility), lockState, resp, null);
762b5b7f260da2c1a2a82e0311e2015d49a82f43667Mathias Agopian        } catch (ImsException e) {
763b5b7f260da2c1a2a82e0311e2015d49a82f43667Mathias Agopian            sendErrorResponse(onComplete, e);
764b5b7f260da2c1a2a82e0311e2015d49a82f43667Mathias Agopian        }
765bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian    }
766bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian
767bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian    @Override
768bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian    public void sendUssdResponse(String ussdMessge) {
769bb641244d7d73312dc65b8e338df18b22e335107Mathias Agopian        Rlog.d(LOG_TAG, "sendUssdResponse");
770b5b7f260da2c1a2a82e0311e2015d49a82f43667Mathias Agopian        ImsPhoneMmiCode mmi = ImsPhoneMmiCode.newFromUssdUserInput(ussdMessge, this);
771b5b7f260da2c1a2a82e0311e2015d49a82f43667Mathias Agopian        mPendingMMIs.add(mmi);
772b5b7f260da2c1a2a82e0311e2015d49a82f43667Mathias Agopian        mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
773b5b7f260da2c1a2a82e0311e2015d49a82f43667Mathias Agopian        mmi.sendUssd(ussdMessge);
774b5b7f260da2c1a2a82e0311e2015d49a82f43667Mathias Agopian    }
775edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
776edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    /* package */
777edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    void sendUSSD (String ussdString, Message response) {
778edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        mCT.sendUSSD(ussdString, response);
779    }
780
781    /* package */
782    void cancelUSSD() {
783        mCT.cancelUSSD();
784    }
785
786    /* package */
787    void sendErrorResponse(Message onComplete) {
788        Rlog.d(LOG_TAG, "sendErrorResponse");
789        if (onComplete != null) {
790            AsyncResult.forMessage(onComplete, null,
791                    new CommandException(CommandException.Error.GENERIC_FAILURE));
792            onComplete.sendToTarget();
793        }
794    }
795
796    /* package */
797    void sendErrorResponse(Message onComplete, Throwable e) {
798        Rlog.d(LOG_TAG, "sendErrorResponse");
799        if (onComplete != null) {
800            AsyncResult.forMessage(onComplete, null, getCommandException(e));
801            onComplete.sendToTarget();
802        }
803    }
804
805    /* package */
806    void sendErrorResponse(Message onComplete, ImsReasonInfo reasonInfo) {
807        Rlog.d(LOG_TAG, "sendErrorResponse reasonCode=" + reasonInfo.getCode());
808        if (onComplete != null) {
809            AsyncResult.forMessage(onComplete, null, getCommandException(reasonInfo.getCode()));
810            onComplete.sendToTarget();
811        }
812    }
813
814    /* package */
815    CommandException getCommandException(int code) {
816        Rlog.d(LOG_TAG, "getCommandException code=" + code);
817        CommandException.Error error = CommandException.Error.GENERIC_FAILURE;
818
819        switch(code) {
820            case ImsReasonInfo.CODE_UT_NOT_SUPPORTED:
821                error = CommandException.Error.REQUEST_NOT_SUPPORTED;
822                break;
823            case ImsReasonInfo.CODE_UT_CB_PASSWORD_MISMATCH:
824                error = CommandException.Error.PASSWORD_INCORRECT;
825                break;
826            default:
827                break;
828        }
829
830        return new CommandException(error);
831    }
832
833    /* package */
834    CommandException getCommandException(Throwable e) {
835        CommandException ex = null;
836
837        if (e instanceof ImsException) {
838            ex = getCommandException(((ImsException)e).getCode());
839        } else {
840            Rlog.d(LOG_TAG, "getCommandException generic failure");
841            ex = new CommandException(CommandException.Error.GENERIC_FAILURE);
842        }
843        return ex;
844    }
845
846    private void
847    onNetworkInitiatedUssd(ImsPhoneMmiCode mmi) {
848        Rlog.d(LOG_TAG, "onNetworkInitiatedUssd");
849        mMmiCompleteRegistrants.notifyRegistrants(
850            new AsyncResult(null, mmi, null));
851    }
852
853    /* package */
854    void onIncomingUSSD (int ussdMode, String ussdMessage) {
855        if (DBG) Rlog.d(LOG_TAG, "onIncomingUSSD ussdMode=" + ussdMode);
856
857        boolean isUssdError;
858        boolean isUssdRequest;
859
860        isUssdRequest
861            = (ussdMode == CommandsInterface.USSD_MODE_REQUEST);
862
863        isUssdError
864            = (ussdMode != CommandsInterface.USSD_MODE_NOTIFY
865                && ussdMode != CommandsInterface.USSD_MODE_REQUEST);
866
867        ImsPhoneMmiCode found = null;
868        for (int i = 0, s = mPendingMMIs.size() ; i < s; i++) {
869            if(mPendingMMIs.get(i).isPendingUSSD()) {
870                found = mPendingMMIs.get(i);
871                break;
872            }
873        }
874
875        if (found != null) {
876            // Complete pending USSD
877            if (isUssdError) {
878                found.onUssdFinishedError();
879            } else {
880                found.onUssdFinished(ussdMessage, isUssdRequest);
881            }
882        } else { // pending USSD not found
883            // The network may initiate its own USSD request
884
885            // ignore everything that isnt a Notify or a Request
886            // also, discard if there is no message to present
887            if (!isUssdError && ussdMessage != null) {
888                ImsPhoneMmiCode mmi;
889                mmi = ImsPhoneMmiCode.newNetworkInitiatedUssd(ussdMessage,
890                        isUssdRequest,
891                        ImsPhone.this);
892                onNetworkInitiatedUssd(mmi);
893            }
894        }
895    }
896
897    /**
898     * Removes the given MMI from the pending list and notifies
899     * registrants that it is complete.
900     * @param mmi MMI that is done
901     */
902    /*package*/ void
903    onMMIDone(ImsPhoneMmiCode mmi) {
904        /* Only notify complete if it's on the pending list.
905         * Otherwise, it's already been handled (eg, previously canceled).
906         * The exception is cancellation of an incoming USSD-REQUEST, which is
907         * not on the list.
908         */
909        if (mPendingMMIs.remove(mmi) || mmi.isUssdRequest()) {
910            mMmiCompleteRegistrants.notifyRegistrants(
911                    new AsyncResult(null, mmi, null));
912        }
913    }
914
915    public ImsPhoneConnection getHandoverConnection() {
916        // handover for single foreground call
917        ImsPhoneConnection conn = getForegroundCall().getHandoverConnection();
918
919        // handover for single background call
920        if (conn == null) {
921            conn = getBackgroundCall().getHandoverConnection();
922        }
923
924        // handover for single ringing call
925        if (conn == null) {
926            conn = getRingingCall().getHandoverConnection();
927        }
928
929        return conn;
930    }
931
932    public void notifySrvccState(Call.SrvccState state) {
933        mCT.notifySrvccState(state);
934    }
935
936    /* package */ void
937    initiateSilentRedial() {
938        String result = mLastDialString;
939        AsyncResult ar = new AsyncResult(null, result, null);
940        if (ar != null) {
941            mSilentRedialRegistrants.notifyRegistrants(ar);
942        }
943    }
944
945    public void registerForSilentRedial(Handler h, int what, Object obj) {
946        mSilentRedialRegistrants.addUnique(h, what, obj);
947    }
948
949    public void unregisterForSilentRedial(Handler h) {
950        mSilentRedialRegistrants.remove(h);
951    }
952
953    @Override
954    public long getSubId() {
955        return mDefaultPhone.getSubId();
956    }
957
958    @Override
959    public int getPhoneId() {
960        return mDefaultPhone.getPhoneId();
961    }
962
963    private IccRecords getIccRecords() {
964        return mDefaultPhone.mIccRecords.get();
965    }
966
967    private CallForwardInfo getCallForwardInfo(ImsCallForwardInfo info) {
968        CallForwardInfo cfInfo = new CallForwardInfo();
969        cfInfo.status = info.mStatus;
970        cfInfo.reason = getCFReasonFromCondition(info.mCondition);
971        cfInfo.serviceClass = SERVICE_CLASS_VOICE;
972        cfInfo.toa = info.mToA;
973        cfInfo.number = info.mNumber;
974        cfInfo.timeSeconds = info.mTimeSeconds;
975        return cfInfo;
976    }
977
978    private CallForwardInfo[] handleCfQueryResult(ImsCallForwardInfo[] infos) {
979        CallForwardInfo[] cfInfos = null;
980
981        if (infos != null && infos.length != 0) {
982            cfInfos = new CallForwardInfo[infos.length];
983        }
984
985        IccRecords r = getIccRecords();
986        if (infos == null || infos.length == 0) {
987            if (r != null) {
988                // Assume the default is not active
989                // Set unconditional CFF in SIM to false
990                r.setVoiceCallForwardingFlag(1, false, null);
991            }
992        } else {
993            for (int i = 0, s = infos.length; i < s; i++) {
994                if (infos[i].mCondition == ImsUtInterface.CDIV_CF_UNCONDITIONAL) {
995                    if (r != null) {
996                        r.setVoiceCallForwardingFlag(1, (infos[i].mStatus == 1),
997                            infos[i].mNumber);
998                    }
999                }
1000                cfInfos[i] = getCallForwardInfo(infos[i]);
1001            }
1002        }
1003
1004        return cfInfos;
1005    }
1006
1007    private int[] handleCbQueryResult(ImsSsInfo[] infos) {
1008        int[] cbInfos = new int[1];
1009        cbInfos[0] = SERVICE_CLASS_NONE;
1010
1011        if (infos[0].mStatus == 1) {
1012            cbInfos[0] = SERVICE_CLASS_VOICE;
1013        }
1014
1015        return cbInfos;
1016    }
1017
1018    private int[] handleCwQueryResult(ImsSsInfo[] infos) {
1019        int[] cwInfos = new int[2];
1020        cwInfos[0] = 0;
1021
1022        if (infos[0].mStatus == 1) {
1023            cwInfos[0] = 1;
1024            cwInfos[1] = SERVICE_CLASS_VOICE;
1025        }
1026
1027        return cwInfos;
1028    }
1029
1030    private void
1031    sendResponse(Message onComplete, Object result, Throwable e) {
1032        if (onComplete != null) {
1033            CommandException ex = null;
1034            if (e != null) {
1035                ex = getCommandException(e);
1036            }
1037            AsyncResult.forMessage(onComplete, result, ex);
1038            onComplete.sendToTarget();
1039        }
1040    }
1041
1042    @Override
1043    public void handleMessage (Message msg) {
1044        AsyncResult ar = (AsyncResult) msg.obj;
1045        Message onComplete;
1046
1047        if (DBG) Rlog.d(LOG_TAG, "handleMessage what=" + msg.what);
1048        switch (msg.what) {
1049            case EVENT_SET_CALL_FORWARD_DONE:
1050                IccRecords r = getIccRecords();
1051                Cf cf = (Cf) ar.userObj;
1052                if (cf.mIsCfu && ar.exception == null && r != null) {
1053                    r.setVoiceCallForwardingFlag(1, msg.arg1 == 1, cf.mSetCfNumber);
1054                }
1055                sendResponse(cf.mOnComplete, null, ar.exception);
1056                break;
1057
1058            case EVENT_GET_CALL_FORWARD_DONE:
1059                CallForwardInfo[] cfInfos = null;
1060                if (ar.exception == null) {
1061                    cfInfos = handleCfQueryResult((ImsCallForwardInfo[])ar.result);
1062                }
1063                sendResponse((Message) ar.userObj, cfInfos, ar.exception);
1064                break;
1065
1066             case EVENT_GET_CALL_BARRING_DONE:
1067             case EVENT_GET_CALL_WAITING_DONE:
1068                int[] ssInfos = null;
1069                if (ar.exception == null) {
1070                    if (msg.what == EVENT_GET_CALL_BARRING_DONE) {
1071                        ssInfos = handleCbQueryResult((ImsSsInfo[])ar.result);
1072                    } else if (msg.what == EVENT_GET_CALL_WAITING_DONE) {
1073                        ssInfos = handleCwQueryResult((ImsSsInfo[])ar.result);
1074                    }
1075                }
1076                sendResponse((Message) ar.userObj, ssInfos, ar.exception);
1077                break;
1078
1079             case EVENT_SET_CALL_BARRING_DONE:
1080             case EVENT_SET_CALL_WAITING_DONE:
1081                sendResponse((Message) ar.userObj, null, ar.exception);
1082                break;
1083
1084             default:
1085                 super.handleMessage(msg);
1086                 break;
1087        }
1088    }
1089
1090    /**
1091     * Listen to the IMS ECBM state change
1092     */
1093    ImsEcbmStateListener mImsEcbmStateListener =
1094            new ImsEcbmStateListener() {
1095                @Override
1096                public void onECBMEntered() {
1097                    if (DBG) Rlog.d(LOG_TAG, "onECBMEntered");
1098                    handleEnterEmergencyCallbackMode();
1099                }
1100
1101                @Override
1102                public void onECBMExited() {
1103                    if (DBG) Rlog.d(LOG_TAG, "onECBMExited");
1104                    handleExitEmergencyCallbackMode();
1105                }
1106            };
1107
1108    public boolean isInEmergencyCall() {
1109        return mCT.isInEmergencyCall();
1110    }
1111
1112    public boolean isInEcm() {
1113        return mIsPhoneInEcmState;
1114    }
1115
1116    void sendEmergencyCallbackModeChange() {
1117        // Send an Intent
1118        Intent intent = new Intent(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
1119        intent.putExtra(PhoneConstants.PHONE_IN_ECM_STATE, mIsPhoneInEcmState);
1120        SubscriptionManager.putPhoneIdAndSubIdExtra(intent, getPhoneId());
1121        ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL);
1122        if (DBG) Rlog.d(LOG_TAG, "sendEmergencyCallbackModeChange");
1123    }
1124
1125    @Override
1126    public void exitEmergencyCallbackMode() {
1127        if (mWakeLock.isHeld()) {
1128            mWakeLock.release();
1129        }
1130        if (DBG) Rlog.d(LOG_TAG, "exitEmergencyCallbackMode()");
1131
1132        // Send a message which will invoke handleExitEmergencyCallbackMode
1133        ImsEcbm ecbm;
1134        try {
1135            ecbm = mCT.getEcbmInterface();
1136            ecbm.exitEmergencyCallbackMode();
1137        } catch (ImsException e) {
1138            e.printStackTrace();
1139        }
1140    }
1141
1142    private void handleEnterEmergencyCallbackMode() {
1143        if (DBG) {
1144            Rlog.d(LOG_TAG, "handleEnterEmergencyCallbackMode,mIsPhoneInEcmState= "
1145                    + mIsPhoneInEcmState);
1146        }
1147        // if phone is not in Ecm mode, and it's changed to Ecm mode
1148        if (mIsPhoneInEcmState == false) {
1149            mIsPhoneInEcmState = true;
1150            // notify change
1151            sendEmergencyCallbackModeChange();
1152            setSystemProperty(TelephonyProperties.PROPERTY_INECM_MODE, "true");
1153
1154            // Post this runnable so we will automatically exit
1155            // if no one invokes exitEmergencyCallbackMode() directly.
1156            long delayInMillis = SystemProperties.getLong(
1157                    TelephonyProperties.PROPERTY_ECM_EXIT_TIMER, DEFAULT_ECM_EXIT_TIMER_VALUE);
1158            postDelayed(mExitEcmRunnable, delayInMillis);
1159            // We don't want to go to sleep while in Ecm
1160            mWakeLock.acquire();
1161        }
1162    }
1163
1164    private void handleExitEmergencyCallbackMode() {
1165        if (DBG) {
1166            Rlog.d(LOG_TAG, "handleExitEmergencyCallbackMode: mIsPhoneInEcmState = "
1167                    + mIsPhoneInEcmState);
1168        }
1169        // Remove pending exit Ecm runnable, if any
1170        removeCallbacks(mExitEcmRunnable);
1171
1172        if (mEcmExitRespRegistrant != null) {
1173            mEcmExitRespRegistrant.notifyResult(Boolean.TRUE);
1174        }
1175            if (mIsPhoneInEcmState) {
1176                mIsPhoneInEcmState = false;
1177                setSystemProperty(TelephonyProperties.PROPERTY_INECM_MODE, "false");
1178            }
1179            // send an Intent
1180            sendEmergencyCallbackModeChange();
1181    }
1182
1183    /**
1184     * Handle to cancel or restart Ecm timer in emergency call back mode if action is
1185     * CANCEL_ECM_TIMER, cancel Ecm timer and notify apps the timer is canceled; otherwise, restart
1186     * Ecm timer and notify apps the timer is restarted.
1187     */
1188    void handleTimerInEmergencyCallbackMode(int action) {
1189        switch (action) {
1190            case CANCEL_ECM_TIMER:
1191                removeCallbacks(mExitEcmRunnable);
1192                if (mDefaultPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM) {
1193                    ((GSMPhone) mDefaultPhone).notifyEcbmTimerReset(Boolean.TRUE);
1194                } else { // Should be CDMA - also go here by default
1195                    ((CDMAPhone) mDefaultPhone).notifyEcbmTimerReset(Boolean.TRUE);
1196                }
1197                break;
1198            case RESTART_ECM_TIMER:
1199                long delayInMillis = SystemProperties.getLong(
1200                        TelephonyProperties.PROPERTY_ECM_EXIT_TIMER, DEFAULT_ECM_EXIT_TIMER_VALUE);
1201                postDelayed(mExitEcmRunnable, delayInMillis);
1202                if (mDefaultPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM) {
1203                    ((GSMPhone) mDefaultPhone).notifyEcbmTimerReset(Boolean.FALSE);
1204                } else { // Should be CDMA - also go here by default
1205                    ((CDMAPhone) mDefaultPhone).notifyEcbmTimerReset(Boolean.FALSE);
1206                }
1207                break;
1208            default:
1209                Rlog.e(LOG_TAG, "handleTimerInEmergencyCallbackMode, unsupported action " + action);
1210        }
1211    }
1212
1213    public void setOnEcbModeExitResponse(Handler h, int what, Object obj) {
1214        mEcmExitRespRegistrant = new Registrant(h, what, obj);
1215    }
1216
1217    public void unsetOnEcbModeExitResponse(Handler h) {
1218        mEcmExitRespRegistrant.clear();
1219    }
1220
1221    public boolean isVolteEnabled() {
1222        return mCT.isVolteEnabled();
1223    }
1224
1225    public boolean isVtEnabled() {
1226        return mCT.isVtEnabled();
1227    }
1228}
1229