GsmMmiCode.java revision 3522c54a64f577f2b657a775dae9b4eb2d8003d5
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;
29c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.text.TextUtils;
30ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Savilleimport android.telephony.Rlog;
31c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
32c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport static com.android.internal.telephony.CommandsInterface.*;
33c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
34c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport java.util.regex.Pattern;
35c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport java.util.regex.Matcher;
36c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
37c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/**
38c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * The motto for this file is:
39c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
40c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * "NOTE:    By using the # as a separator, most cases are expected to be unambiguous."
41c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *   -- TS 22.030 6.5.2
42c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
43c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * {@hide}
44c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
45c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */
46c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savillepublic final class GsmMmiCode extends Handler implements MmiCode {
47cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    static final String LOG_TAG = "GsmMmiCode";
48c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
49c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Constants
50c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
51c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Max Size of the Short Code (aka Short String from TS 22.030 6.5.2)
52c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MAX_LENGTH_SHORT_CODE = 2;
53c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
54c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // TS 22.030 6.5.2 Every Short String USSD command will end with #-key
55c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // (known as #-String)
56c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final char END_OF_USSD_COMMAND = '#';
57c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
58c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // From TS 22.030 6.5.2
59c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String ACTION_ACTIVATE = "*";
60c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String ACTION_DEACTIVATE = "#";
61c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String ACTION_INTERROGATE = "*#";
62c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String ACTION_REGISTER = "**";
63c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String ACTION_ERASURE = "##";
64c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
65c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Supp Service codes from TS 22.030 Annex B
66c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
67c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //Called line presentation
68c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CLIP    = "30";
69c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CLIR    = "31";
70c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
71c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Call Forwarding
72c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CFU     = "21";
73c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CFB     = "67";
74c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CFNRy   = "61";
75c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CFNR    = "62";
76c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
77c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CF_All = "002";
78c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CF_All_Conditional = "004";
79c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
80c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Call Waiting
81c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_WAIT     = "43";
82c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
83c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Call Barring
84c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BAOC         = "33";
85c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BAOIC        = "331";
86c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BAOICxH      = "332";
87c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BAIC         = "35";
88c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BAICr        = "351";
89c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
90c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BA_ALL       = "330";
91c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BA_MO        = "333";
92c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BA_MT        = "353";
93c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
94c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Supp Service Password registration
95c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_PWD          = "03";
96c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
97c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // PIN/PIN2/PUK/PUK2
98c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_PIN          = "04";
99c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_PIN2         = "042";
100c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_PUK          = "05";
101c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_PUK2         = "052";
102c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
103c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Event Constants
104c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
105c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_SET_COMPLETE         = 1;
106c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_GET_CLIR_COMPLETE    = 2;
107c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_QUERY_CF_COMPLETE    = 3;
108c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_USSD_COMPLETE        = 4;
109c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_QUERY_COMPLETE       = 5;
110c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_SET_CFF_COMPLETE     = 6;
111c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_USSD_CANCEL_COMPLETE = 7;
112c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
113c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Instance Variables
114c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
11522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    GSMPhone mPhone;
11622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    Context mContext;
117e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    UiccCardApplication mUiccApplication;
118e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    IccRecords mIccRecords;
119c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
12022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    String mAction;              // One of ACTION_*
12122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    String mSc;                  // Service Code
12222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    String mSia, mSib, mSic;       // Service Info a,b,c
12322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    String mPoundString;         // Entire MMI string up to and including #
12422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    String mDialingNumber;
12522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    String mPwd;                 // For password registration
126c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
127c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Set to true in processCode, not at newFromDialString time */
12822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    private boolean mIsPendingUSSD;
129c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
13022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    private boolean mIsUssdRequest;
131c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
13222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    private boolean mIsCallFwdReg;
13322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    State mState = State.PENDING;
13422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    CharSequence mMessage;
135c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
136c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Class Variables
137c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
138c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
139c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // See TS 22.030 6.5.2 "Structure of the MMI"
140c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
141c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static Pattern sPatternSuppService = Pattern.compile(
1429225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang        "((\\*|#|\\*#|\\*\\*|##)(\\d{2,3})(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*))?)?)?)?#)(.*)");
143c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/*       1  2                    3          4  5       6   7         8    9     10  11             12
144c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
145c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         1 = Full string up to and including #
146c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         2 = action (activation/interrogation/registration/erasure)
147c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         3 = service code
148c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         5 = SIA
149c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         7 = SIB
150c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         9 = SIC
1519225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang         10 = dialing number
152c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville*/
153c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
154c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_POUND_STRING = 1;
155c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
156c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_ACTION = 2;
157c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        //(activation/interrogation/registration/erasure)
158c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
159c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_SERVICE_CODE = 3;
160c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_SIA = 5;
161c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_SIB = 7;
162c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_SIC = 9;
163c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_PWD_CONFIRM = 11;
164c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_DIALING_NUMBER = 12;
165c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static private String[] sTwoDigitNumberPattern;
166c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
167c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Public Class methods
168c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
169c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
170c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Some dial strings in GSM are defined to do non-call setup
171c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * things, such as modify or query supplementary service settings (eg, call
172c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * forwarding). These are generally referred to as "MMI codes".
173c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * We look to see if the dial string contains a valid MMI code (potentially
174c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * with a dial string at the end as well) and return info here.
175c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
176c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * If the dial string contains no MMI code, we return an instance with
177c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * only "dialingNumber" set
178c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
179c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Please see flow chart in TS 22.030 6.5.3.2
180c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
181c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
182c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static GsmMmiCode
183e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    newFromDialString(String dialString, GSMPhone phone, UiccCardApplication app) {
184c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        Matcher m;
185c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        GsmMmiCode ret = null;
186c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
187c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        m = sPatternSuppService.matcher(dialString);
188c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
189c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Is this formatted like a standard supplementary service code?
190c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (m.matches()) {
191e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            ret = new GsmMmiCode(phone, app);
19222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mPoundString = makeEmptyNull(m.group(MATCH_GROUP_POUND_STRING));
19322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mAction = makeEmptyNull(m.group(MATCH_GROUP_ACTION));
19422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mSc = makeEmptyNull(m.group(MATCH_GROUP_SERVICE_CODE));
19522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mSia = makeEmptyNull(m.group(MATCH_GROUP_SIA));
19622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mSib = makeEmptyNull(m.group(MATCH_GROUP_SIB));
19722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mSic = makeEmptyNull(m.group(MATCH_GROUP_SIC));
19822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mPwd = makeEmptyNull(m.group(MATCH_GROUP_PWD_CONFIRM));
19922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mDialingNumber = makeEmptyNull(m.group(MATCH_GROUP_DIALING_NUMBER));
2009225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            // According to TS 22.030 6.5.2 "Structure of the MMI",
2019225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            // the dialing number should not ending with #.
2029225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            // The dialing number ending # is treated as unique USSD,
2039225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            // eg, *400#16 digit number# to recharge the prepaid card
2049225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            // in India operator(Mumbai MTNL)
20522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            if(ret.mDialingNumber != null &&
20622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    ret.mDialingNumber.endsWith("#") &&
2079225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang                    dialString.endsWith("#")){
2089225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang                ret = new GsmMmiCode(phone, app);
20922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                ret.mPoundString = dialString;
2109225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            }
211c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (dialString.endsWith("#")) {
212c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // TS 22.030 sec 6.5.3.2
213c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // "Entry of any characters defined in the 3GPP TS 23.038 [8] Default Alphabet
214c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // (up to the maximum defined in 3GPP TS 24.080 [10]), followed by #SEND".
215c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
216e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            ret = new GsmMmiCode(phone, app);
21722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mPoundString = dialString;
218c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isTwoDigitShortCode(phone.getContext(), dialString)) {
219c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            //Is a country-specific exception to short codes as defined in TS 22.030, 6.5.3.2
220c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ret = null;
221c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isShortCode(dialString, phone)) {
222c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // this may be a short code, as defined in TS 22.030, 6.5.3.2
223e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            ret = new GsmMmiCode(phone, app);
22422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mDialingNumber = dialString;
225c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
226c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
227c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return ret;
228c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
229c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
230c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static GsmMmiCode
231c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    newNetworkInitiatedUssd (String ussdMessage,
232e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                                boolean isUssdRequest, GSMPhone phone, UiccCardApplication app) {
233c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        GsmMmiCode ret;
234c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
235e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        ret = new GsmMmiCode(phone, app);
236c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
23722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        ret.mMessage = ussdMessage;
23822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        ret.mIsUssdRequest = isUssdRequest;
239c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
240c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // If it's a request, set to PENDING so that it's cancelable.
241c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (isUssdRequest) {
24222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mIsPendingUSSD = true;
24322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mState = State.PENDING;
244c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
24522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mState = State.COMPLETE;
246c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
247c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
248c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return ret;
249c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
250c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
251e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    static GsmMmiCode newFromUssdUserInput(String ussdMessge,
252e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                                           GSMPhone phone,
253e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                                           UiccCardApplication app) {
254e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        GsmMmiCode ret = new GsmMmiCode(phone, app);
255c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
25622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        ret.mMessage = ussdMessge;
25722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        ret.mState = State.PENDING;
25822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        ret.mIsPendingUSSD = true;
259c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
260c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return ret;
261c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
262c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
263c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Private Class methods
264c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
265c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** make empty strings be null.
266c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  Regexp returns empty strings for empty groups
267c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
268c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static String
269c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    makeEmptyNull (String s) {
270c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (s != null && s.length() == 0) return null;
271c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
272c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return s;
273c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
274c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
275c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** returns true of the string is empty or null */
276c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static boolean
277c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isEmptyOrNull(CharSequence s) {
278c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return s == null || (s.length() == 0);
279c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
280c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
281c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
282c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static int
283c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    scToCallForwardReason(String sc) {
284c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sc == null) {
285c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            throw new RuntimeException ("invalid call forward sc");
286c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
287c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
288c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sc.equals(SC_CF_All)) {
289c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville           return CommandsInterface.CF_REASON_ALL;
290c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_CFU)) {
291c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CF_REASON_UNCONDITIONAL;
292c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_CFB)) {
293c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CF_REASON_BUSY;
294c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_CFNR)) {
295c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CF_REASON_NOT_REACHABLE;
296c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_CFNRy)) {
297c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CF_REASON_NO_REPLY;
298c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_CF_All_Conditional)) {
299c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville           return CommandsInterface.CF_REASON_ALL_CONDITIONAL;
300c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
301c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            throw new RuntimeException ("invalid call forward sc");
302c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
303c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
304c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
305c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static int
306c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    siToServiceClass(String si) {
307c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (si == null || si.length() == 0) {
308c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return  SERVICE_CLASS_NONE;
309c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
310c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // NumberFormatException should cause MMI fail
311c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            int serviceCode = Integer.parseInt(si, 10);
312c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
313c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            switch (serviceCode) {
314c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 10: return SERVICE_CLASS_SMS + SERVICE_CLASS_FAX  + SERVICE_CLASS_VOICE;
315c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 11: return SERVICE_CLASS_VOICE;
316c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 12: return SERVICE_CLASS_SMS + SERVICE_CLASS_FAX;
317c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 13: return SERVICE_CLASS_FAX;
318c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
319c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 16: return SERVICE_CLASS_SMS;
320c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
321c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 19: return SERVICE_CLASS_FAX + SERVICE_CLASS_VOICE;
322c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/*
323c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    Note for code 20:
324c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     From TS 22.030 Annex C:
325c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                "All GPRS bearer services" are not included in "All tele and bearer services"
326c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    and "All bearer services"."
327c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville....so SERVICE_CLASS_DATA, which (according to 27.007) includes GPRS
328c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville*/
329c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 20: return SERVICE_CLASS_DATA_ASYNC + SERVICE_CLASS_DATA_SYNC;
330c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
331c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 21: return SERVICE_CLASS_PAD + SERVICE_CLASS_DATA_ASYNC;
332c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 22: return SERVICE_CLASS_PACKET + SERVICE_CLASS_DATA_SYNC;
333c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 24: return SERVICE_CLASS_DATA_SYNC;
334c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 25: return SERVICE_CLASS_DATA_ASYNC;
335c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 26: return SERVICE_CLASS_DATA_SYNC + SERVICE_CLASS_VOICE;
336c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 99: return SERVICE_CLASS_PACKET;
337c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
338c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                default:
339c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException("unsupported MMI service code " + si);
340c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
341c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
342c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
343c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
344c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static int
345c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    siToTime (String si) {
346c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (si == null || si.length() == 0) {
347c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return 0;
348c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
349c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // NumberFormatException should cause MMI fail
350c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return Integer.parseInt(si, 10);
351c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
352c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
353c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
354c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static boolean
355c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isServiceCodeCallForwarding(String sc) {
356c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return sc != null &&
357c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                (sc.equals(SC_CFU)
358c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                || sc.equals(SC_CFB) || sc.equals(SC_CFNRy)
359c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                || sc.equals(SC_CFNR) || sc.equals(SC_CF_All)
360c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                || sc.equals(SC_CF_All_Conditional));
361c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
362c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
363c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static boolean
364c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isServiceCodeCallBarring(String sc) {
36521fe62acc2d11ace0410b2b6d83263a96081c092duho.ro        Resources resource = Resources.getSystem();
36621fe62acc2d11ace0410b2b6d83263a96081c092duho.ro        if (sc != null) {
36721fe62acc2d11ace0410b2b6d83263a96081c092duho.ro            String[] barringMMI = resource.getStringArray(
36821fe62acc2d11ace0410b2b6d83263a96081c092duho.ro                com.android.internal.R.array.config_callBarringMMI);
36921fe62acc2d11ace0410b2b6d83263a96081c092duho.ro            if (barringMMI != null) {
37021fe62acc2d11ace0410b2b6d83263a96081c092duho.ro                for (String match : barringMMI) {
37121fe62acc2d11ace0410b2b6d83263a96081c092duho.ro                    if (sc.equals(match)) return true;
37221fe62acc2d11ace0410b2b6d83263a96081c092duho.ro                }
37321fe62acc2d11ace0410b2b6d83263a96081c092duho.ro            }
37421fe62acc2d11ace0410b2b6d83263a96081c092duho.ro        }
37521fe62acc2d11ace0410b2b6d83263a96081c092duho.ro        return false;
376c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
377c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
378c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static String
379c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    scToBarringFacility(String sc) {
380c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sc == null) {
381c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            throw new RuntimeException ("invalid call barring sc");
382c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
383c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
384c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sc.equals(SC_BAOC)) {
385c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BAOC;
386c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BAOIC)) {
387c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BAOIC;
388c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BAOICxH)) {
389c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BAOICxH;
390c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BAIC)) {
391c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BAIC;
392c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BAICr)) {
393c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BAICr;
394c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BA_ALL)) {
395c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BA_ALL;
396c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BA_MO)) {
397c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BA_MO;
398c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BA_MT)) {
399c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BA_MT;
400c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
401c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            throw new RuntimeException ("invalid call barring sc");
402c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
403c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
404c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
405c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Constructor
406c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
407e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    GsmMmiCode (GSMPhone phone, UiccCardApplication app) {
408c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // The telephony unit-test cases may create GsmMmiCode's
409c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // in secondary threads
410c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        super(phone.getHandler().getLooper());
41122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mPhone = phone;
41222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mContext = phone.getContext();
413e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mUiccApplication = app;
414e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (app != null) {
415e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mIccRecords = app.getIccRecords();
416e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
417c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
418c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
419c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** MmiCode implementation
420c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
421cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
422c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public State
423c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    getState() {
42422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mState;
425c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
426c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
427cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
428c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public CharSequence
429c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    getMessage() {
43022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mMessage;
431c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
432c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
433c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // inherited javadoc suffices
434cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
435c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void
436c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    cancel() {
437c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Complete or failed cannot be cancelled
43822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mState == State.COMPLETE || mState == State.FAILED) {
439c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return;
440c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
441c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
44222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mState = State.CANCELLED;
443c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
44422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mIsPendingUSSD) {
445c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            /*
446c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             * There can only be one pending USSD session, so tell the radio to
447c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             * cancel it.
448c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             */
44922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mPhone.mCi.cancelPendingUssd(obtainMessage(EVENT_USSD_CANCEL_COMPLETE, this));
450c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
451c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            /*
452c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             * Don't call phone.onMMIDone here; wait for CANCEL_COMPLETE notice
453c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             * from RIL.
454c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             */
455c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
456c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // TODO in cases other than USSD, it would be nice to cancel
457c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // the pending radio operation. This requires RIL cancellation
458c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // support, which does not presently exist.
459c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
46022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mPhone.onMMIDone (this);
461c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
462c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
463c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
464c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
465cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
466c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public boolean isCancelable() {
467c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        /* Can only cancel pending USSD sessions. */
46822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mIsPendingUSSD;
469c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
470c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
471c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Instance Methods
472c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
473c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Does this dial string contain a structured or unstructured MMI code? */
474c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean
475c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isMMI() {
47622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mPoundString != null;
477c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
478c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
479c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /* Is this a 1 or 2 digit "short code" as defined in TS 22.030 sec 6.5.3.2? */
480c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean
481c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isShortCode() {
48222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mPoundString == null
48322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    && mDialingNumber != null && mDialingNumber.length() <= 2;
484c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
485c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
486c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
487c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static private boolean
488c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isTwoDigitShortCode(Context context, String dialString) {
489ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville        Rlog.d(LOG_TAG, "isTwoDigitShortCode");
490c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
491c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (dialString == null || dialString.length() != 2) return false;
492c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
493c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sTwoDigitNumberPattern == null) {
494c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            sTwoDigitNumberPattern = context.getResources().getStringArray(
495c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    com.android.internal.R.array.config_twoDigitNumberPattern);
496c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
497c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
498c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        for (String dialnumber : sTwoDigitNumberPattern) {
499ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.d(LOG_TAG, "Two Digit Number Pattern " + dialnumber);
500c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (dialString.equals(dialnumber)) {
501ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.d(LOG_TAG, "Two Digit Number Pattern -true");
502c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return true;
503c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
504c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
505ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville        Rlog.d(LOG_TAG, "Two Digit Number Pattern -false");
506c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return false;
507c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
508c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
509c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
510c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Helper function for newFromDialString. Returns true if dialString appears
511c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * to be a short code AND conditions are correct for it to be treated as
512c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * such.
513c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
514c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static private boolean isShortCode(String dialString, GSMPhone phone) {
515c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Refer to TS 22.030 Figure 3.5.3.2:
516c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (dialString == null) {
517c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return false;
518c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
519c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
520c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Illegal dial string characters will give a ZERO length.
521c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // At this point we do not want to crash as any application with
522c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // call privileges may send a non dial string.
523c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // It return false as when the dialString is equal to NULL.
524c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (dialString.length() == 0) {
525c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return false;
526c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
527c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
528c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (PhoneNumberUtils.isLocalEmergencyNumber(dialString, phone.getContext())) {
529c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return false;
530c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
531c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return isShortCodeUSSD(dialString, phone);
532c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
533c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
534c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
535c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
536c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Helper function for isShortCode. Returns true if dialString appears to be
537c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * a short code and it is a USSD structure
538c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
539c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * According to the 3PGG TS 22.030 specification Figure 3.5.3.2: A 1 or 2
540c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * digit "short code" is treated as USSD if it is entered while on a call or
541c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * does not satisfy the condition (exactly 2 digits && starts with '1'), there
542c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * are however exceptions to this rule (see below)
543c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
544c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Exception (1) to Call initiation is: If the user of the device is already in a call
545c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * and enters a Short String without any #-key at the end and the length of the Short String is
546c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * equal or less then the MAX_LENGTH_SHORT_CODE [constant that is equal to 2]
547c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
548c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * The phone shall initiate a USSD/SS commands.
549c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
550c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static private boolean isShortCodeUSSD(String dialString, GSMPhone phone) {
55110e574acd0992d22abce257b420d333f5a49e71dJeevaka Badrappan        if (dialString != null && dialString.length() <= MAX_LENGTH_SHORT_CODE) {
552c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (phone.isInCall()) {
55310e574acd0992d22abce257b420d333f5a49e71dJeevaka Badrappan                return true;
554c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
555c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
55610e574acd0992d22abce257b420d333f5a49e71dJeevaka Badrappan            if (dialString.length() != MAX_LENGTH_SHORT_CODE ||
55710e574acd0992d22abce257b420d333f5a49e71dJeevaka Badrappan                    dialString.charAt(0) != '1') {
55810e574acd0992d22abce257b420d333f5a49e71dJeevaka Badrappan                return true;
559c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
560c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
561c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return false;
562c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
563c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
564c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
565c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @return true if the Service Code is PIN/PIN2/PUK/PUK2-related
566c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
5673522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville    boolean isPinPukCommand() {
56822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mSc != null && (mSc.equals(SC_PIN) || mSc.equals(SC_PIN2)
56922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                              || mSc.equals(SC_PUK) || mSc.equals(SC_PUK2));
570c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     }
571c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
572c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
573c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * See TS 22.030 Annex B.
574c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * In temporary mode, to suppress CLIR for a single call, enter:
575c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *      " * 31 # [called number] SEND "
576c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  In temporary mode, to invoke CLIR for a single call enter:
577c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *       " # 31 # [called number] SEND "
578c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
579c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean
580c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isTemporaryModeCLIR() {
58122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mSc != null && mSc.equals(SC_CLIR) && mDialingNumber != null
582c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                && (isActivate() || isDeactivate());
583c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
584c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
585c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
586c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * returns CommandsInterface.CLIR_*
587c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * See also isTemporaryModeCLIR()
588c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
589c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    int
590c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    getCLIRMode() {
59122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mSc != null && mSc.equals(SC_CLIR)) {
592c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (isActivate()) {
593c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return CommandsInterface.CLIR_SUPPRESSION;
594c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else if (isDeactivate()) {
595c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return CommandsInterface.CLIR_INVOCATION;
596c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
597c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
598c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
599c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return CommandsInterface.CLIR_DEFAULT;
600c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
601c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
602c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean isActivate() {
60322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mAction != null && mAction.equals(ACTION_ACTIVATE);
604c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
605c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
606c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean isDeactivate() {
60722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mAction != null && mAction.equals(ACTION_DEACTIVATE);
608c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
609c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
610c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean isInterrogate() {
61122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mAction != null && mAction.equals(ACTION_INTERROGATE);
612c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
613c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
614c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean isRegister() {
61522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mAction != null && mAction.equals(ACTION_REGISTER);
616c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
617c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
618c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean isErasure() {
61922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mAction != null && mAction.equals(ACTION_ERASURE);
620c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
621c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
622c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
623c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Returns true if this is a USSD code that's been submitted to the
624c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * network...eg, after processCode() is called
625c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
626c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public boolean isPendingUSSD() {
62722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mIsPendingUSSD;
628c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
629c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
630cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
631c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public boolean isUssdRequest() {
63222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mIsUssdRequest;
633c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
634c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
635c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Process a MMI code or short code...anything that isn't a dialing number */
636c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    void
637c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    processCode () {
638c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        try {
639c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (isShortCode()) {
640ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.d(LOG_TAG, "isShortCode");
641c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // These just get treated as USSD.
64222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sendUssd(mDialingNumber);
64322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mDialingNumber != null) {
644c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // We should have no dialing numbers here
645c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                throw new RuntimeException ("Invalid or Unsupported MMI Code");
64622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc != null && mSc.equals(SC_CLIP)) {
647ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.d(LOG_TAG, "is CLIP");
648c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isInterrogate()) {
64922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.queryCLIP(
650c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            obtainMessage(EVENT_QUERY_COMPLETE, this));
651c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
652c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException ("Invalid or Unsupported MMI Code");
653c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
65422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc != null && mSc.equals(SC_CLIR)) {
655ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.d(LOG_TAG, "is CLIR");
656c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isActivate()) {
65722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.setCLIR(CommandsInterface.CLIR_INVOCATION,
658c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        obtainMessage(EVENT_SET_COMPLETE, this));
659c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (isDeactivate()) {
66022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.setCLIR(CommandsInterface.CLIR_SUPPRESSION,
661c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        obtainMessage(EVENT_SET_COMPLETE, this));
662c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (isInterrogate()) {
66322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.getCLIR(
664c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        obtainMessage(EVENT_GET_CLIR_COMPLETE, this));
665c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
666c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException ("Invalid or Unsupported MMI Code");
667c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
66822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (isServiceCodeCallForwarding(mSc)) {
669ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.d(LOG_TAG, "is CF");
670c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
67122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                String dialingNumber = mSia;
67222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                int serviceClass = siToServiceClass(mSib);
67322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                int reason = scToCallForwardReason(mSc);
67422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                int time = siToTime(mSic);
675c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
676c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isInterrogate()) {
67722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.queryCallForwardStatus(
678c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            reason, serviceClass,  dialingNumber,
679c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                obtainMessage(EVENT_QUERY_CF_COMPLETE, this));
680c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
681c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    int cfAction;
682c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
683c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    if (isActivate()) {
6845f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        // 3GPP TS 22.030 6.5.2
6855f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        // a call forwarding request with a single * would be
6865f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        // interpreted as registration if containing a forwarded-to
6875f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        // number, or an activation if not
6885f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        if (isEmptyOrNull(dialingNumber)) {
6895f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                            cfAction = CommandsInterface.CF_ACTION_ENABLE;
69022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            mIsCallFwdReg = false;
6915f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        } else {
6925f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                            cfAction = CommandsInterface.CF_ACTION_REGISTRATION;
69322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            mIsCallFwdReg = true;
6945f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        }
695c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else if (isDeactivate()) {
696c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        cfAction = CommandsInterface.CF_ACTION_DISABLE;
697c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else if (isRegister()) {
698c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        cfAction = CommandsInterface.CF_ACTION_REGISTRATION;
699c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else if (isErasure()) {
700c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        cfAction = CommandsInterface.CF_ACTION_ERASURE;
701c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else {
702c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        throw new RuntimeException ("invalid action");
703c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
704c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
705c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    int isSettingUnconditionalVoice =
706c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        (((reason == CommandsInterface.CF_REASON_UNCONDITIONAL) ||
707c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                (reason == CommandsInterface.CF_REASON_ALL)) &&
708c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                (((serviceClass & CommandsInterface.SERVICE_CLASS_VOICE) != 0) ||
709c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                 (serviceClass == CommandsInterface.SERVICE_CLASS_NONE))) ? 1 : 0;
710c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
711c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    int isEnableDesired =
712c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        ((cfAction == CommandsInterface.CF_ACTION_ENABLE) ||
713c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                (cfAction == CommandsInterface.CF_ACTION_REGISTRATION)) ? 1 : 0;
714c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
715ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                    Rlog.d(LOG_TAG, "is CF setCallForward");
71622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.setCallForward(cfAction, reason, serviceClass,
717c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            dialingNumber, time, obtainMessage(
718c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    EVENT_SET_CFF_COMPLETE,
719c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    isSettingUnconditionalVoice,
720c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    isEnableDesired, this));
721c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
72222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (isServiceCodeCallBarring(mSc)) {
723c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sia = password
724c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sib = basic service group
725c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
72622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                String password = mSia;
72722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                int serviceClass = siToServiceClass(mSib);
72822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                String facility = scToBarringFacility(mSc);
729c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
730c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isInterrogate()) {
73122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.queryFacilityLock(facility, password,
732c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            serviceClass, obtainMessage(EVENT_QUERY_COMPLETE, this));
733c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (isActivate() || isDeactivate()) {
73422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.setFacilityLock(facility, isActivate(), password,
735c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            serviceClass, obtainMessage(EVENT_SET_COMPLETE, this));
736c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
737c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException ("Invalid or Unsupported MMI Code");
738c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
739c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
74022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc != null && mSc.equals(SC_PWD)) {
741c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sia = fac
742c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sib = old pwd
743c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sic = new pwd
744c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // pwd = new pwd
745c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                String facility;
74622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                String oldPwd = mSib;
74722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                String newPwd = mSic;
748c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isActivate() || isRegister()) {
749c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // Even though ACTIVATE is acceptable, this is really termed a REGISTER
75022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mAction = ACTION_REGISTER;
751c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
75222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    if (mSia == null) {
753c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // If sc was not specified, treat it as BA_ALL.
754c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        facility = CommandsInterface.CB_FACILITY_BA_ALL;
755c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else {
75622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        facility = scToBarringFacility(mSia);
757c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
75822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    if (newPwd.equals(mPwd)) {
75922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        mPhone.mCi.changeBarringPassword(facility, oldPwd,
760c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                newPwd, obtainMessage(EVENT_SET_COMPLETE, this));
761c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else {
762c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // password mismatch; return error
763c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        handlePasswordError(com.android.internal.R.string.passwordIncorrect);
764c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
765c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
766c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException ("Invalid or Unsupported MMI Code");
767c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
768c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
76922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc != null && mSc.equals(SC_WAIT)) {
770c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sia = basic service group
77122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                int serviceClass = siToServiceClass(mSia);
772c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
773c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isActivate() || isDeactivate()) {
77422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.setCallWaiting(isActivate(), serviceClass,
775c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            obtainMessage(EVENT_SET_COMPLETE, this));
776c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (isInterrogate()) {
77722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.queryCallWaiting(serviceClass,
778c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            obtainMessage(EVENT_QUERY_COMPLETE, this));
779c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
780c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException ("Invalid or Unsupported MMI Code");
781c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
7823522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville            } else if (isPinPukCommand()) {
7833522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                // TODO: This is the same as the code in CmdaMmiCode.java,
7843522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                // MmiCode should be an abstract or base class and this and
7853522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                // other common variables and code should be promoted.
7863522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville
787c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sia = old PIN or PUK
788c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sib = new PIN
789c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sic = new PIN
79022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                String oldPinOrPuk = mSia;
7913522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                String newPinOrPuk = mSib;
7923522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                int pinLen = newPinOrPuk.length();
793c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isRegister()) {
7943522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    if (!newPinOrPuk.equals(mSic)) {
795c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // password mismatch; return error
796c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        handlePasswordError(com.android.internal.R.string.mismatchPin);
797c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else if (pinLen < 4 || pinLen > 8 ) {
798c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // invalid length
799c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        handlePasswordError(com.android.internal.R.string.invalidPin);
8003522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    } else if (mSc.equals(SC_PIN)
8013522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            && mUiccApplication != null
8023522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            && mUiccApplication.getState() == AppState.APPSTATE_PUK) {
803c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // Sim is puk-locked
804c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        handlePasswordError(com.android.internal.R.string.needPuk);
8053522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    } else if (mUiccApplication != null) {
8063522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        Rlog.d(LOG_TAG, "process mmi service code using UiccApp sc=" + mSc);
8073522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville
8083522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        // We have an app and the pre-checks are OK
80922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        if (mSc.equals(SC_PIN)) {
8103522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            mUiccApplication.changeIccLockPassword(oldPinOrPuk, newPinOrPuk,
811c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    obtainMessage(EVENT_SET_COMPLETE, this));
81222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        } else if (mSc.equals(SC_PIN2)) {
8133522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            mUiccApplication.changeIccFdnPassword(oldPinOrPuk, newPinOrPuk,
814c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    obtainMessage(EVENT_SET_COMPLETE, this));
81522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        } else if (mSc.equals(SC_PUK)) {
8163522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            mUiccApplication.supplyPuk(oldPinOrPuk, newPinOrPuk,
817c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    obtainMessage(EVENT_SET_COMPLETE, this));
81822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        } else if (mSc.equals(SC_PUK2)) {
8193522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            mUiccApplication.supplyPuk2(oldPinOrPuk, newPinOrPuk,
820c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    obtainMessage(EVENT_SET_COMPLETE, this));
8213522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        } else {
8223522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            throw new RuntimeException("uicc unsupported service code=" + mSc);
823c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        }
8243522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    } else {
8253522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        throw new RuntimeException("No application mUiccApplicaiton is null");
826c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
827c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
8283522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    throw new RuntimeException ("Ivalid register/action=" + mAction);
829c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
83022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mPoundString != null) {
83122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sendUssd(mPoundString);
832c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
833c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                throw new RuntimeException ("Invalid or Unsupported MMI Code");
834c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
835c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } catch (RuntimeException exc) {
83622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.FAILED;
83722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mMessage = mContext.getText(com.android.internal.R.string.mmiError);
83822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mPhone.onMMIDone(this);
839c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
840c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
841c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
842c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void handlePasswordError(int res) {
84322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mState = State.FAILED;
844c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder(getScString());
845c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("\n");
84622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        sb.append(mContext.getText(res));
84722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mMessage = sb;
84822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mPhone.onMMIDone(this);
849c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
850c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
851c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
852c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Called from GSMPhone
853c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
854c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * An unsolicited USSD NOTIFY or REQUEST has come in matching
855c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * up with this pending USSD request
856c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
857c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Note: If REQUEST, this exchange is complete, but the session remains
858c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *       active (ie, the network expects user input).
859c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
860c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    void
861c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    onUssdFinished(String ussdMessage, boolean isUssdRequest) {
86222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mState == State.PENDING) {
863c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (ussdMessage == null) {
86422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mMessage = mContext.getText(com.android.internal.R.string.mmiComplete);
865c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
86622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mMessage = ussdMessage;
867c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
86822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mIsUssdRequest = isUssdRequest;
869c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // If it's a request, leave it PENDING so that it's cancelable.
870c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (!isUssdRequest) {
87122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mState = State.COMPLETE;
872c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
873c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
87422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mPhone.onMMIDone(this);
875c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
876c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
877c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
878c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
879c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Called from GSMPhone
880c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
881c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * The radio has reset, and this is still pending
882c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
883c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
884c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    void
885c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    onUssdFinishedError() {
88622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mState == State.PENDING) {
88722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.FAILED;
88822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mMessage = mContext.getText(com.android.internal.R.string.mmiError);
889c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
89022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mPhone.onMMIDone(this);
891c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
892c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
893c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
894c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    void sendUssd(String ussdMessage) {
895c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Treat this as a USSD string
89622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mIsPendingUSSD = true;
897c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
898c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Note that unlike most everything else, the USSD complete
899c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // response does not complete this MMI code...we wait for
900c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // an unsolicited USSD "Notify" or "Request".
901c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // The matching up of this is done in GSMPhone.
902c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
90322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mPhone.mCi.sendUSSD(ussdMessage,
904c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            obtainMessage(EVENT_USSD_COMPLETE, this));
905c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
906c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
907c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Called from GSMPhone.handleMessage; not a Handler subclass */
908cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
909c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void
910c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    handleMessage (Message msg) {
911c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        AsyncResult ar;
912c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
913c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        switch (msg.what) {
914c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_SET_COMPLETE:
915c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
916c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
9173522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                onSetComplete(msg, ar);
918c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
919c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
920c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_SET_CFF_COMPLETE:
921c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
922c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
923c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                /*
924c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                * msg.arg1 = 1 means to set unconditional voice call forwarding
925c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                * msg.arg2 = 1 means to enable voice call forwarding
926c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                */
927c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if ((ar.exception == null) && (msg.arg1 == 1)) {
928c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    boolean cffEnabled = (msg.arg2 == 1);
929e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    if (mIccRecords != null) {
93031ae682ff511ddde4073c3f94eff15da2f7fade6Wink Saville                        mIccRecords.setVoiceCallForwardingFlag(1, cffEnabled, mDialingNumber);
931bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                    }
932c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
933c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
9343522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                onSetComplete(msg, ar);
935c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
936c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
937c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_GET_CLIR_COMPLETE:
938c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
939c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                onGetClirComplete(ar);
940c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
941c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
942c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_QUERY_CF_COMPLETE:
943c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
944c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                onQueryCfComplete(ar);
945c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
946c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
947c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_QUERY_COMPLETE:
948c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
949c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                onQueryComplete(ar);
950c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
951c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
952c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_USSD_COMPLETE:
953c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
954c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
955c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (ar.exception != null) {
95622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mState = State.FAILED;
95722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mMessage = getErrorMessage(ar);
958c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
95922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.onMMIDone(this);
960c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
961c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
962c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // Note that unlike most everything else, the USSD complete
963c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // response does not complete this MMI code...we wait for
964c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // an unsolicited USSD "Notify" or "Request".
965c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // The matching up of this is done in GSMPhone.
966c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
967c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
968c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
969c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_USSD_CANCEL_COMPLETE:
97022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mPhone.onMMIDone(this);
971c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
972c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
973c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
974c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Private instance methods
975c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
976c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence getErrorMessage(AsyncResult ar) {
977c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
978c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (ar.exception instanceof CommandException) {
979c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            CommandException.Error err = ((CommandException)(ar.exception)).getCommandError();
980c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (err == CommandException.Error.FDN_CHECK_FAILURE) {
981ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.i(LOG_TAG, "FDN_CHECK_FAILURE");
98222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.mmiFdnError);
983c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
984c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
985c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
98622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mContext.getText(com.android.internal.R.string.mmiError);
987c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
988c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
989c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence getScString() {
99022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mSc != null) {
99122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            if (isServiceCodeCallBarring(mSc)) {
99222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.BaMmi);
99322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (isServiceCodeCallForwarding(mSc)) {
99422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.CfMmi);
99522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc.equals(SC_CLIP)) {
99622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.ClipMmi);
99722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc.equals(SC_CLIR)) {
99822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.ClirMmi);
99922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc.equals(SC_PWD)) {
100022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.PwdMmi);
100122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc.equals(SC_WAIT)) {
100222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.CwMmi);
10033522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville            } else if (isPinPukCommand()) {
100422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.PinMmi);
1005c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1006c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1007c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1008c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return "";
1009c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1010c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1011c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void
10123522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville    onSetComplete(Message msg, AsyncResult ar){
1013c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder(getScString());
1014c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("\n");
1015c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1016c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (ar.exception != null) {
101722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.FAILED;
1018c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (ar.exception instanceof CommandException) {
1019c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                CommandException.Error err = ((CommandException)(ar.exception)).getCommandError();
1020c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (err == CommandException.Error.PASSWORD_INCORRECT) {
10213522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    if (isPinPukCommand()) {
1022c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // look specifically for the PUK commands and adjust
1023c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // the message accordingly.
102422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        if (mSc.equals(SC_PUK) || mSc.equals(SC_PUK2)) {
102522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1026c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.badPuk));
1027c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        } else {
102822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1029c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.badPin));
1030c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        }
10313522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        // Get the No. of retries remaining to unlock PUK/PUK2
10323522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        int attemptsRemaining = msg.arg1;
10333522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        if (attemptsRemaining >= 0) {
10343522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            sb.append(mContext.getResources().getQuantityString(
10353522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                                    com.android.internal.R.plurals.pinpuk_attempts,
10363522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                                    attemptsRemaining, attemptsRemaining));
10373522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        }
1038c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else {
103922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        sb.append(mContext.getText(
1040c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                com.android.internal.R.string.passwordIncorrect));
1041c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
1042c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (err == CommandException.Error.SIM_PUK2) {
104322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(
1044c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            com.android.internal.R.string.badPin));
1045c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    sb.append("\n");
104622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(
1047c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            com.android.internal.R.string.needPuk2));
10483522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                } else if (err == CommandException.Error.REQUEST_NOT_SUPPORTED) {
10493522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    if (mSc.equals(SC_PIN)) {
10503522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        sb.append(mContext.getText(com.android.internal.R.string.enablePin));
10513522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    }
1052c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (err == CommandException.Error.FDN_CHECK_FAILURE) {
1053ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                    Rlog.i(LOG_TAG, "FDN_CHECK_FAILURE");
105422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(com.android.internal.R.string.mmiFdnError));
1055c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
105622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(
1057c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            com.android.internal.R.string.mmiError));
1058c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
1059c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
106022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sb.append(mContext.getText(
1061c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.mmiError));
1062c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1063c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isActivate()) {
106422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.COMPLETE;
106522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            if (mIsCallFwdReg) {
106622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sb.append(mContext.getText(
10675f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        com.android.internal.R.string.serviceRegistered));
10685f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li            } else {
106922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sb.append(mContext.getText(
10705f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        com.android.internal.R.string.serviceEnabled));
10715f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li            }
1072c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // Record CLIR setting
107322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            if (mSc.equals(SC_CLIR)) {
107422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mPhone.saveClirSetting(CommandsInterface.CLIR_INVOCATION);
1075c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1076c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isDeactivate()) {
107722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.COMPLETE;
107822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            sb.append(mContext.getText(
1079c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    com.android.internal.R.string.serviceDisabled));
1080c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // Record CLIR setting
108122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            if (mSc.equals(SC_CLIR)) {
108222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mPhone.saveClirSetting(CommandsInterface.CLIR_SUPPRESSION);
1083c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1084c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isRegister()) {
108522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.COMPLETE;
108622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            sb.append(mContext.getText(
1087c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    com.android.internal.R.string.serviceRegistered));
1088c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isErasure()) {
108922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.COMPLETE;
109022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            sb.append(mContext.getText(
1091c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    com.android.internal.R.string.serviceErased));
1092c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
109322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.FAILED;
109422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            sb.append(mContext.getText(
1095c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    com.android.internal.R.string.mmiError));
1096c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1097c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
109822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mMessage = sb;
109922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mPhone.onMMIDone(this);
1100c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1101c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1102c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void
1103c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    onGetClirComplete(AsyncResult ar) {
1104c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder(getScString());
1105c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("\n");
1106c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1107c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (ar.exception != null) {
110822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.FAILED;
1109c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            sb.append(getErrorMessage(ar));
1110c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
1111c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            int clirArgs[];
1112c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1113c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            clirArgs = (int[])ar.result;
1114c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1115c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // the 'm' parameter from TS 27.007 7.7
1116c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            switch (clirArgs[1]) {
1117c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 0: // CLIR not provisioned
111822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(
1119c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                com.android.internal.R.string.serviceNotProvisioned));
112022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mState = State.COMPLETE;
1121c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1122c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1123c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 1: // CLIR provisioned in permanent mode
112422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(
1125c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                com.android.internal.R.string.CLIRPermanent));
112622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mState = State.COMPLETE;
1127c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1128c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1129c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 2: // unknown (e.g. no network, etc.)
113022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(
1131c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                com.android.internal.R.string.mmiError));
113222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mState = State.FAILED;
1133c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1134c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1135c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 3: // CLIR temporary mode presentation restricted
1136c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1137c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // the 'n' parameter from TS 27.007 7.7
1138c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    switch (clirArgs[0]) {
1139c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        default:
1140c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 0: // Default
114122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1142c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOnNextCallOn));
1143c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1144c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 1: // CLIR invocation
114522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1146c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOnNextCallOn));
1147c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1148c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 2: // CLIR suppression
114922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1150c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOnNextCallOff));
1151c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1152c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
115322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mState = State.COMPLETE;
1154c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1155c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1156c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 4: // CLIR temporary mode presentation allowed
1157c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // the 'n' parameter from TS 27.007 7.7
1158c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    switch (clirArgs[0]) {
1159c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        default:
1160c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 0: // Default
116122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1162c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOffNextCallOff));
1163c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1164c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 1: // CLIR invocation
116522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1166c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOffNextCallOn));
1167c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1168c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 2: // CLIR suppression
116922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1170c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOffNextCallOff));
1171c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1172c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
1173c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
117422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mState = State.COMPLETE;
1175c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1176c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1177c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1178c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
117922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mMessage = sb;
118022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mPhone.onMMIDone(this);
1181c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1182c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1183c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
1184c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param serviceClass 1 bit of the service class bit vectory
1185c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @return String to be used for call forward query MMI response text.
1186c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *        Returns null if unrecognized
1187c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
1188c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1189c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence
1190c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    serviceClassToCFString (int serviceClass) {
1191c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        switch (serviceClass) {
1192c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_VOICE:
119322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassVoice);
1194c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_DATA:
119522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassData);
1196c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_FAX:
119722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassFAX);
1198c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_SMS:
119922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassSMS);
1200c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_DATA_SYNC:
120122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassDataSync);
1202c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_DATA_ASYNC:
120322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassDataAsync);
1204c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_PACKET:
120522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassPacket);
1206c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_PAD:
120722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassPAD);
1208c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            default:
1209c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return null;
1210c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1211c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1212c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1213c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1214c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** one CallForwardInfo + serviceClassMask -> one line of text */
1215c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence
1216c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    makeCFQueryResultMessage(CallForwardInfo info, int serviceClassMask) {
1217c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        CharSequence template;
1218c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        String sources[] = {"{0}", "{1}", "{2}"};
1219c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        CharSequence destinations[] = new CharSequence[3];
1220c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        boolean needTimeTemplate;
1221c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1222c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // CF_REASON_NO_REPLY also has a time value associated with
1223c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // it. All others don't.
1224c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1225c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        needTimeTemplate =
1226c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            (info.reason == CommandsInterface.CF_REASON_NO_REPLY);
1227c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1228c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (info.status == 1) {
1229c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (needTimeTemplate) {
123022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                template = mContext.getText(
1231c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.cfTemplateForwardedTime);
1232c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
123322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                template = mContext.getText(
1234c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.cfTemplateForwarded);
1235c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1236c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (info.status == 0 && isEmptyOrNull(info.number)) {
123722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            template = mContext.getText(
1238c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.cfTemplateNotForwarded);
1239c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else { /* (info.status == 0) && !isEmptyOrNull(info.number) */
1240c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // A call forward record that is not active but contains
1241c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // a phone number is considered "registered"
1242c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1243c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (needTimeTemplate) {
124422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                template = mContext.getText(
1245c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.cfTemplateRegisteredTime);
1246c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
124722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                template = mContext.getText(
1248c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.cfTemplateRegistered);
1249c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1250c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1251c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1252c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // In the template (from strings.xmls)
1253c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        //         {0} is one of "bearerServiceCode*"
1254c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        //        {1} is dialing number
1255c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        //      {2} is time in seconds
1256c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1257c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        destinations[0] = serviceClassToCFString(info.serviceClass & serviceClassMask);
1258c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        destinations[1] = PhoneNumberUtils.stringFromStringAndTOA(info.number, info.toa);
1259c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        destinations[2] = Integer.toString(info.timeSeconds);
1260c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1261c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (info.reason == CommandsInterface.CF_REASON_UNCONDITIONAL &&
1262c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                (info.serviceClass & serviceClassMask)
1263c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        == CommandsInterface.SERVICE_CLASS_VOICE) {
1264c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            boolean cffEnabled = (info.status == 1);
1265e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (mIccRecords != null) {
126631ae682ff511ddde4073c3f94eff15da2f7fade6Wink Saville                mIccRecords.setVoiceCallForwardingFlag(1, cffEnabled, info.number);
1267bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka            }
1268c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1269c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1270c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return TextUtils.replace(template, sources, destinations);
1271c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1272c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1273c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1274c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void
1275c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    onQueryCfComplete(AsyncResult ar) {
1276c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder(getScString());
1277c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("\n");
1278c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1279c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (ar.exception != null) {
128022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.FAILED;
1281c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            sb.append(getErrorMessage(ar));
1282c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
1283c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            CallForwardInfo infos[];
1284c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1285c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            infos = (CallForwardInfo[]) ar.result;
1286c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1287c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (infos.length == 0) {
1288c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // Assume the default is not active
128922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sb.append(mContext.getText(com.android.internal.R.string.serviceDisabled));
1290c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1291c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // Set unconditional CFF in SIM to false
1292e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if (mIccRecords != null) {
129331ae682ff511ddde4073c3f94eff15da2f7fade6Wink Saville                    mIccRecords.setVoiceCallForwardingFlag(1, false, null);
1294bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                }
1295c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
1296c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1297c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                SpannableStringBuilder tb = new SpannableStringBuilder();
1298c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1299c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // Each bit in the service class gets its own result line
1300c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // The service classes may be split up over multiple
1301c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // CallForwardInfos. So, for each service class, find out
1302c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // which CallForwardInfo represents it and then build
1303c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // the response text based on that
1304c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1305c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                for (int serviceClassMask = 1
1306c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            ; serviceClassMask <= SERVICE_CLASS_MAX
1307c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            ; serviceClassMask <<= 1
1308c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ) {
1309c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    for (int i = 0, s = infos.length; i < s ; i++) {
1310c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        if ((serviceClassMask & infos[i].serviceClass) != 0) {
1311c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            tb.append(makeCFQueryResultMessage(infos[i],
1312c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                            serviceClassMask));
1313c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            tb.append("\n");
1314c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        }
1315c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
1316c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
1317c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sb.append(tb);
1318c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1319c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
132022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.COMPLETE;
1321c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1322c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
132322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mMessage = sb;
132422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mPhone.onMMIDone(this);
1325c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1326c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1327c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1328c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void
1329c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    onQueryComplete(AsyncResult ar) {
1330c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder(getScString());
1331c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("\n");
1332c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1333c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (ar.exception != null) {
133422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.FAILED;
1335c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            sb.append(getErrorMessage(ar));
1336c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
1337c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            int[] ints = (int[])ar.result;
1338c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1339c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (ints.length != 0) {
1340c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (ints[0] == 0) {
134122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(com.android.internal.R.string.serviceDisabled));
134222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                } else if (mSc.equals(SC_WAIT)) {
1343c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // Call Waiting includes additional data in the response.
1344c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    sb.append(createQueryCallWaitingResultMessage(ints[1]));
134522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                } else if (isServiceCodeCallBarring(mSc)) {
1346c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // ints[0] for Call Barring is a bit vector of services
1347c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    sb.append(createQueryCallBarringResultMessage(ints[0]));
1348c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (ints[0] == 1) {
1349c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // for all other services, treat it as a boolean
135022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(com.android.internal.R.string.serviceEnabled));
1351c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
135222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(com.android.internal.R.string.mmiError));
1353c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
1354c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
135522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sb.append(mContext.getText(com.android.internal.R.string.mmiError));
1356c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
135722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.COMPLETE;
1358c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1359c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
136022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mMessage = sb;
136122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mPhone.onMMIDone(this);
1362c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1363c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1364c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence
1365c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    createQueryCallWaitingResultMessage(int serviceClass) {
1366c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb =
136722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                new StringBuilder(mContext.getText(com.android.internal.R.string.serviceEnabledFor));
1368c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1369c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        for (int classMask = 1
1370c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    ; classMask <= SERVICE_CLASS_MAX
1371c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    ; classMask <<= 1
1372c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        ) {
1373c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if ((classMask & serviceClass) != 0) {
1374c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sb.append("\n");
1375c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sb.append(serviceClassToCFString(classMask & serviceClass));
1376c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1377c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1378c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return sb;
1379c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1380c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence
1381c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    createQueryCallBarringResultMessage(int serviceClass)
1382c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    {
138322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        StringBuilder sb = new StringBuilder(mContext.getText(com.android.internal.R.string.serviceEnabledFor));
1384c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1385c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        for (int classMask = 1
1386c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    ; classMask <= SERVICE_CLASS_MAX
1387c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    ; classMask <<= 1
1388c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        ) {
1389c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if ((classMask & serviceClass) != 0) {
1390c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sb.append("\n");
1391c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sb.append(serviceClassToCFString(classMask & serviceClass));
1392c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1393c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1394c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return sb;
1395c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1396c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1397c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /***
1398c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * TODO: It would be nice to have a method here that can take in a dialstring and
1399c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * figure out if there is an MMI code embedded within it.  This code would replace
1400c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * some of the string parsing functionality in the Phone App's
1401c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * SpecialCharSequenceMgr class.
1402c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
1403c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1404c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
1405c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public String toString() {
1406c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder("GsmMmiCode {");
1407c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1408c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("State=" + getState());
140922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mAction != null) sb.append(" action=" + mAction);
141022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mSc != null) sb.append(" sc=" + mSc);
141122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mSia != null) sb.append(" sia=" + mSia);
141222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mSib != null) sb.append(" sib=" + mSib);
141322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mSic != null) sb.append(" sic=" + mSic);
141422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mPoundString != null) sb.append(" poundString=" + mPoundString);
141522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mDialingNumber != null) sb.append(" dialingNumber=" + mDialingNumber);
141622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mPwd != null) sb.append(" pwd=" + mPwd);
1417c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("}");
1418c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return sb.toString();
1419c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1420c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville}
1421