1c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/*
2c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Copyright (C) 2006 The Android Open Source Project
3c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
4c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Licensed under the Apache License, Version 2.0 (the "License");
5c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * you may not use this file except in compliance with the License.
6c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * You may obtain a copy of the License at
7c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
8c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *      http://www.apache.org/licenses/LICENSE-2.0
9c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
10c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Unless required by applicable law or agreed to in writing, software
11c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * distributed under the License is distributed on an "AS IS" BASIS,
12c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * See the License for the specific language governing permissions and
14c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * limitations under the License.
15c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */
16c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
17c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savillepackage com.android.internal.telephony.gsm;
18c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
19c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.content.Context;
2021fe62acc2d11ace0410b2b6d83263a96081c092duho.roimport android.content.res.Resources;
21c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.*;
22d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccRecords;
23d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.UiccCardApplication;
24d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState;
25c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
26c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.os.*;
27c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.telephony.PhoneNumberUtils;
28c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.text.SpannableStringBuilder;
298697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlssonimport android.text.BidiFormatter;
308697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlssonimport android.text.TextDirectionHeuristics;
31c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.text.TextUtils;
32ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Savilleimport android.telephony.Rlog;
33c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
34c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport static com.android.internal.telephony.CommandsInterface.*;
35c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
36c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport java.util.regex.Pattern;
37c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport java.util.regex.Matcher;
38c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
39c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/**
40c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * The motto for this file is:
41c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
42c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * "NOTE:    By using the # as a separator, most cases are expected to be unambiguous."
43c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *   -- TS 22.030 6.5.2
44c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
45c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * {@hide}
46c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
47c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */
48c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savillepublic final class GsmMmiCode extends Handler implements MmiCode {
49cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    static final String LOG_TAG = "GsmMmiCode";
50c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
51c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Constants
52c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
53c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Max Size of the Short Code (aka Short String from TS 22.030 6.5.2)
54c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MAX_LENGTH_SHORT_CODE = 2;
55c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
56c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // TS 22.030 6.5.2 Every Short String USSD command will end with #-key
57c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // (known as #-String)
58c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final char END_OF_USSD_COMMAND = '#';
59c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
60c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // From TS 22.030 6.5.2
61c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String ACTION_ACTIVATE = "*";
62c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String ACTION_DEACTIVATE = "#";
63c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String ACTION_INTERROGATE = "*#";
64c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String ACTION_REGISTER = "**";
65c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String ACTION_ERASURE = "##";
66c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
67c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Supp Service codes from TS 22.030 Annex B
68c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
69c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //Called line presentation
70c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CLIP    = "30";
71c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CLIR    = "31";
72c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
73c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Call Forwarding
74c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CFU     = "21";
75c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CFB     = "67";
76c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CFNRy   = "61";
77c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CFNR    = "62";
78c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
79c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CF_All = "002";
80c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CF_All_Conditional = "004";
81c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
82c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Call Waiting
83c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_WAIT     = "43";
84c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
85c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Call Barring
86c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BAOC         = "33";
87c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BAOIC        = "331";
88c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BAOICxH      = "332";
89c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BAIC         = "35";
90c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BAICr        = "351";
91c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
92c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BA_ALL       = "330";
93c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BA_MO        = "333";
94c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BA_MT        = "353";
95c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
96c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Supp Service Password registration
97c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_PWD          = "03";
98c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
99c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // PIN/PIN2/PUK/PUK2
100c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_PIN          = "04";
101c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_PIN2         = "042";
102c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_PUK          = "05";
103c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_PUK2         = "052";
104c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
105c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Event Constants
106c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
107c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_SET_COMPLETE         = 1;
108c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_GET_CLIR_COMPLETE    = 2;
109c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_QUERY_CF_COMPLETE    = 3;
110c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_USSD_COMPLETE        = 4;
111c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_QUERY_COMPLETE       = 5;
112c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_SET_CFF_COMPLETE     = 6;
113c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_USSD_CANCEL_COMPLETE = 7;
114c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
115c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Instance Variables
116c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1173a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    GsmCdmaPhone mPhone;
11822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    Context mContext;
119e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    UiccCardApplication mUiccApplication;
120e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    IccRecords mIccRecords;
121c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
12222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    String mAction;              // One of ACTION_*
12322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    String mSc;                  // Service Code
12422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    String mSia, mSib, mSic;       // Service Info a,b,c
12522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    String mPoundString;         // Entire MMI string up to and including #
1263a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    public String mDialingNumber;
12722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    String mPwd;                 // For password registration
128c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
129c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Set to true in processCode, not at newFromDialString time */
13022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    private boolean mIsPendingUSSD;
131c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
13222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    private boolean mIsUssdRequest;
133c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
13422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    private boolean mIsCallFwdReg;
13522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    State mState = State.PENDING;
13622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    CharSequence mMessage;
13709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja    private boolean mIsSsInfo = false;
13816b58d13bde6487c6993831ca63385915be8956epkanwar    private ResultReceiver mCallbackReceiver;
13909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja
140c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
141c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Class Variables
142c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
143c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
144c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // See TS 22.030 6.5.2 "Structure of the MMI"
145c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
146c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static Pattern sPatternSuppService = Pattern.compile(
1479225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang        "((\\*|#|\\*#|\\*\\*|##)(\\d{2,3})(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*))?)?)?)?#)(.*)");
148c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/*       1  2                    3          4  5       6   7         8    9     10  11             12
149c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
150c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         1 = Full string up to and including #
151c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         2 = action (activation/interrogation/registration/erasure)
152c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         3 = service code
153c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         5 = SIA
154c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         7 = SIB
155c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         9 = SIC
1569225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang         10 = dialing number
157c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville*/
158c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
159c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_POUND_STRING = 1;
160c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
161c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_ACTION = 2;
162c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        //(activation/interrogation/registration/erasure)
163c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
164c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_SERVICE_CODE = 3;
165c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_SIA = 5;
166c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_SIB = 7;
167c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_SIC = 9;
168c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_PWD_CONFIRM = 11;
169c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_DIALING_NUMBER = 12;
170c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static private String[] sTwoDigitNumberPattern;
171c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
172c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Public Class methods
173c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
174c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
175c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Some dial strings in GSM are defined to do non-call setup
176c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * things, such as modify or query supplementary service settings (eg, call
177c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * forwarding). These are generally referred to as "MMI codes".
178c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * We look to see if the dial string contains a valid MMI code (potentially
179c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * with a dial string at the end as well) and return info here.
180c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
181c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * If the dial string contains no MMI code, we return an instance with
182c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * only "dialingNumber" set
183c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
184c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Please see flow chart in TS 22.030 6.5.3.2
185c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
18616b58d13bde6487c6993831ca63385915be8956epkanwar    public static GsmMmiCode newFromDialString(String dialString, GsmCdmaPhone phone,
18716b58d13bde6487c6993831ca63385915be8956epkanwar            UiccCardApplication app) {
18816b58d13bde6487c6993831ca63385915be8956epkanwar        return newFromDialString(dialString, phone, app, null);
18916b58d13bde6487c6993831ca63385915be8956epkanwar    }
190c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
19116b58d13bde6487c6993831ca63385915be8956epkanwar    public static GsmMmiCode newFromDialString(String dialString, GsmCdmaPhone phone,
19216b58d13bde6487c6993831ca63385915be8956epkanwar            UiccCardApplication app, ResultReceiver wrappedCallback) {
193c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        Matcher m;
194c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        GsmMmiCode ret = null;
195c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
196c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        m = sPatternSuppService.matcher(dialString);
197c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
198c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Is this formatted like a standard supplementary service code?
199c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (m.matches()) {
200e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            ret = new GsmMmiCode(phone, app);
20122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mPoundString = makeEmptyNull(m.group(MATCH_GROUP_POUND_STRING));
20222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mAction = makeEmptyNull(m.group(MATCH_GROUP_ACTION));
20322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mSc = makeEmptyNull(m.group(MATCH_GROUP_SERVICE_CODE));
20422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mSia = makeEmptyNull(m.group(MATCH_GROUP_SIA));
20522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mSib = makeEmptyNull(m.group(MATCH_GROUP_SIB));
20622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mSic = makeEmptyNull(m.group(MATCH_GROUP_SIC));
20722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mPwd = makeEmptyNull(m.group(MATCH_GROUP_PWD_CONFIRM));
20822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mDialingNumber = makeEmptyNull(m.group(MATCH_GROUP_DIALING_NUMBER));
20916b58d13bde6487c6993831ca63385915be8956epkanwar            ret.mCallbackReceiver = wrappedCallback;
2109225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            // According to TS 22.030 6.5.2 "Structure of the MMI",
2119225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            // the dialing number should not ending with #.
2129225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            // The dialing number ending # is treated as unique USSD,
2139225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            // eg, *400#16 digit number# to recharge the prepaid card
2149225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            // in India operator(Mumbai MTNL)
21522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            if(ret.mDialingNumber != null &&
21622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    ret.mDialingNumber.endsWith("#") &&
2179225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang                    dialString.endsWith("#")){
2189225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang                ret = new GsmMmiCode(phone, app);
21922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                ret.mPoundString = dialString;
2209225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            }
221c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (dialString.endsWith("#")) {
222c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // TS 22.030 sec 6.5.3.2
223c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // "Entry of any characters defined in the 3GPP TS 23.038 [8] Default Alphabet
224c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // (up to the maximum defined in 3GPP TS 24.080 [10]), followed by #SEND".
225c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
226e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            ret = new GsmMmiCode(phone, app);
22722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mPoundString = dialString;
228c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isTwoDigitShortCode(phone.getContext(), dialString)) {
229c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            //Is a country-specific exception to short codes as defined in TS 22.030, 6.5.3.2
230c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ret = null;
231c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isShortCode(dialString, phone)) {
232c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // this may be a short code, as defined in TS 22.030, 6.5.3.2
233e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            ret = new GsmMmiCode(phone, app);
23422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mDialingNumber = dialString;
235c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
236c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
237c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return ret;
238c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
239c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
2403a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    public static GsmMmiCode
2413a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    newNetworkInitiatedUssd(String ussdMessage,
2423a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan                            boolean isUssdRequest, GsmCdmaPhone phone, UiccCardApplication app) {
243c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        GsmMmiCode ret;
244c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
245e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        ret = new GsmMmiCode(phone, app);
246c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
24722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        ret.mMessage = ussdMessage;
24822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        ret.mIsUssdRequest = isUssdRequest;
249c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
250c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // If it's a request, set to PENDING so that it's cancelable.
251c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (isUssdRequest) {
25222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mIsPendingUSSD = true;
25322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mState = State.PENDING;
254c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
25522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mState = State.COMPLETE;
256c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
257c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
258c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return ret;
259c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
260c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
2613a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    public static GsmMmiCode newFromUssdUserInput(String ussdMessge,
2623a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan                                                  GsmCdmaPhone phone,
2633a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan                                                  UiccCardApplication app) {
264e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        GsmMmiCode ret = new GsmMmiCode(phone, app);
265c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
26622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        ret.mMessage = ussdMessge;
26722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        ret.mState = State.PENDING;
26822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        ret.mIsPendingUSSD = true;
269c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
270c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return ret;
271c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
272c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
27309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja    /** Process SS Data */
2743a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    public void
27509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja    processSsData(AsyncResult data) {
27609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        Rlog.d(LOG_TAG, "In processSsData");
27709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja
27809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        mIsSsInfo = true;
27909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        try {
28009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            SsData ssData = (SsData)data.result;
28109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            parseSsData(ssData);
28209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        } catch (ClassCastException ex) {
28309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            Rlog.e(LOG_TAG, "Class Cast Exception in parsing SS Data : " + ex);
28409b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        } catch (NullPointerException ex) {
28509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            Rlog.e(LOG_TAG, "Null Pointer Exception in parsing SS Data : " + ex);
28609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        }
28709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja    }
28809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja
28909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja    void parseSsData(SsData ssData) {
29009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        CommandException ex;
29109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja
29209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        ex = CommandException.fromRilErrno(ssData.result);
29309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        mSc = getScStringFromScType(ssData.serviceType);
29409b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        mAction = getActionStringFromReqType(ssData.requestType);
29509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        Rlog.d(LOG_TAG, "parseSsData msc = " + mSc + ", action = " + mAction + ", ex = " + ex);
29609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja
29709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        switch (ssData.requestType) {
29809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_ACTIVATION:
29909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_DEACTIVATION:
30009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_REGISTRATION:
30109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_ERASURE:
30209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                if ((ssData.result == RILConstants.SUCCESS) &&
30309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                      ssData.serviceType.isTypeUnConditional()) {
30409b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                    /*
30509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                     * When ServiceType is SS_CFU/SS_CF_ALL and RequestType is activate/register
30609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                     * and ServiceClass is Voice/None, set IccRecords.setVoiceCallForwardingFlag.
30709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                     * Only CF status can be set here since number is not available.
30809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                     */
30909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                    boolean cffEnabled = ((ssData.requestType == SsData.RequestType.SS_ACTIVATION ||
31009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                            ssData.requestType == SsData.RequestType.SS_REGISTRATION) &&
31109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                            isServiceClassVoiceorNone(ssData.serviceClass));
31209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja
31309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                    Rlog.d(LOG_TAG, "setVoiceCallForwardingFlag cffEnabled: " + cffEnabled);
314a1fd99a6910a97470cab01fbc28bfea82e832dabNarayan Kamath                    if (mIccRecords != null) {
315eadee84166d397b6425cfd56f89fa1569f6a93f5Amit Mahajan                        mPhone.setVoiceCallForwardingFlag(1, cffEnabled, null);
31609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                        Rlog.d(LOG_TAG, "setVoiceCallForwardingFlag done from SS Info.");
31709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                    } else {
31809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                        Rlog.e(LOG_TAG, "setVoiceCallForwardingFlag aborted. sim records is null.");
31909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                    }
32009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                }
32109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                onSetComplete(null, new AsyncResult(null, ssData.cfInfo, ex));
32209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                break;
32309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_INTERROGATION:
32409b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                if (ssData.serviceType.isTypeClir()) {
32509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                    Rlog.d(LOG_TAG, "CLIR INTERROGATION");
32609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                    onGetClirComplete(new AsyncResult(null, ssData.ssInfo, ex));
32709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                } else if (ssData.serviceType.isTypeCF()) {
32809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                    Rlog.d(LOG_TAG, "CALL FORWARD INTERROGATION");
32909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                    onQueryCfComplete(new AsyncResult(null, ssData.cfInfo, ex));
33009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                } else {
33109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                    onQueryComplete(new AsyncResult(null, ssData.ssInfo, ex));
33209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                }
33309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                break;
33409b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            default:
33509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                Rlog.e(LOG_TAG, "Invaid requestType in SSData : " + ssData.requestType);
33609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                break;
33709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        }
33809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja    }
33909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja
34009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja    private String getScStringFromScType(SsData.ServiceType sType) {
34109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        switch (sType) {
34209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_CFU:
34309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_CFU;
34409b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_CF_BUSY:
34509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_CFB;
34609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_CF_NO_REPLY:
34709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_CFNRy;
34809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_CF_NOT_REACHABLE:
34909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_CFNR;
35009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_CF_ALL:
35109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_CF_All;
35209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_CF_ALL_CONDITIONAL:
35309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_CF_All_Conditional;
35409b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_CLIP:
35509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_CLIP;
35609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_CLIR:
35709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_CLIR;
35809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_WAIT:
35909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_WAIT;
36009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_BAOC:
36109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_BAOC;
36209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_BAOIC:
36309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_BAOIC;
36409b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_BAOIC_EXC_HOME:
36509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_BAOICxH;
36609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_BAIC:
36709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_BAIC;
36809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_BAIC_ROAMING:
36909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_BAICr;
37009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_ALL_BARRING:
37109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_BA_ALL;
37209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_OUTGOING_BARRING:
37309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_BA_MO;
37409b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_INCOMING_BARRING:
37509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_BA_MT;
37609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        }
37709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja
37809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        return "";
37909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja    }
38009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja
38109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja    private String getActionStringFromReqType(SsData.RequestType rType) {
38209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        switch (rType) {
38309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_ACTIVATION:
38409b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return ACTION_ACTIVATE;
38509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_DEACTIVATION:
38609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return ACTION_DEACTIVATE;
38709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_INTERROGATION:
38809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return ACTION_INTERROGATE;
38909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_REGISTRATION:
39009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return ACTION_REGISTER;
39109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_ERASURE:
39209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return ACTION_ERASURE;
39309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        }
39409b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja
39509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        return "";
39609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja    }
39709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja
39809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja    private boolean isServiceClassVoiceorNone(int serviceClass) {
39909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        return (((serviceClass & CommandsInterface.SERVICE_CLASS_VOICE) != 0) ||
40009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                (serviceClass == CommandsInterface.SERVICE_CLASS_NONE));
40109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja    }
40209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja
403c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Private Class methods
404c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
405c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** make empty strings be null.
406c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  Regexp returns empty strings for empty groups
407c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
408c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static String
409c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    makeEmptyNull (String s) {
410c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (s != null && s.length() == 0) return null;
411c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
412c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return s;
413c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
414c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
415c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** returns true of the string is empty or null */
416c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static boolean
417c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isEmptyOrNull(CharSequence s) {
418c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return s == null || (s.length() == 0);
419c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
420c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
421c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
422c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static int
423c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    scToCallForwardReason(String sc) {
424c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sc == null) {
425c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            throw new RuntimeException ("invalid call forward sc");
426c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
427c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
428c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sc.equals(SC_CF_All)) {
429c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville           return CommandsInterface.CF_REASON_ALL;
430c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_CFU)) {
431c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CF_REASON_UNCONDITIONAL;
432c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_CFB)) {
433c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CF_REASON_BUSY;
434c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_CFNR)) {
435c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CF_REASON_NOT_REACHABLE;
436c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_CFNRy)) {
437c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CF_REASON_NO_REPLY;
438c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_CF_All_Conditional)) {
439c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville           return CommandsInterface.CF_REASON_ALL_CONDITIONAL;
440c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
441c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            throw new RuntimeException ("invalid call forward sc");
442c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
443c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
444c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
445c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static int
446c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    siToServiceClass(String si) {
447c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (si == null || si.length() == 0) {
448c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return  SERVICE_CLASS_NONE;
449c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
450c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // NumberFormatException should cause MMI fail
451c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            int serviceCode = Integer.parseInt(si, 10);
452c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
453c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            switch (serviceCode) {
454c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 10: return SERVICE_CLASS_SMS + SERVICE_CLASS_FAX  + SERVICE_CLASS_VOICE;
455c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 11: return SERVICE_CLASS_VOICE;
456c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 12: return SERVICE_CLASS_SMS + SERVICE_CLASS_FAX;
457c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 13: return SERVICE_CLASS_FAX;
458c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
459c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 16: return SERVICE_CLASS_SMS;
460c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
461c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 19: return SERVICE_CLASS_FAX + SERVICE_CLASS_VOICE;
462c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/*
463c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    Note for code 20:
464c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     From TS 22.030 Annex C:
465c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                "All GPRS bearer services" are not included in "All tele and bearer services"
466c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    and "All bearer services"."
467c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville....so SERVICE_CLASS_DATA, which (according to 27.007) includes GPRS
468c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville*/
469c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 20: return SERVICE_CLASS_DATA_ASYNC + SERVICE_CLASS_DATA_SYNC;
470c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
471c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 21: return SERVICE_CLASS_PAD + SERVICE_CLASS_DATA_ASYNC;
472c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 22: return SERVICE_CLASS_PACKET + SERVICE_CLASS_DATA_SYNC;
473c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 24: return SERVICE_CLASS_DATA_SYNC;
474c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 25: return SERVICE_CLASS_DATA_ASYNC;
475c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 26: return SERVICE_CLASS_DATA_SYNC + SERVICE_CLASS_VOICE;
476c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 99: return SERVICE_CLASS_PACKET;
477c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
478c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                default:
479c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException("unsupported MMI service code " + si);
480c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
481c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
482c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
483c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
484c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static int
485c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    siToTime (String si) {
486c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (si == null || si.length() == 0) {
487c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return 0;
488c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
489c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // NumberFormatException should cause MMI fail
490c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return Integer.parseInt(si, 10);
491c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
492c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
493c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
494c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static boolean
495c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isServiceCodeCallForwarding(String sc) {
496c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return sc != null &&
497c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                (sc.equals(SC_CFU)
498c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                || sc.equals(SC_CFB) || sc.equals(SC_CFNRy)
499c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                || sc.equals(SC_CFNR) || sc.equals(SC_CF_All)
500c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                || sc.equals(SC_CF_All_Conditional));
501c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
502c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
503c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static boolean
504c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isServiceCodeCallBarring(String sc) {
50521fe62acc2d11ace0410b2b6d83263a96081c092duho.ro        Resources resource = Resources.getSystem();
50621fe62acc2d11ace0410b2b6d83263a96081c092duho.ro        if (sc != null) {
50721fe62acc2d11ace0410b2b6d83263a96081c092duho.ro            String[] barringMMI = resource.getStringArray(
50821fe62acc2d11ace0410b2b6d83263a96081c092duho.ro                com.android.internal.R.array.config_callBarringMMI);
50921fe62acc2d11ace0410b2b6d83263a96081c092duho.ro            if (barringMMI != null) {
51021fe62acc2d11ace0410b2b6d83263a96081c092duho.ro                for (String match : barringMMI) {
51121fe62acc2d11ace0410b2b6d83263a96081c092duho.ro                    if (sc.equals(match)) return true;
51221fe62acc2d11ace0410b2b6d83263a96081c092duho.ro                }
51321fe62acc2d11ace0410b2b6d83263a96081c092duho.ro            }
51421fe62acc2d11ace0410b2b6d83263a96081c092duho.ro        }
51521fe62acc2d11ace0410b2b6d83263a96081c092duho.ro        return false;
516c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
517c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
518c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static String
519c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    scToBarringFacility(String sc) {
520c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sc == null) {
521c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            throw new RuntimeException ("invalid call barring sc");
522c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
523c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
524c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sc.equals(SC_BAOC)) {
525c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BAOC;
526c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BAOIC)) {
527c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BAOIC;
528c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BAOICxH)) {
529c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BAOICxH;
530c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BAIC)) {
531c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BAIC;
532c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BAICr)) {
533c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BAICr;
534c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BA_ALL)) {
535c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BA_ALL;
536c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BA_MO)) {
537c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BA_MO;
538c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BA_MT)) {
539c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BA_MT;
540c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
541c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            throw new RuntimeException ("invalid call barring sc");
542c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
543c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
544c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
545c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Constructor
546c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
5473a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    public GsmMmiCode(GsmCdmaPhone phone, UiccCardApplication app) {
548c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // The telephony unit-test cases may create GsmMmiCode's
549c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // in secondary threads
550c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        super(phone.getHandler().getLooper());
55122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mPhone = phone;
55222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mContext = phone.getContext();
553e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mUiccApplication = app;
554e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (app != null) {
555e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mIccRecords = app.getIccRecords();
556e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
557c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
558c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
559c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** MmiCode implementation
560c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
561cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
562c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public State
563c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    getState() {
56422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mState;
565c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
566c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
567cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
568c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public CharSequence
569c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    getMessage() {
57022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mMessage;
571c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
572c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
573a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public Phone
574a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    getPhone() {
575a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return ((Phone) mPhone);
576a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
577a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
578c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // inherited javadoc suffices
579cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
580c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void
581c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    cancel() {
582c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Complete or failed cannot be cancelled
58322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mState == State.COMPLETE || mState == State.FAILED) {
584c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return;
585c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
586c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
58722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mState = State.CANCELLED;
588c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
58922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mIsPendingUSSD) {
590c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            /*
591c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             * There can only be one pending USSD session, so tell the radio to
592c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             * cancel it.
593c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             */
59422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mPhone.mCi.cancelPendingUssd(obtainMessage(EVENT_USSD_CANCEL_COMPLETE, this));
595c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
596c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            /*
597c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             * Don't call phone.onMMIDone here; wait for CANCEL_COMPLETE notice
598c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             * from RIL.
599c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             */
600c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
601c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // TODO in cases other than USSD, it would be nice to cancel
602c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // the pending radio operation. This requires RIL cancellation
603c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // support, which does not presently exist.
604c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
60522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mPhone.onMMIDone (this);
606c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
607c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
608c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
609c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
610cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
611c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public boolean isCancelable() {
612c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        /* Can only cancel pending USSD sessions. */
61322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mIsPendingUSSD;
614c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
615c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
616c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Instance Methods
617c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
618c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Does this dial string contain a structured or unstructured MMI code? */
619c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean
620c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isMMI() {
62122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mPoundString != null;
622c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
623c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
624c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /* Is this a 1 or 2 digit "short code" as defined in TS 22.030 sec 6.5.3.2? */
625c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean
626c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isShortCode() {
62722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mPoundString == null
62822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    && mDialingNumber != null && mDialingNumber.length() <= 2;
629c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
630c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
631c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
63216b58d13bde6487c6993831ca63385915be8956epkanwar    @Override
63316b58d13bde6487c6993831ca63385915be8956epkanwar    public String getDialString() {
63416b58d13bde6487c6993831ca63385915be8956epkanwar        return mPoundString;
63516b58d13bde6487c6993831ca63385915be8956epkanwar    }
63616b58d13bde6487c6993831ca63385915be8956epkanwar
637c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static private boolean
638c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isTwoDigitShortCode(Context context, String dialString) {
639ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville        Rlog.d(LOG_TAG, "isTwoDigitShortCode");
640c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
6416103b5df6705c89193f452c35eaf5e9a26c188cfJing Zhao        if (dialString == null || dialString.length() > 2) return false;
642c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
643c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sTwoDigitNumberPattern == null) {
644c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            sTwoDigitNumberPattern = context.getResources().getStringArray(
645c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    com.android.internal.R.array.config_twoDigitNumberPattern);
646c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
647c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
648c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        for (String dialnumber : sTwoDigitNumberPattern) {
649ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.d(LOG_TAG, "Two Digit Number Pattern " + dialnumber);
650c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (dialString.equals(dialnumber)) {
651ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.d(LOG_TAG, "Two Digit Number Pattern -true");
652c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return true;
653c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
654c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
655ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville        Rlog.d(LOG_TAG, "Two Digit Number Pattern -false");
656c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return false;
657c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
658c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
659c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
660c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Helper function for newFromDialString. Returns true if dialString appears
661c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * to be a short code AND conditions are correct for it to be treated as
662c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * such.
663c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
6643a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    static private boolean isShortCode(String dialString, GsmCdmaPhone phone) {
665c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Refer to TS 22.030 Figure 3.5.3.2:
666c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (dialString == null) {
667c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return false;
668c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
669c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
670c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Illegal dial string characters will give a ZERO length.
671c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // At this point we do not want to crash as any application with
672c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // call privileges may send a non dial string.
673c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // It return false as when the dialString is equal to NULL.
674c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (dialString.length() == 0) {
675c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return false;
676c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
677c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
678f4f5308a309d43fcfca8d0d5fbb54bc38c82ca3fYorke Lee        if (PhoneNumberUtils.isLocalEmergencyNumber(phone.getContext(), dialString)) {
679c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return false;
680c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
681c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return isShortCodeUSSD(dialString, phone);
682c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
683c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
684c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
685c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
686c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Helper function for isShortCode. Returns true if dialString appears to be
687c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * a short code and it is a USSD structure
688c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
689c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * According to the 3PGG TS 22.030 specification Figure 3.5.3.2: A 1 or 2
690c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * digit "short code" is treated as USSD if it is entered while on a call or
691c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * does not satisfy the condition (exactly 2 digits && starts with '1'), there
692c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * are however exceptions to this rule (see below)
693c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
694c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Exception (1) to Call initiation is: If the user of the device is already in a call
695c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * and enters a Short String without any #-key at the end and the length of the Short String is
696c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * equal or less then the MAX_LENGTH_SHORT_CODE [constant that is equal to 2]
697c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
698c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * The phone shall initiate a USSD/SS commands.
699c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
7003a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    static private boolean isShortCodeUSSD(String dialString, GsmCdmaPhone phone) {
70110e574acd0992d22abce257b420d333f5a49e71dJeevaka Badrappan        if (dialString != null && dialString.length() <= MAX_LENGTH_SHORT_CODE) {
702c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (phone.isInCall()) {
70310e574acd0992d22abce257b420d333f5a49e71dJeevaka Badrappan                return true;
704c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
705c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
70610e574acd0992d22abce257b420d333f5a49e71dJeevaka Badrappan            if (dialString.length() != MAX_LENGTH_SHORT_CODE ||
70710e574acd0992d22abce257b420d333f5a49e71dJeevaka Badrappan                    dialString.charAt(0) != '1') {
70810e574acd0992d22abce257b420d333f5a49e71dJeevaka Badrappan                return true;
709c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
710c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
711c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return false;
712c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
713c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
714c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
715c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @return true if the Service Code is PIN/PIN2/PUK/PUK2-related
716c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
7173a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    public boolean isPinPukCommand() {
71822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mSc != null && (mSc.equals(SC_PIN) || mSc.equals(SC_PIN2)
71922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                              || mSc.equals(SC_PUK) || mSc.equals(SC_PUK2));
720c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     }
721c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
722c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
723c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * See TS 22.030 Annex B.
724c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * In temporary mode, to suppress CLIR for a single call, enter:
725c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *      " * 31 # [called number] SEND "
726c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  In temporary mode, to invoke CLIR for a single call enter:
727c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *       " # 31 # [called number] SEND "
728c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
7293a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    public boolean
730c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isTemporaryModeCLIR() {
73122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mSc != null && mSc.equals(SC_CLIR) && mDialingNumber != null
732c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                && (isActivate() || isDeactivate());
733c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
734c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
735c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
736c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * returns CommandsInterface.CLIR_*
737c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * See also isTemporaryModeCLIR()
738c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
7393a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    public int
740c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    getCLIRMode() {
74122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mSc != null && mSc.equals(SC_CLIR)) {
742c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (isActivate()) {
743c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return CommandsInterface.CLIR_SUPPRESSION;
744c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else if (isDeactivate()) {
745c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return CommandsInterface.CLIR_INVOCATION;
746c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
747c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
748c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
749c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return CommandsInterface.CLIR_DEFAULT;
750c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
751c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
752c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean isActivate() {
75322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mAction != null && mAction.equals(ACTION_ACTIVATE);
754c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
755c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
756c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean isDeactivate() {
75722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mAction != null && mAction.equals(ACTION_DEACTIVATE);
758c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
759c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
760c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean isInterrogate() {
76122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mAction != null && mAction.equals(ACTION_INTERROGATE);
762c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
763c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
764c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean isRegister() {
76522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mAction != null && mAction.equals(ACTION_REGISTER);
766c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
767c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
768c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean isErasure() {
76922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mAction != null && mAction.equals(ACTION_ERASURE);
770c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
771c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
772c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
773c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Returns true if this is a USSD code that's been submitted to the
774c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * network...eg, after processCode() is called
775c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
776c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public boolean isPendingUSSD() {
77722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mIsPendingUSSD;
778c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
779c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
780cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
781c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public boolean isUssdRequest() {
78222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mIsUssdRequest;
783c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
784c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
78509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja    public boolean isSsInfo() {
78609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        return mIsSsInfo;
78709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja    }
78809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja
789c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Process a MMI code or short code...anything that isn't a dialing number */
7903a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    public void
7913a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    processCode() throws CallStateException {
792c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        try {
793c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (isShortCode()) {
7945b58978562c11e704b42a745bda55d6319a9b0c8Tyler Gunn                Rlog.d(LOG_TAG, "processCode: isShortCode");
795c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // These just get treated as USSD.
79622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sendUssd(mDialingNumber);
79722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mDialingNumber != null) {
798c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // We should have no dialing numbers here
799c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                throw new RuntimeException ("Invalid or Unsupported MMI Code");
80022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc != null && mSc.equals(SC_CLIP)) {
8015b58978562c11e704b42a745bda55d6319a9b0c8Tyler Gunn                Rlog.d(LOG_TAG, "processCode: is CLIP");
802c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isInterrogate()) {
80322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.queryCLIP(
804c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            obtainMessage(EVENT_QUERY_COMPLETE, this));
805c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
806c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException ("Invalid or Unsupported MMI Code");
807c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
80822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc != null && mSc.equals(SC_CLIR)) {
8095b58978562c11e704b42a745bda55d6319a9b0c8Tyler Gunn                Rlog.d(LOG_TAG, "processCode: is CLIR");
810c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isActivate()) {
81122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.setCLIR(CommandsInterface.CLIR_INVOCATION,
812c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        obtainMessage(EVENT_SET_COMPLETE, this));
813c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (isDeactivate()) {
81422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.setCLIR(CommandsInterface.CLIR_SUPPRESSION,
815c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        obtainMessage(EVENT_SET_COMPLETE, this));
816c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (isInterrogate()) {
81722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.getCLIR(
818c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        obtainMessage(EVENT_GET_CLIR_COMPLETE, this));
819c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
820c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException ("Invalid or Unsupported MMI Code");
821c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
82222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (isServiceCodeCallForwarding(mSc)) {
8235b58978562c11e704b42a745bda55d6319a9b0c8Tyler Gunn                Rlog.d(LOG_TAG, "processCode: is CF");
824c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
82522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                String dialingNumber = mSia;
82622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                int serviceClass = siToServiceClass(mSib);
82722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                int reason = scToCallForwardReason(mSc);
82822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                int time = siToTime(mSic);
829c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
830c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isInterrogate()) {
83122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.queryCallForwardStatus(
832c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            reason, serviceClass,  dialingNumber,
833c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                obtainMessage(EVENT_QUERY_CF_COMPLETE, this));
834c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
835c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    int cfAction;
836c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
837c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    if (isActivate()) {
8385f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        // 3GPP TS 22.030 6.5.2
8395f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        // a call forwarding request with a single * would be
8405f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        // interpreted as registration if containing a forwarded-to
8415f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        // number, or an activation if not
8425f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        if (isEmptyOrNull(dialingNumber)) {
8435f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                            cfAction = CommandsInterface.CF_ACTION_ENABLE;
84422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            mIsCallFwdReg = false;
8455f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        } else {
8465f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                            cfAction = CommandsInterface.CF_ACTION_REGISTRATION;
84722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            mIsCallFwdReg = true;
8485f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        }
849c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else if (isDeactivate()) {
850c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        cfAction = CommandsInterface.CF_ACTION_DISABLE;
851c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else if (isRegister()) {
852c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        cfAction = CommandsInterface.CF_ACTION_REGISTRATION;
853c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else if (isErasure()) {
854c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        cfAction = CommandsInterface.CF_ACTION_ERASURE;
855c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else {
856c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        throw new RuntimeException ("invalid action");
857c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
858c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
859c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    int isSettingUnconditionalVoice =
860c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        (((reason == CommandsInterface.CF_REASON_UNCONDITIONAL) ||
861c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                (reason == CommandsInterface.CF_REASON_ALL)) &&
862c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                (((serviceClass & CommandsInterface.SERVICE_CLASS_VOICE) != 0) ||
863c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                 (serviceClass == CommandsInterface.SERVICE_CLASS_NONE))) ? 1 : 0;
864c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
865c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    int isEnableDesired =
866c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        ((cfAction == CommandsInterface.CF_ACTION_ENABLE) ||
867c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                (cfAction == CommandsInterface.CF_ACTION_REGISTRATION)) ? 1 : 0;
868c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
8695b58978562c11e704b42a745bda55d6319a9b0c8Tyler Gunn                    Rlog.d(LOG_TAG, "processCode: is CF setCallForward");
87022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.setCallForward(cfAction, reason, serviceClass,
871c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            dialingNumber, time, obtainMessage(
872c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    EVENT_SET_CFF_COMPLETE,
873c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    isSettingUnconditionalVoice,
874c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    isEnableDesired, this));
875c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
87622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (isServiceCodeCallBarring(mSc)) {
877c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sia = password
878c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sib = basic service group
879c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
88022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                String password = mSia;
88122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                int serviceClass = siToServiceClass(mSib);
88222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                String facility = scToBarringFacility(mSc);
883c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
884c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isInterrogate()) {
88522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.queryFacilityLock(facility, password,
886c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            serviceClass, obtainMessage(EVENT_QUERY_COMPLETE, this));
887c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (isActivate() || isDeactivate()) {
88822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.setFacilityLock(facility, isActivate(), password,
889c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            serviceClass, obtainMessage(EVENT_SET_COMPLETE, this));
890c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
891c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException ("Invalid or Unsupported MMI Code");
892c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
893c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
89422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc != null && mSc.equals(SC_PWD)) {
895c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sia = fac
896c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sib = old pwd
897c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sic = new pwd
898c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // pwd = new pwd
899c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                String facility;
90022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                String oldPwd = mSib;
90122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                String newPwd = mSic;
902c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isActivate() || isRegister()) {
903c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // Even though ACTIVATE is acceptable, this is really termed a REGISTER
90422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mAction = ACTION_REGISTER;
905c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
90622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    if (mSia == null) {
907c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // If sc was not specified, treat it as BA_ALL.
908c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        facility = CommandsInterface.CB_FACILITY_BA_ALL;
909c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else {
91022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        facility = scToBarringFacility(mSia);
911c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
91222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    if (newPwd.equals(mPwd)) {
91322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        mPhone.mCi.changeBarringPassword(facility, oldPwd,
914c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                newPwd, obtainMessage(EVENT_SET_COMPLETE, this));
915c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else {
916c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // password mismatch; return error
917c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        handlePasswordError(com.android.internal.R.string.passwordIncorrect);
918c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
919c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
920c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException ("Invalid or Unsupported MMI Code");
921c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
922c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
92322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc != null && mSc.equals(SC_WAIT)) {
924c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sia = basic service group
92522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                int serviceClass = siToServiceClass(mSia);
926c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
927c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isActivate() || isDeactivate()) {
92822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.setCallWaiting(isActivate(), serviceClass,
929c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            obtainMessage(EVENT_SET_COMPLETE, this));
930c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (isInterrogate()) {
93122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.queryCallWaiting(serviceClass,
932c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            obtainMessage(EVENT_QUERY_COMPLETE, this));
933c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
934c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException ("Invalid or Unsupported MMI Code");
935c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
9363522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville            } else if (isPinPukCommand()) {
9373522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                // TODO: This is the same as the code in CmdaMmiCode.java,
9383522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                // MmiCode should be an abstract or base class and this and
9393522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                // other common variables and code should be promoted.
9403522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville
941c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sia = old PIN or PUK
942c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sib = new PIN
943c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sic = new PIN
94422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                String oldPinOrPuk = mSia;
9453522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                String newPinOrPuk = mSib;
9463522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                int pinLen = newPinOrPuk.length();
947c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isRegister()) {
9483522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    if (!newPinOrPuk.equals(mSic)) {
949c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // password mismatch; return error
950c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        handlePasswordError(com.android.internal.R.string.mismatchPin);
951c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else if (pinLen < 4 || pinLen > 8 ) {
952c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // invalid length
953c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        handlePasswordError(com.android.internal.R.string.invalidPin);
9543522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    } else if (mSc.equals(SC_PIN)
9553522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            && mUiccApplication != null
9563522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            && mUiccApplication.getState() == AppState.APPSTATE_PUK) {
957c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // Sim is puk-locked
958c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        handlePasswordError(com.android.internal.R.string.needPuk);
9593522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    } else if (mUiccApplication != null) {
9605b58978562c11e704b42a745bda55d6319a9b0c8Tyler Gunn                        Rlog.d(LOG_TAG,
9615b58978562c11e704b42a745bda55d6319a9b0c8Tyler Gunn                                "processCode: process mmi service code using UiccApp sc=" + mSc);
9623522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville
9633522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        // We have an app and the pre-checks are OK
96422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        if (mSc.equals(SC_PIN)) {
9653522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            mUiccApplication.changeIccLockPassword(oldPinOrPuk, newPinOrPuk,
966c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    obtainMessage(EVENT_SET_COMPLETE, this));
96722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        } else if (mSc.equals(SC_PIN2)) {
9683522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            mUiccApplication.changeIccFdnPassword(oldPinOrPuk, newPinOrPuk,
969c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    obtainMessage(EVENT_SET_COMPLETE, this));
97022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        } else if (mSc.equals(SC_PUK)) {
9713522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            mUiccApplication.supplyPuk(oldPinOrPuk, newPinOrPuk,
972c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    obtainMessage(EVENT_SET_COMPLETE, this));
97322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        } else if (mSc.equals(SC_PUK2)) {
9743522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            mUiccApplication.supplyPuk2(oldPinOrPuk, newPinOrPuk,
975c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    obtainMessage(EVENT_SET_COMPLETE, this));
9763522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        } else {
9773522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            throw new RuntimeException("uicc unsupported service code=" + mSc);
978c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        }
9793522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    } else {
9803522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        throw new RuntimeException("No application mUiccApplicaiton is null");
981c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
982c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
9833522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    throw new RuntimeException ("Ivalid register/action=" + mAction);
984c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
98522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mPoundString != null) {
98622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sendUssd(mPoundString);
987c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
9885b58978562c11e704b42a745bda55d6319a9b0c8Tyler Gunn                Rlog.d(LOG_TAG, "processCode: Invalid or Unsupported MMI Code");
989c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                throw new RuntimeException ("Invalid or Unsupported MMI Code");
990c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
991c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } catch (RuntimeException exc) {
99222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.FAILED;
99322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mMessage = mContext.getText(com.android.internal.R.string.mmiError);
9945b58978562c11e704b42a745bda55d6319a9b0c8Tyler Gunn            Rlog.d(LOG_TAG, "processCode: RuntimeException=" + exc);
99522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mPhone.onMMIDone(this);
996c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
997c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
998c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
999c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void handlePasswordError(int res) {
100022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mState = State.FAILED;
1001c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder(getScString());
1002c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("\n");
100322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        sb.append(mContext.getText(res));
100422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mMessage = sb;
100522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mPhone.onMMIDone(this);
1006c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1007c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1008c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
100958dd6858dc8013b680ea003d22063fd65ed5fe1cAmit Mahajan     * Called from GsmCdmaPhone
1010c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
1011c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * An unsolicited USSD NOTIFY or REQUEST has come in matching
1012c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * up with this pending USSD request
1013c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
1014c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Note: If REQUEST, this exchange is complete, but the session remains
1015c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *       active (ie, the network expects user input).
1016c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
10173a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    public void
1018c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    onUssdFinished(String ussdMessage, boolean isUssdRequest) {
101922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mState == State.PENDING) {
1020f5bd60e5d8cb7700aced832ee685da8a77044a22Tyler Gunn            if (TextUtils.isEmpty(ussdMessage)) {
1021f5bd60e5d8cb7700aced832ee685da8a77044a22Tyler Gunn                Rlog.d(LOG_TAG, "onUssdFinished: no network provided message; using default.");
102222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mMessage = mContext.getText(com.android.internal.R.string.mmiComplete);
1023c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
102422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mMessage = ussdMessage;
1025c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
102622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mIsUssdRequest = isUssdRequest;
1027c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // If it's a request, leave it PENDING so that it's cancelable.
1028c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (!isUssdRequest) {
102922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mState = State.COMPLETE;
1030c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
10315b58978562c11e704b42a745bda55d6319a9b0c8Tyler Gunn            Rlog.d(LOG_TAG, "onUssdFinished: ussdMessage=" + ussdMessage);
103222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mPhone.onMMIDone(this);
1033c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1034c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1035c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1036c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
103758dd6858dc8013b680ea003d22063fd65ed5fe1cAmit Mahajan     * Called from GsmCdmaPhone
1038c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
1039c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * The radio has reset, and this is still pending
1040c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
1041c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
10423a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    public void
1043c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    onUssdFinishedError() {
104422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mState == State.PENDING) {
104522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.FAILED;
104622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mMessage = mContext.getText(com.android.internal.R.string.mmiError);
10475b58978562c11e704b42a745bda55d6319a9b0c8Tyler Gunn            Rlog.d(LOG_TAG, "onUssdFinishedError");
104822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mPhone.onMMIDone(this);
1049c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1050c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1051c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
10520aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati    /**
105358dd6858dc8013b680ea003d22063fd65ed5fe1cAmit Mahajan     * Called from GsmCdmaPhone
10540aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati     *
10550aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati     * An unsolicited USSD NOTIFY or REQUEST has come in matching
10560aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati     * up with this pending USSD request
10570aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati     *
10580aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati     * Note: If REQUEST, this exchange is complete, but the session remains
10590aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati     *       active (ie, the network expects user input).
10600aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati     */
10613a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    public void
10620aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati    onUssdRelease() {
10630aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati        if (mState == State.PENDING) {
10640aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati            mState = State.COMPLETE;
10650aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati            mMessage = null;
10665b58978562c11e704b42a745bda55d6319a9b0c8Tyler Gunn            Rlog.d(LOG_TAG, "onUssdRelease");
10670aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati            mPhone.onMMIDone(this);
10680aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati        }
10690aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati    }
10700aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati
10713a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    public void sendUssd(String ussdMessage) {
1072c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Treat this as a USSD string
107322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mIsPendingUSSD = true;
1074c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1075c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Note that unlike most everything else, the USSD complete
1076c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // response does not complete this MMI code...we wait for
1077c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // an unsolicited USSD "Notify" or "Request".
107858dd6858dc8013b680ea003d22063fd65ed5fe1cAmit Mahajan        // The matching up of this is done in GsmCdmaPhone.
107922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mPhone.mCi.sendUSSD(ussdMessage,
1080c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            obtainMessage(EVENT_USSD_COMPLETE, this));
1081c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1082c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
108358dd6858dc8013b680ea003d22063fd65ed5fe1cAmit Mahajan    /** Called from GsmCdmaPhone.handleMessage; not a Handler subclass */
1084cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
1085c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void
1086c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    handleMessage (Message msg) {
1087c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        AsyncResult ar;
1088c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1089c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        switch (msg.what) {
1090c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_SET_COMPLETE:
1091c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
1092c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
10933522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                onSetComplete(msg, ar);
1094c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1095c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1096c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_SET_CFF_COMPLETE:
1097c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
1098c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1099c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                /*
1100c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                * msg.arg1 = 1 means to set unconditional voice call forwarding
1101c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                * msg.arg2 = 1 means to enable voice call forwarding
1102c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                */
1103c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if ((ar.exception == null) && (msg.arg1 == 1)) {
1104c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    boolean cffEnabled = (msg.arg2 == 1);
1105e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    if (mIccRecords != null) {
1106eadee84166d397b6425cfd56f89fa1569f6a93f5Amit Mahajan                        mPhone.setVoiceCallForwardingFlag(1, cffEnabled, mDialingNumber);
1107bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                    }
1108c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
1109c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
11103522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                onSetComplete(msg, ar);
1111c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1112c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1113c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_GET_CLIR_COMPLETE:
1114c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
1115c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                onGetClirComplete(ar);
1116c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
1117c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1118c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_QUERY_CF_COMPLETE:
1119c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
1120c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                onQueryCfComplete(ar);
1121c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
1122c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1123c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_QUERY_COMPLETE:
1124c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
1125c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                onQueryComplete(ar);
1126c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
1127c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1128c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_USSD_COMPLETE:
1129c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
1130c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1131c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (ar.exception != null) {
113222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mState = State.FAILED;
113322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mMessage = getErrorMessage(ar);
1134c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
113522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.onMMIDone(this);
1136c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
1137c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1138c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // Note that unlike most everything else, the USSD complete
1139c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // response does not complete this MMI code...we wait for
1140c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // an unsolicited USSD "Notify" or "Request".
114158dd6858dc8013b680ea003d22063fd65ed5fe1cAmit Mahajan                // The matching up of this is done in GsmCdmaPhone.
1142c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1143c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
1144c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1145c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_USSD_CANCEL_COMPLETE:
114622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mPhone.onMMIDone(this);
1147c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
1148c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1149c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1150c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Private instance methods
1151c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1152c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence getErrorMessage(AsyncResult ar) {
1153c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1154c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (ar.exception instanceof CommandException) {
1155c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            CommandException.Error err = ((CommandException)(ar.exception)).getCommandError();
1156c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (err == CommandException.Error.FDN_CHECK_FAILURE) {
1157ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.i(LOG_TAG, "FDN_CHECK_FAILURE");
115822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.mmiFdnError);
115909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            } else if (err == CommandException.Error.USSD_MODIFIED_TO_DIAL) {
116009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                Rlog.i(LOG_TAG, "USSD_MODIFIED_TO_DIAL");
116109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return mContext.getText(com.android.internal.R.string.stk_cc_ussd_to_dial);
116209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            } else if (err == CommandException.Error.USSD_MODIFIED_TO_SS) {
116309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                Rlog.i(LOG_TAG, "USSD_MODIFIED_TO_SS");
116409b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return mContext.getText(com.android.internal.R.string.stk_cc_ussd_to_ss);
116509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            } else if (err == CommandException.Error.USSD_MODIFIED_TO_USSD) {
116609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                Rlog.i(LOG_TAG, "USSD_MODIFIED_TO_USSD");
116709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return mContext.getText(com.android.internal.R.string.stk_cc_ussd_to_ussd);
116809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            } else if (err == CommandException.Error.SS_MODIFIED_TO_DIAL) {
116909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                Rlog.i(LOG_TAG, "SS_MODIFIED_TO_DIAL");
117009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return mContext.getText(com.android.internal.R.string.stk_cc_ss_to_dial);
117109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            } else if (err == CommandException.Error.SS_MODIFIED_TO_USSD) {
117209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                Rlog.i(LOG_TAG, "SS_MODIFIED_TO_USSD");
117309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return mContext.getText(com.android.internal.R.string.stk_cc_ss_to_ussd);
117409b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            } else if (err == CommandException.Error.SS_MODIFIED_TO_SS) {
117509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                Rlog.i(LOG_TAG, "SS_MODIFIED_TO_SS");
117609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return mContext.getText(com.android.internal.R.string.stk_cc_ss_to_ss);
1177c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1178c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1179c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
118022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mContext.getText(com.android.internal.R.string.mmiError);
1181c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1182c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1183c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence getScString() {
118422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mSc != null) {
118522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            if (isServiceCodeCallBarring(mSc)) {
118622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.BaMmi);
118722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (isServiceCodeCallForwarding(mSc)) {
118822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.CfMmi);
118922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc.equals(SC_CLIP)) {
119022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.ClipMmi);
119122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc.equals(SC_CLIR)) {
119222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.ClirMmi);
119322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc.equals(SC_PWD)) {
119422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.PwdMmi);
119522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc.equals(SC_WAIT)) {
119622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.CwMmi);
11973522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville            } else if (isPinPukCommand()) {
119822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.PinMmi);
1199c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1200c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1201c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1202c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return "";
1203c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1204c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1205c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void
12063522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville    onSetComplete(Message msg, AsyncResult ar){
1207c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder(getScString());
1208c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("\n");
1209c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1210c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (ar.exception != null) {
121122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.FAILED;
1212c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (ar.exception instanceof CommandException) {
1213c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                CommandException.Error err = ((CommandException)(ar.exception)).getCommandError();
1214c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (err == CommandException.Error.PASSWORD_INCORRECT) {
12153522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    if (isPinPukCommand()) {
1216c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // look specifically for the PUK commands and adjust
1217c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // the message accordingly.
121822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        if (mSc.equals(SC_PUK) || mSc.equals(SC_PUK2)) {
121922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1220c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.badPuk));
1221c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        } else {
122222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1223c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.badPin));
1224c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        }
12253522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        // Get the No. of retries remaining to unlock PUK/PUK2
12263522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        int attemptsRemaining = msg.arg1;
12276d3c836bb8991e9cf7ffb322ebabf48c2446126dWink Saville                        if (attemptsRemaining <= 0) {
12286d3c836bb8991e9cf7ffb322ebabf48c2446126dWink Saville                            Rlog.d(LOG_TAG, "onSetComplete: PUK locked,"
12296d3c836bb8991e9cf7ffb322ebabf48c2446126dWink Saville                                    + " cancel as lock screen will handle this");
12306d3c836bb8991e9cf7ffb322ebabf48c2446126dWink Saville                            mState = State.CANCELLED;
12316d3c836bb8991e9cf7ffb322ebabf48c2446126dWink Saville                        } else if (attemptsRemaining > 0) {
12326d3c836bb8991e9cf7ffb322ebabf48c2446126dWink Saville                            Rlog.d(LOG_TAG, "onSetComplete: attemptsRemaining="+attemptsRemaining);
12333522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            sb.append(mContext.getResources().getQuantityString(
12343522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                                    com.android.internal.R.plurals.pinpuk_attempts,
12353522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                                    attemptsRemaining, attemptsRemaining));
12363522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        }
1237c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else {
123822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        sb.append(mContext.getText(
1239c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                com.android.internal.R.string.passwordIncorrect));
1240c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
1241c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (err == CommandException.Error.SIM_PUK2) {
124222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(
1243c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            com.android.internal.R.string.badPin));
1244c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    sb.append("\n");
124522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(
1246c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            com.android.internal.R.string.needPuk2));
12473522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                } else if (err == CommandException.Error.REQUEST_NOT_SUPPORTED) {
12483522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    if (mSc.equals(SC_PIN)) {
12493522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        sb.append(mContext.getText(com.android.internal.R.string.enablePin));
12503522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    }
1251c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (err == CommandException.Error.FDN_CHECK_FAILURE) {
1252ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                    Rlog.i(LOG_TAG, "FDN_CHECK_FAILURE");
125322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(com.android.internal.R.string.mmiFdnError));
1254e48f325a296ce0e74415dd737c7d461b021b0fccBrad Ebinger                } else if (err == CommandException.Error.MODEM_ERR) {
1255e48f325a296ce0e74415dd737c7d461b021b0fccBrad Ebinger                    // Some carriers do not allow changing call forwarding settings while roaming
1256e48f325a296ce0e74415dd737c7d461b021b0fccBrad Ebinger                    // and will return an error from the modem.
1257e48f325a296ce0e74415dd737c7d461b021b0fccBrad Ebinger                    if (isServiceCodeCallForwarding(mSc)
1258e48f325a296ce0e74415dd737c7d461b021b0fccBrad Ebinger                            && mPhone.getServiceState().getVoiceRoaming()
1259e48f325a296ce0e74415dd737c7d461b021b0fccBrad Ebinger                            && !mPhone.supports3gppCallForwardingWhileRoaming()) {
1260e48f325a296ce0e74415dd737c7d461b021b0fccBrad Ebinger                        sb.append(mContext.getText(
1261e48f325a296ce0e74415dd737c7d461b021b0fccBrad Ebinger                                com.android.internal.R.string.mmiErrorWhileRoaming));
1262e48f325a296ce0e74415dd737c7d461b021b0fccBrad Ebinger                    } else {
1263e48f325a296ce0e74415dd737c7d461b021b0fccBrad Ebinger                        sb.append(getErrorMessage(ar));
1264e48f325a296ce0e74415dd737c7d461b021b0fccBrad Ebinger                    }
1265c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
126609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                    sb.append(getErrorMessage(ar));
1267c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
1268c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
126922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sb.append(mContext.getText(
1270c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.mmiError));
1271c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1272c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isActivate()) {
127322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.COMPLETE;
127422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            if (mIsCallFwdReg) {
127522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sb.append(mContext.getText(
12765f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        com.android.internal.R.string.serviceRegistered));
12775f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li            } else {
127822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sb.append(mContext.getText(
12795f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        com.android.internal.R.string.serviceEnabled));
12805f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li            }
1281c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // Record CLIR setting
128222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            if (mSc.equals(SC_CLIR)) {
128322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mPhone.saveClirSetting(CommandsInterface.CLIR_INVOCATION);
1284c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1285c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isDeactivate()) {
128622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.COMPLETE;
128722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            sb.append(mContext.getText(
1288c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    com.android.internal.R.string.serviceDisabled));
1289c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // Record CLIR setting
129022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            if (mSc.equals(SC_CLIR)) {
129122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mPhone.saveClirSetting(CommandsInterface.CLIR_SUPPRESSION);
1292c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1293c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isRegister()) {
129422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.COMPLETE;
129522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            sb.append(mContext.getText(
1296c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    com.android.internal.R.string.serviceRegistered));
1297c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isErasure()) {
129822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.COMPLETE;
129922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            sb.append(mContext.getText(
1300c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    com.android.internal.R.string.serviceErased));
1301c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
130222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.FAILED;
130322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            sb.append(mContext.getText(
1304c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    com.android.internal.R.string.mmiError));
1305c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1306c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
130722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mMessage = sb;
13085b58978562c11e704b42a745bda55d6319a9b0c8Tyler Gunn        Rlog.d(LOG_TAG, "onSetComplete mmi=" + this);
130922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mPhone.onMMIDone(this);
1310c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1311c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1312c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void
1313c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    onGetClirComplete(AsyncResult ar) {
1314c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder(getScString());
1315c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("\n");
1316c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1317c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (ar.exception != null) {
131822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.FAILED;
1319c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            sb.append(getErrorMessage(ar));
1320c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
1321c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            int clirArgs[];
1322c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1323c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            clirArgs = (int[])ar.result;
1324c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1325c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // the 'm' parameter from TS 27.007 7.7
1326c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            switch (clirArgs[1]) {
1327c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 0: // CLIR not provisioned
132822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(
1329c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                com.android.internal.R.string.serviceNotProvisioned));
133022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mState = State.COMPLETE;
1331c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1332c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1333c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 1: // CLIR provisioned in permanent mode
133422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(
1335c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                com.android.internal.R.string.CLIRPermanent));
133622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mState = State.COMPLETE;
1337c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1338c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1339c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 2: // unknown (e.g. no network, etc.)
134022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(
1341c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                com.android.internal.R.string.mmiError));
134222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mState = State.FAILED;
1343c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1344c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1345c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 3: // CLIR temporary mode presentation restricted
1346c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1347c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // the 'n' parameter from TS 27.007 7.7
1348c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    switch (clirArgs[0]) {
1349c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        default:
1350c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 0: // Default
135122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1352c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOnNextCallOn));
1353c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1354c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 1: // CLIR invocation
135522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1356c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOnNextCallOn));
1357c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1358c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 2: // CLIR suppression
135922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1360c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOnNextCallOff));
1361c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1362c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
136322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mState = State.COMPLETE;
1364c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1365c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1366c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 4: // CLIR temporary mode presentation allowed
1367c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // the 'n' parameter from TS 27.007 7.7
1368c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    switch (clirArgs[0]) {
1369c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        default:
1370c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 0: // Default
137122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1372c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOffNextCallOff));
1373c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1374c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 1: // CLIR invocation
137522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1376c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOffNextCallOn));
1377c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1378c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 2: // CLIR suppression
137922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1380c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOffNextCallOff));
1381c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1382c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
1383c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
138422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mState = State.COMPLETE;
1385c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1386c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1387c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1388c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
138922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mMessage = sb;
13905b58978562c11e704b42a745bda55d6319a9b0c8Tyler Gunn        Rlog.d(LOG_TAG, "onGetClirComplete: mmi=" + this);
139122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mPhone.onMMIDone(this);
1392c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1393c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1394c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
1395c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param serviceClass 1 bit of the service class bit vectory
1396c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @return String to be used for call forward query MMI response text.
1397c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *        Returns null if unrecognized
1398c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
1399c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1400c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence
1401c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    serviceClassToCFString (int serviceClass) {
1402c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        switch (serviceClass) {
1403c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_VOICE:
140422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassVoice);
1405c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_DATA:
140622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassData);
1407c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_FAX:
140822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassFAX);
1409c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_SMS:
141022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassSMS);
1411c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_DATA_SYNC:
141222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassDataSync);
1413c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_DATA_ASYNC:
141422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassDataAsync);
1415c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_PACKET:
141622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassPacket);
1417c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_PAD:
141822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassPAD);
1419c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            default:
1420c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return null;
1421c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1422c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1423c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1424c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1425c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** one CallForwardInfo + serviceClassMask -> one line of text */
1426c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence
1427c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    makeCFQueryResultMessage(CallForwardInfo info, int serviceClassMask) {
1428c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        CharSequence template;
1429c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        String sources[] = {"{0}", "{1}", "{2}"};
1430c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        CharSequence destinations[] = new CharSequence[3];
1431c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        boolean needTimeTemplate;
1432c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1433c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // CF_REASON_NO_REPLY also has a time value associated with
1434c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // it. All others don't.
1435c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1436c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        needTimeTemplate =
1437c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            (info.reason == CommandsInterface.CF_REASON_NO_REPLY);
1438c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1439c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (info.status == 1) {
1440c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (needTimeTemplate) {
144122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                template = mContext.getText(
1442c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.cfTemplateForwardedTime);
1443c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
144422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                template = mContext.getText(
1445c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.cfTemplateForwarded);
1446c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1447c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (info.status == 0 && isEmptyOrNull(info.number)) {
144822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            template = mContext.getText(
1449c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.cfTemplateNotForwarded);
1450c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else { /* (info.status == 0) && !isEmptyOrNull(info.number) */
1451c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // A call forward record that is not active but contains
1452c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // a phone number is considered "registered"
1453c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1454c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (needTimeTemplate) {
145522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                template = mContext.getText(
1456c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.cfTemplateRegisteredTime);
1457c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
145822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                template = mContext.getText(
1459c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.cfTemplateRegistered);
1460c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1461c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1462c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1463c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // In the template (from strings.xmls)
1464c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        //         {0} is one of "bearerServiceCode*"
1465c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        //        {1} is dialing number
1466c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        //      {2} is time in seconds
1467c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1468c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        destinations[0] = serviceClassToCFString(info.serviceClass & serviceClassMask);
14698697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlsson        destinations[1] = formatLtr(
14708697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlsson                PhoneNumberUtils.stringFromStringAndTOA(info.number, info.toa));
1471c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        destinations[2] = Integer.toString(info.timeSeconds);
1472c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1473c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (info.reason == CommandsInterface.CF_REASON_UNCONDITIONAL &&
1474c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                (info.serviceClass & serviceClassMask)
1475c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        == CommandsInterface.SERVICE_CLASS_VOICE) {
1476c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            boolean cffEnabled = (info.status == 1);
1477e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (mIccRecords != null) {
1478eadee84166d397b6425cfd56f89fa1569f6a93f5Amit Mahajan                mPhone.setVoiceCallForwardingFlag(1, cffEnabled, info.number);
1479bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka            }
1480c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1481c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1482c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return TextUtils.replace(template, sources, destinations);
1483c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1484c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
14858697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlsson    /**
14868697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlsson     * Used to format a string that should be displayed as LTR even in RTL locales
14878697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlsson     */
14888697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlsson    private String formatLtr(String str) {
14898697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlsson        BidiFormatter fmt = BidiFormatter.getInstance();
14908697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlsson        return str == null ? str : fmt.unicodeWrap(str, TextDirectionHeuristics.LTR, true);
14918697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlsson    }
1492c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1493c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void
1494c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    onQueryCfComplete(AsyncResult ar) {
1495c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder(getScString());
1496c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("\n");
1497c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1498c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (ar.exception != null) {
149922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.FAILED;
1500c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            sb.append(getErrorMessage(ar));
1501c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
1502c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            CallForwardInfo infos[];
1503c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1504c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            infos = (CallForwardInfo[]) ar.result;
1505c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1506c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (infos.length == 0) {
1507c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // Assume the default is not active
150822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sb.append(mContext.getText(com.android.internal.R.string.serviceDisabled));
1509c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1510c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // Set unconditional CFF in SIM to false
1511e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if (mIccRecords != null) {
1512eadee84166d397b6425cfd56f89fa1569f6a93f5Amit Mahajan                    mPhone.setVoiceCallForwardingFlag(1, false, null);
1513bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                }
1514c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
1515c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1516c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                SpannableStringBuilder tb = new SpannableStringBuilder();
1517c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1518c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // Each bit in the service class gets its own result line
1519c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // The service classes may be split up over multiple
1520c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // CallForwardInfos. So, for each service class, find out
1521c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // which CallForwardInfo represents it and then build
1522c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // the response text based on that
1523c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1524c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                for (int serviceClassMask = 1
1525c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            ; serviceClassMask <= SERVICE_CLASS_MAX
1526c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            ; serviceClassMask <<= 1
1527c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ) {
1528c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    for (int i = 0, s = infos.length; i < s ; i++) {
1529c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        if ((serviceClassMask & infos[i].serviceClass) != 0) {
1530c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            tb.append(makeCFQueryResultMessage(infos[i],
1531c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                            serviceClassMask));
1532c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            tb.append("\n");
1533c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        }
1534c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
1535c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
1536c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sb.append(tb);
1537c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1538c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
153922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.COMPLETE;
1540c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1541c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
154222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mMessage = sb;
15435b58978562c11e704b42a745bda55d6319a9b0c8Tyler Gunn        Rlog.d(LOG_TAG, "onQueryCfComplete: mmi=" + this);
154422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mPhone.onMMIDone(this);
1545c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1546c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1547c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1548c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void
1549c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    onQueryComplete(AsyncResult ar) {
1550c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder(getScString());
1551c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("\n");
1552c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1553c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (ar.exception != null) {
155422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.FAILED;
1555c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            sb.append(getErrorMessage(ar));
1556c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
1557c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            int[] ints = (int[])ar.result;
1558c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1559c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (ints.length != 0) {
1560c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (ints[0] == 0) {
156122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(com.android.internal.R.string.serviceDisabled));
156222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                } else if (mSc.equals(SC_WAIT)) {
1563c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // Call Waiting includes additional data in the response.
1564c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    sb.append(createQueryCallWaitingResultMessage(ints[1]));
156522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                } else if (isServiceCodeCallBarring(mSc)) {
1566c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // ints[0] for Call Barring is a bit vector of services
1567c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    sb.append(createQueryCallBarringResultMessage(ints[0]));
1568c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (ints[0] == 1) {
1569c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // for all other services, treat it as a boolean
157022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(com.android.internal.R.string.serviceEnabled));
1571c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
157222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(com.android.internal.R.string.mmiError));
1573c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
1574c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
157522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sb.append(mContext.getText(com.android.internal.R.string.mmiError));
1576c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
157722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.COMPLETE;
1578c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1579c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
158022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mMessage = sb;
15815b58978562c11e704b42a745bda55d6319a9b0c8Tyler Gunn        Rlog.d(LOG_TAG, "onQueryComplete: mmi=" + this);
158222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mPhone.onMMIDone(this);
1583c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1584c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1585c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence
1586c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    createQueryCallWaitingResultMessage(int serviceClass) {
1587c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb =
158822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                new StringBuilder(mContext.getText(com.android.internal.R.string.serviceEnabledFor));
1589c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1590c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        for (int classMask = 1
1591c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    ; classMask <= SERVICE_CLASS_MAX
1592c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    ; classMask <<= 1
1593c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        ) {
1594c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if ((classMask & serviceClass) != 0) {
1595c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sb.append("\n");
1596c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sb.append(serviceClassToCFString(classMask & serviceClass));
1597c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1598c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1599c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return sb;
1600c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1601c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence
1602c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    createQueryCallBarringResultMessage(int serviceClass)
1603c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    {
160422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        StringBuilder sb = new StringBuilder(mContext.getText(com.android.internal.R.string.serviceEnabledFor));
1605c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1606c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        for (int classMask = 1
1607c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    ; classMask <= SERVICE_CLASS_MAX
1608c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    ; classMask <<= 1
1609c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        ) {
1610c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if ((classMask & serviceClass) != 0) {
1611c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sb.append("\n");
1612c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sb.append(serviceClassToCFString(classMask & serviceClass));
1613c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1614c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1615c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return sb;
1616c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1617c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
161816b58d13bde6487c6993831ca63385915be8956epkanwar    public ResultReceiver getUssdCallbackReceiver() {
161916b58d13bde6487c6993831ca63385915be8956epkanwar        return this.mCallbackReceiver;
162016b58d13bde6487c6993831ca63385915be8956epkanwar    }
162116b58d13bde6487c6993831ca63385915be8956epkanwar
1622c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /***
1623c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * TODO: It would be nice to have a method here that can take in a dialstring and
1624c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * figure out if there is an MMI code embedded within it.  This code would replace
1625c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * some of the string parsing functionality in the Phone App's
1626c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * SpecialCharSequenceMgr class.
1627c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
1628c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1629c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
1630c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public String toString() {
1631c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder("GsmMmiCode {");
1632c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1633c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("State=" + getState());
163422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mAction != null) sb.append(" action=" + mAction);
163522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mSc != null) sb.append(" sc=" + mSc);
1636f0e497e8cf789cf47bd60a68ac12e5e22dbbe855Shunta Sakai        if (mSia != null) sb.append(" sia=" + Rlog.pii(LOG_TAG, mSia));
1637f0e497e8cf789cf47bd60a68ac12e5e22dbbe855Shunta Sakai        if (mSib != null) sb.append(" sib=" + Rlog.pii(LOG_TAG, mSib));
1638f0e497e8cf789cf47bd60a68ac12e5e22dbbe855Shunta Sakai        if (mSic != null) sb.append(" sic=" + Rlog.pii(LOG_TAG, mSic));
1639f0e497e8cf789cf47bd60a68ac12e5e22dbbe855Shunta Sakai        if (mPoundString != null) sb.append(" poundString=" + Rlog.pii(LOG_TAG, mPoundString));
1640feefaf43d83ee53c9f9798206a387448f233f7a9Tyler Gunn        if (mDialingNumber != null) {
1641feefaf43d83ee53c9f9798206a387448f233f7a9Tyler Gunn            sb.append(" dialingNumber=" + Rlog.pii(LOG_TAG, mDialingNumber));
1642feefaf43d83ee53c9f9798206a387448f233f7a9Tyler Gunn        }
1643feefaf43d83ee53c9f9798206a387448f233f7a9Tyler Gunn        if (mPwd != null) sb.append(" pwd=" + Rlog.pii(LOG_TAG, mPwd));
1644feefaf43d83ee53c9f9798206a387448f233f7a9Tyler Gunn        if (mCallbackReceiver != null) sb.append(" hasReceiver");
1645c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("}");
1646c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return sb.toString();
1647c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1648c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville}
1649