GsmMmiCode.java revision cbaa45bbf2cab852b6c9c3a887e9f803d4e857ea
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;
20c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.*;
21d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccRecords;
22d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.UiccCardApplication;
23d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState;
24c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
25c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.os.*;
26c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.telephony.PhoneNumberUtils;
27c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.text.SpannableStringBuilder;
28c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.text.TextUtils;
29ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Savilleimport android.telephony.Rlog;
30c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
31c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport static com.android.internal.telephony.CommandsInterface.*;
32c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
33c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport java.util.regex.Pattern;
34c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport java.util.regex.Matcher;
35c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
36c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/**
37c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * The motto for this file is:
38c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
39c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * "NOTE:    By using the # as a separator, most cases are expected to be unambiguous."
40c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *   -- TS 22.030 6.5.2
41c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
42c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * {@hide}
43c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
44c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */
45c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savillepublic final class GsmMmiCode extends Handler implements MmiCode {
46cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    static final String LOG_TAG = "GsmMmiCode";
47c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
48c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Constants
49c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
50c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Max Size of the Short Code (aka Short String from TS 22.030 6.5.2)
51c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MAX_LENGTH_SHORT_CODE = 2;
52c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
53c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // TS 22.030 6.5.2 Every Short String USSD command will end with #-key
54c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // (known as #-String)
55c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final char END_OF_USSD_COMMAND = '#';
56c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
57c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // From TS 22.030 6.5.2
58c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String ACTION_ACTIVATE = "*";
59c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String ACTION_DEACTIVATE = "#";
60c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String ACTION_INTERROGATE = "*#";
61c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String ACTION_REGISTER = "**";
62c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String ACTION_ERASURE = "##";
63c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
64c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Supp Service codes from TS 22.030 Annex B
65c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
66c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //Called line presentation
67c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CLIP    = "30";
68c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CLIR    = "31";
69c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
70c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Call Forwarding
71c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CFU     = "21";
72c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CFB     = "67";
73c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CFNRy   = "61";
74c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CFNR    = "62";
75c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
76c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CF_All = "002";
77c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CF_All_Conditional = "004";
78c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
79c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Call Waiting
80c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_WAIT     = "43";
81c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
82c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Call Barring
83c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BAOC         = "33";
84c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BAOIC        = "331";
85c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BAOICxH      = "332";
86c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BAIC         = "35";
87c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BAICr        = "351";
88c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
89c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BA_ALL       = "330";
90c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BA_MO        = "333";
91c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BA_MT        = "353";
92c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
93c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Supp Service Password registration
94c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_PWD          = "03";
95c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
96c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // PIN/PIN2/PUK/PUK2
97c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_PIN          = "04";
98c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_PIN2         = "042";
99c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_PUK          = "05";
100c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_PUK2         = "052";
101c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
102c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Event Constants
103c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
104c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_SET_COMPLETE         = 1;
105c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_GET_CLIR_COMPLETE    = 2;
106c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_QUERY_CF_COMPLETE    = 3;
107c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_USSD_COMPLETE        = 4;
108c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_QUERY_COMPLETE       = 5;
109c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_SET_CFF_COMPLETE     = 6;
110c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_USSD_CANCEL_COMPLETE = 7;
111c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
112c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Instance Variables
113c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
114c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    GSMPhone phone;
115c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    Context context;
116e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    UiccCardApplication mUiccApplication;
117e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    IccRecords mIccRecords;
118c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
119c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    String action;              // One of ACTION_*
120c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    String sc;                  // Service Code
121c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    String sia, sib, sic;       // Service Info a,b,c
122c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    String poundString;         // Entire MMI string up to and including #
123c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    String dialingNumber;
124c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    String pwd;                 // For password registration
125c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
126c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Set to true in processCode, not at newFromDialString time */
127c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private boolean isPendingUSSD;
128c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
129c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private boolean isUssdRequest;
130c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1315f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li    private boolean isCallFwdReg;
132c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    State state = State.PENDING;
133c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    CharSequence message;
134c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
135c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Class Variables
136c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
137c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
138c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // See TS 22.030 6.5.2 "Structure of the MMI"
139c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
140c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static Pattern sPatternSuppService = Pattern.compile(
1419225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang        "((\\*|#|\\*#|\\*\\*|##)(\\d{2,3})(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*))?)?)?)?#)(.*)");
142c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/*       1  2                    3          4  5       6   7         8    9     10  11             12
143c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
144c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         1 = Full string up to and including #
145c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         2 = action (activation/interrogation/registration/erasure)
146c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         3 = service code
147c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         5 = SIA
148c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         7 = SIB
149c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         9 = SIC
1509225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang         10 = dialing number
151c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville*/
152c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
153c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_POUND_STRING = 1;
154c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
155c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_ACTION = 2;
156c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        //(activation/interrogation/registration/erasure)
157c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
158c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_SERVICE_CODE = 3;
159c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_SIA = 5;
160c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_SIB = 7;
161c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_SIC = 9;
162c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_PWD_CONFIRM = 11;
163c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_DIALING_NUMBER = 12;
164c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static private String[] sTwoDigitNumberPattern;
165c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
166c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Public Class methods
167c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
168c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
169c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Some dial strings in GSM are defined to do non-call setup
170c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * things, such as modify or query supplementary service settings (eg, call
171c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * forwarding). These are generally referred to as "MMI codes".
172c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * We look to see if the dial string contains a valid MMI code (potentially
173c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * with a dial string at the end as well) and return info here.
174c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
175c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * If the dial string contains no MMI code, we return an instance with
176c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * only "dialingNumber" set
177c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
178c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Please see flow chart in TS 22.030 6.5.3.2
179c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
180c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
181c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static GsmMmiCode
182e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    newFromDialString(String dialString, GSMPhone phone, UiccCardApplication app) {
183c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        Matcher m;
184c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        GsmMmiCode ret = null;
185c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
186c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        m = sPatternSuppService.matcher(dialString);
187c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
188c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Is this formatted like a standard supplementary service code?
189c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (m.matches()) {
190e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            ret = new GsmMmiCode(phone, app);
191c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ret.poundString = makeEmptyNull(m.group(MATCH_GROUP_POUND_STRING));
192c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ret.action = makeEmptyNull(m.group(MATCH_GROUP_ACTION));
193c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ret.sc = makeEmptyNull(m.group(MATCH_GROUP_SERVICE_CODE));
194c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ret.sia = makeEmptyNull(m.group(MATCH_GROUP_SIA));
195c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ret.sib = makeEmptyNull(m.group(MATCH_GROUP_SIB));
196c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ret.sic = makeEmptyNull(m.group(MATCH_GROUP_SIC));
197c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ret.pwd = makeEmptyNull(m.group(MATCH_GROUP_PWD_CONFIRM));
198c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ret.dialingNumber = makeEmptyNull(m.group(MATCH_GROUP_DIALING_NUMBER));
1999225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            // According to TS 22.030 6.5.2 "Structure of the MMI",
2009225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            // the dialing number should not ending with #.
2019225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            // The dialing number ending # is treated as unique USSD,
2029225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            // eg, *400#16 digit number# to recharge the prepaid card
2039225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            // in India operator(Mumbai MTNL)
2049225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            if(ret.dialingNumber != null &&
2059225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang                    ret.dialingNumber.endsWith("#") &&
2069225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang                    dialString.endsWith("#")){
2079225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang                ret = new GsmMmiCode(phone, app);
2089225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang                ret.poundString = dialString;
2099225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            }
210c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (dialString.endsWith("#")) {
211c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // TS 22.030 sec 6.5.3.2
212c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // "Entry of any characters defined in the 3GPP TS 23.038 [8] Default Alphabet
213c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // (up to the maximum defined in 3GPP TS 24.080 [10]), followed by #SEND".
214c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
215e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            ret = new GsmMmiCode(phone, app);
216c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ret.poundString = dialString;
217c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isTwoDigitShortCode(phone.getContext(), dialString)) {
218c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            //Is a country-specific exception to short codes as defined in TS 22.030, 6.5.3.2
219c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ret = null;
220c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isShortCode(dialString, phone)) {
221c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // this may be a short code, as defined in TS 22.030, 6.5.3.2
222e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            ret = new GsmMmiCode(phone, app);
223c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ret.dialingNumber = dialString;
224c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
225c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
226c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return ret;
227c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
228c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
229c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static GsmMmiCode
230c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    newNetworkInitiatedUssd (String ussdMessage,
231e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                                boolean isUssdRequest, GSMPhone phone, UiccCardApplication app) {
232c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        GsmMmiCode ret;
233c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
234e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        ret = new GsmMmiCode(phone, app);
235c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
236c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        ret.message = ussdMessage;
237c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        ret.isUssdRequest = isUssdRequest;
238c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
239c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // If it's a request, set to PENDING so that it's cancelable.
240c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (isUssdRequest) {
241c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ret.isPendingUSSD = true;
242c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ret.state = State.PENDING;
243c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
244c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ret.state = State.COMPLETE;
245c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
246c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
247c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return ret;
248c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
249c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
250e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    static GsmMmiCode newFromUssdUserInput(String ussdMessge,
251e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                                           GSMPhone phone,
252e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                                           UiccCardApplication app) {
253e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        GsmMmiCode ret = new GsmMmiCode(phone, app);
254c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
255c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        ret.message = ussdMessge;
256c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        ret.state = State.PENDING;
257c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        ret.isPendingUSSD = true;
258c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
259c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return ret;
260c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
261c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
262c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Private Class methods
263c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
264c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** make empty strings be null.
265c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  Regexp returns empty strings for empty groups
266c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
267c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static String
268c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    makeEmptyNull (String s) {
269c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (s != null && s.length() == 0) return null;
270c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
271c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return s;
272c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
273c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
274c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** returns true of the string is empty or null */
275c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static boolean
276c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isEmptyOrNull(CharSequence s) {
277c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return s == null || (s.length() == 0);
278c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
279c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
280c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
281c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static int
282c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    scToCallForwardReason(String sc) {
283c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sc == null) {
284c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            throw new RuntimeException ("invalid call forward sc");
285c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
286c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
287c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sc.equals(SC_CF_All)) {
288c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville           return CommandsInterface.CF_REASON_ALL;
289c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_CFU)) {
290c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CF_REASON_UNCONDITIONAL;
291c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_CFB)) {
292c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CF_REASON_BUSY;
293c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_CFNR)) {
294c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CF_REASON_NOT_REACHABLE;
295c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_CFNRy)) {
296c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CF_REASON_NO_REPLY;
297c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_CF_All_Conditional)) {
298c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville           return CommandsInterface.CF_REASON_ALL_CONDITIONAL;
299c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
300c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            throw new RuntimeException ("invalid call forward sc");
301c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
302c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
303c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
304c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static int
305c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    siToServiceClass(String si) {
306c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (si == null || si.length() == 0) {
307c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return  SERVICE_CLASS_NONE;
308c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
309c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // NumberFormatException should cause MMI fail
310c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            int serviceCode = Integer.parseInt(si, 10);
311c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
312c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            switch (serviceCode) {
313c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 10: return SERVICE_CLASS_SMS + SERVICE_CLASS_FAX  + SERVICE_CLASS_VOICE;
314c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 11: return SERVICE_CLASS_VOICE;
315c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 12: return SERVICE_CLASS_SMS + SERVICE_CLASS_FAX;
316c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 13: return SERVICE_CLASS_FAX;
317c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
318c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 16: return SERVICE_CLASS_SMS;
319c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
320c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 19: return SERVICE_CLASS_FAX + SERVICE_CLASS_VOICE;
321c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/*
322c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    Note for code 20:
323c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     From TS 22.030 Annex C:
324c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                "All GPRS bearer services" are not included in "All tele and bearer services"
325c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    and "All bearer services"."
326c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville....so SERVICE_CLASS_DATA, which (according to 27.007) includes GPRS
327c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville*/
328c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 20: return SERVICE_CLASS_DATA_ASYNC + SERVICE_CLASS_DATA_SYNC;
329c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
330c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 21: return SERVICE_CLASS_PAD + SERVICE_CLASS_DATA_ASYNC;
331c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 22: return SERVICE_CLASS_PACKET + SERVICE_CLASS_DATA_SYNC;
332c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 24: return SERVICE_CLASS_DATA_SYNC;
333c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 25: return SERVICE_CLASS_DATA_ASYNC;
334c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 26: return SERVICE_CLASS_DATA_SYNC + SERVICE_CLASS_VOICE;
335c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 99: return SERVICE_CLASS_PACKET;
336c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
337c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                default:
338c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException("unsupported MMI service code " + si);
339c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
340c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
341c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
342c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
343c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static int
344c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    siToTime (String si) {
345c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (si == null || si.length() == 0) {
346c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return 0;
347c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
348c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // NumberFormatException should cause MMI fail
349c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return Integer.parseInt(si, 10);
350c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
351c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
352c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
353c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static boolean
354c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isServiceCodeCallForwarding(String sc) {
355c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return sc != null &&
356c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                (sc.equals(SC_CFU)
357c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                || sc.equals(SC_CFB) || sc.equals(SC_CFNRy)
358c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                || sc.equals(SC_CFNR) || sc.equals(SC_CF_All)
359c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                || sc.equals(SC_CF_All_Conditional));
360c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
361c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
362c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static boolean
363c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isServiceCodeCallBarring(String sc) {
364c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return sc != null &&
365c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                (sc.equals(SC_BAOC)
366c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                || sc.equals(SC_BAOIC)
367c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                || sc.equals(SC_BAOICxH)
368c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                || sc.equals(SC_BAIC)
369c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                || sc.equals(SC_BAICr)
370c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                || sc.equals(SC_BA_ALL)
371c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                || sc.equals(SC_BA_MO)
372c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                || sc.equals(SC_BA_MT));
373c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
374c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
375c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static String
376c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    scToBarringFacility(String sc) {
377c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sc == null) {
378c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            throw new RuntimeException ("invalid call barring sc");
379c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
380c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
381c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sc.equals(SC_BAOC)) {
382c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BAOC;
383c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BAOIC)) {
384c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BAOIC;
385c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BAOICxH)) {
386c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BAOICxH;
387c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BAIC)) {
388c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BAIC;
389c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BAICr)) {
390c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BAICr;
391c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BA_ALL)) {
392c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BA_ALL;
393c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BA_MO)) {
394c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BA_MO;
395c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BA_MT)) {
396c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BA_MT;
397c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
398c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            throw new RuntimeException ("invalid call barring sc");
399c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
400c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
401c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
402c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Constructor
403c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
404e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    GsmMmiCode (GSMPhone phone, UiccCardApplication app) {
405c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // The telephony unit-test cases may create GsmMmiCode's
406c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // in secondary threads
407c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        super(phone.getHandler().getLooper());
408c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        this.phone = phone;
409c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        this.context = phone.getContext();
410e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mUiccApplication = app;
411e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (app != null) {
412e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mIccRecords = app.getIccRecords();
413e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
414c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
415c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
416c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** MmiCode implementation
417c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
418cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
419c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public State
420c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    getState() {
421c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return state;
422c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
423c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
424cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
425c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public CharSequence
426c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    getMessage() {
427c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return message;
428c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
429c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
430c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // inherited javadoc suffices
431cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
432c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void
433c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    cancel() {
434c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Complete or failed cannot be cancelled
435c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (state == State.COMPLETE || state == State.FAILED) {
436c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return;
437c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
438c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
439c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        state = State.CANCELLED;
440c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
441c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (isPendingUSSD) {
442c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            /*
443c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             * There can only be one pending USSD session, so tell the radio to
444c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             * cancel it.
445c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             */
446c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            phone.mCM.cancelPendingUssd(obtainMessage(EVENT_USSD_CANCEL_COMPLETE, this));
447c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
448c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            /*
449c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             * Don't call phone.onMMIDone here; wait for CANCEL_COMPLETE notice
450c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             * from RIL.
451c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             */
452c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
453c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // TODO in cases other than USSD, it would be nice to cancel
454c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // the pending radio operation. This requires RIL cancellation
455c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // support, which does not presently exist.
456c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
457c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            phone.onMMIDone (this);
458c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
459c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
460c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
461c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
462cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
463c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public boolean isCancelable() {
464c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        /* Can only cancel pending USSD sessions. */
465c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return isPendingUSSD;
466c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
467c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
468c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Instance Methods
469c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
470c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Does this dial string contain a structured or unstructured MMI code? */
471c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean
472c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isMMI() {
473c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return poundString != null;
474c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
475c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
476c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /* Is this a 1 or 2 digit "short code" as defined in TS 22.030 sec 6.5.3.2? */
477c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean
478c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isShortCode() {
479c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return poundString == null
480c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    && dialingNumber != null && dialingNumber.length() <= 2;
481c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
482c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
483c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
484c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static private boolean
485c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isTwoDigitShortCode(Context context, String dialString) {
486ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville        Rlog.d(LOG_TAG, "isTwoDigitShortCode");
487c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
488c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (dialString == null || dialString.length() != 2) return false;
489c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
490c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sTwoDigitNumberPattern == null) {
491c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            sTwoDigitNumberPattern = context.getResources().getStringArray(
492c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    com.android.internal.R.array.config_twoDigitNumberPattern);
493c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
494c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
495c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        for (String dialnumber : sTwoDigitNumberPattern) {
496ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.d(LOG_TAG, "Two Digit Number Pattern " + dialnumber);
497c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (dialString.equals(dialnumber)) {
498ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.d(LOG_TAG, "Two Digit Number Pattern -true");
499c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return true;
500c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
501c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
502ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville        Rlog.d(LOG_TAG, "Two Digit Number Pattern -false");
503c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return false;
504c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
505c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
506c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
507c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Helper function for newFromDialString. Returns true if dialString appears
508c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * to be a short code AND conditions are correct for it to be treated as
509c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * such.
510c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
511c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static private boolean isShortCode(String dialString, GSMPhone phone) {
512c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Refer to TS 22.030 Figure 3.5.3.2:
513c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (dialString == null) {
514c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return false;
515c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
516c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
517c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Illegal dial string characters will give a ZERO length.
518c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // At this point we do not want to crash as any application with
519c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // call privileges may send a non dial string.
520c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // It return false as when the dialString is equal to NULL.
521c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (dialString.length() == 0) {
522c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return false;
523c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
524c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
525c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (PhoneNumberUtils.isLocalEmergencyNumber(dialString, phone.getContext())) {
526c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return false;
527c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
528c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return isShortCodeUSSD(dialString, phone);
529c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
530c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
531c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
532c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
533c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Helper function for isShortCode. Returns true if dialString appears to be
534c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * a short code and it is a USSD structure
535c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
536c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * According to the 3PGG TS 22.030 specification Figure 3.5.3.2: A 1 or 2
537c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * digit "short code" is treated as USSD if it is entered while on a call or
538c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * does not satisfy the condition (exactly 2 digits && starts with '1'), there
539c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * are however exceptions to this rule (see below)
540c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
541c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Exception (1) to Call initiation is: If the user of the device is already in a call
542c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * and enters a Short String without any #-key at the end and the length of the Short String is
543c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * equal or less then the MAX_LENGTH_SHORT_CODE [constant that is equal to 2]
544c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
545c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * The phone shall initiate a USSD/SS commands.
546c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
547c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static private boolean isShortCodeUSSD(String dialString, GSMPhone phone) {
54810e574acd0992d22abce257b420d333f5a49e71dJeevaka Badrappan        if (dialString != null && dialString.length() <= MAX_LENGTH_SHORT_CODE) {
549c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (phone.isInCall()) {
55010e574acd0992d22abce257b420d333f5a49e71dJeevaka Badrappan                return true;
551c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
552c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
55310e574acd0992d22abce257b420d333f5a49e71dJeevaka Badrappan            if (dialString.length() != MAX_LENGTH_SHORT_CODE ||
55410e574acd0992d22abce257b420d333f5a49e71dJeevaka Badrappan                    dialString.charAt(0) != '1') {
55510e574acd0992d22abce257b420d333f5a49e71dJeevaka Badrappan                return true;
556c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
557c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
558c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return false;
559c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
560c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
561c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
562c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @return true if the Service Code is PIN/PIN2/PUK/PUK2-related
563c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
564c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean isPinCommand() {
565c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return sc != null && (sc.equals(SC_PIN) || sc.equals(SC_PIN2)
566c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                              || sc.equals(SC_PUK) || sc.equals(SC_PUK2));
567c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     }
568c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
569c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
570c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * See TS 22.030 Annex B.
571c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * In temporary mode, to suppress CLIR for a single call, enter:
572c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *      " * 31 # [called number] SEND "
573c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  In temporary mode, to invoke CLIR for a single call enter:
574c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *       " # 31 # [called number] SEND "
575c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
576c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean
577c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isTemporaryModeCLIR() {
578c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return sc != null && sc.equals(SC_CLIR) && dialingNumber != null
579c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                && (isActivate() || isDeactivate());
580c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
581c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
582c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
583c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * returns CommandsInterface.CLIR_*
584c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * See also isTemporaryModeCLIR()
585c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
586c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    int
587c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    getCLIRMode() {
588c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sc != null && sc.equals(SC_CLIR)) {
589c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (isActivate()) {
590c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return CommandsInterface.CLIR_SUPPRESSION;
591c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else if (isDeactivate()) {
592c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return CommandsInterface.CLIR_INVOCATION;
593c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
594c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
595c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
596c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return CommandsInterface.CLIR_DEFAULT;
597c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
598c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
599c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean isActivate() {
600c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return action != null && action.equals(ACTION_ACTIVATE);
601c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
602c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
603c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean isDeactivate() {
604c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return action != null && action.equals(ACTION_DEACTIVATE);
605c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
606c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
607c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean isInterrogate() {
608c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return action != null && action.equals(ACTION_INTERROGATE);
609c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
610c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
611c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean isRegister() {
612c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return action != null && action.equals(ACTION_REGISTER);
613c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
614c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
615c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean isErasure() {
616c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return action != null && action.equals(ACTION_ERASURE);
617c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
618c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
619c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
620c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Returns true if this is a USSD code that's been submitted to the
621c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * network...eg, after processCode() is called
622c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
623c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public boolean isPendingUSSD() {
624c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return isPendingUSSD;
625c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
626c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
627cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
628c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public boolean isUssdRequest() {
629c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return isUssdRequest;
630c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
631c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
632c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Process a MMI code or short code...anything that isn't a dialing number */
633c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    void
634c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    processCode () {
635c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        try {
636c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (isShortCode()) {
637ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.d(LOG_TAG, "isShortCode");
638c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // These just get treated as USSD.
639c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sendUssd(dialingNumber);
640c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else if (dialingNumber != null) {
641c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // We should have no dialing numbers here
642c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                throw new RuntimeException ("Invalid or Unsupported MMI Code");
643c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else if (sc != null && sc.equals(SC_CLIP)) {
644ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.d(LOG_TAG, "is CLIP");
645c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isInterrogate()) {
646c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    phone.mCM.queryCLIP(
647c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            obtainMessage(EVENT_QUERY_COMPLETE, this));
648c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
649c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException ("Invalid or Unsupported MMI Code");
650c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
651c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else if (sc != null && sc.equals(SC_CLIR)) {
652ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.d(LOG_TAG, "is CLIR");
653c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isActivate()) {
654c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    phone.mCM.setCLIR(CommandsInterface.CLIR_INVOCATION,
655c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        obtainMessage(EVENT_SET_COMPLETE, this));
656c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (isDeactivate()) {
657c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    phone.mCM.setCLIR(CommandsInterface.CLIR_SUPPRESSION,
658c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        obtainMessage(EVENT_SET_COMPLETE, this));
659c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (isInterrogate()) {
660c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    phone.mCM.getCLIR(
661c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        obtainMessage(EVENT_GET_CLIR_COMPLETE, this));
662c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
663c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException ("Invalid or Unsupported MMI Code");
664c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
665c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else if (isServiceCodeCallForwarding(sc)) {
666ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.d(LOG_TAG, "is CF");
667c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
668c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                String dialingNumber = sia;
669c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                int serviceClass = siToServiceClass(sib);
670c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                int reason = scToCallForwardReason(sc);
671c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                int time = siToTime(sic);
672c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
673c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isInterrogate()) {
674c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    phone.mCM.queryCallForwardStatus(
675c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            reason, serviceClass,  dialingNumber,
676c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                obtainMessage(EVENT_QUERY_CF_COMPLETE, this));
677c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
678c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    int cfAction;
679c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
680c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    if (isActivate()) {
6815f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        // 3GPP TS 22.030 6.5.2
6825f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        // a call forwarding request with a single * would be
6835f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        // interpreted as registration if containing a forwarded-to
6845f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        // number, or an activation if not
6855f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        if (isEmptyOrNull(dialingNumber)) {
6865f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                            cfAction = CommandsInterface.CF_ACTION_ENABLE;
6875f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                            isCallFwdReg = false;
6885f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        } else {
6895f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                            cfAction = CommandsInterface.CF_ACTION_REGISTRATION;
6905f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                            isCallFwdReg = true;
6915f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        }
692c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else if (isDeactivate()) {
693c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        cfAction = CommandsInterface.CF_ACTION_DISABLE;
694c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else if (isRegister()) {
695c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        cfAction = CommandsInterface.CF_ACTION_REGISTRATION;
696c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else if (isErasure()) {
697c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        cfAction = CommandsInterface.CF_ACTION_ERASURE;
698c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else {
699c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        throw new RuntimeException ("invalid action");
700c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
701c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
702c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    int isSettingUnconditionalVoice =
703c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        (((reason == CommandsInterface.CF_REASON_UNCONDITIONAL) ||
704c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                (reason == CommandsInterface.CF_REASON_ALL)) &&
705c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                (((serviceClass & CommandsInterface.SERVICE_CLASS_VOICE) != 0) ||
706c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                 (serviceClass == CommandsInterface.SERVICE_CLASS_NONE))) ? 1 : 0;
707c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
708c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    int isEnableDesired =
709c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        ((cfAction == CommandsInterface.CF_ACTION_ENABLE) ||
710c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                (cfAction == CommandsInterface.CF_ACTION_REGISTRATION)) ? 1 : 0;
711c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
712ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                    Rlog.d(LOG_TAG, "is CF setCallForward");
713c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    phone.mCM.setCallForward(cfAction, reason, serviceClass,
714c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            dialingNumber, time, obtainMessage(
715c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    EVENT_SET_CFF_COMPLETE,
716c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    isSettingUnconditionalVoice,
717c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    isEnableDesired, this));
718c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
719c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else if (isServiceCodeCallBarring(sc)) {
720c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sia = password
721c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sib = basic service group
722c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
723c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                String password = sia;
724c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                int serviceClass = siToServiceClass(sib);
725c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                String facility = scToBarringFacility(sc);
726c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
727c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isInterrogate()) {
728c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    phone.mCM.queryFacilityLock(facility, password,
729c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            serviceClass, obtainMessage(EVENT_QUERY_COMPLETE, this));
730c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (isActivate() || isDeactivate()) {
731c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    phone.mCM.setFacilityLock(facility, isActivate(), password,
732c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            serviceClass, obtainMessage(EVENT_SET_COMPLETE, this));
733c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
734c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException ("Invalid or Unsupported MMI Code");
735c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
736c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
737c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else if (sc != null && sc.equals(SC_PWD)) {
738c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sia = fac
739c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sib = old pwd
740c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sic = new pwd
741c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // pwd = new pwd
742c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                String facility;
743c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                String oldPwd = sib;
744c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                String newPwd = sic;
745c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isActivate() || isRegister()) {
746c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // Even though ACTIVATE is acceptable, this is really termed a REGISTER
747c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    action = ACTION_REGISTER;
748c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
749c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    if (sia == null) {
750c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // If sc was not specified, treat it as BA_ALL.
751c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        facility = CommandsInterface.CB_FACILITY_BA_ALL;
752c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else {
753c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        facility = scToBarringFacility(sia);
754c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
755c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    if (newPwd.equals(pwd)) {
756c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        phone.mCM.changeBarringPassword(facility, oldPwd,
757c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                newPwd, obtainMessage(EVENT_SET_COMPLETE, this));
758c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else {
759c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // password mismatch; return error
760c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        handlePasswordError(com.android.internal.R.string.passwordIncorrect);
761c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
762c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
763c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException ("Invalid or Unsupported MMI Code");
764c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
765c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
766c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else if (sc != null && sc.equals(SC_WAIT)) {
767c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sia = basic service group
768c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                int serviceClass = siToServiceClass(sia);
769c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
770c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isActivate() || isDeactivate()) {
771c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    phone.mCM.setCallWaiting(isActivate(), serviceClass,
772c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            obtainMessage(EVENT_SET_COMPLETE, this));
773c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (isInterrogate()) {
774c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    phone.mCM.queryCallWaiting(serviceClass,
775c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            obtainMessage(EVENT_QUERY_COMPLETE, this));
776c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
777c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException ("Invalid or Unsupported MMI Code");
778c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
779c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else if (isPinCommand()) {
780c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sia = old PIN or PUK
781c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sib = new PIN
782c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sic = new PIN
783c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                String oldPinOrPuk = sia;
784c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                String newPin = sib;
785c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                int pinLen = newPin.length();
786c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isRegister()) {
787c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    if (!newPin.equals(sic)) {
788c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // password mismatch; return error
789c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        handlePasswordError(com.android.internal.R.string.mismatchPin);
790c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else if (pinLen < 4 || pinLen > 8 ) {
791c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // invalid length
792c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        handlePasswordError(com.android.internal.R.string.invalidPin);
793e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    } else if (sc.equals(SC_PIN) &&
794e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                               mUiccApplication != null &&
795e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                               mUiccApplication.getState() == AppState.APPSTATE_PUK ) {
796c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // Sim is puk-locked
797c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        handlePasswordError(com.android.internal.R.string.needPuk);
798c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else {
799c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // pre-checks OK
800c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        if (sc.equals(SC_PIN)) {
801c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            phone.mCM.changeIccPin(oldPinOrPuk, newPin,
802c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    obtainMessage(EVENT_SET_COMPLETE, this));
803c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        } else if (sc.equals(SC_PIN2)) {
804c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            phone.mCM.changeIccPin2(oldPinOrPuk, newPin,
805c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    obtainMessage(EVENT_SET_COMPLETE, this));
806c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        } else if (sc.equals(SC_PUK)) {
807c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            phone.mCM.supplyIccPuk(oldPinOrPuk, newPin,
808c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    obtainMessage(EVENT_SET_COMPLETE, this));
809c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        } else if (sc.equals(SC_PUK2)) {
810c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            phone.mCM.supplyIccPuk2(oldPinOrPuk, newPin,
811c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    obtainMessage(EVENT_SET_COMPLETE, this));
812c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        }
813c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
814c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
815c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException ("Invalid or Unsupported MMI Code");
816c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
817c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else if (poundString != null) {
818c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sendUssd(poundString);
819c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
820c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                throw new RuntimeException ("Invalid or Unsupported MMI Code");
821c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
822c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } catch (RuntimeException exc) {
823c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            state = State.FAILED;
824c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            message = context.getText(com.android.internal.R.string.mmiError);
825c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            phone.onMMIDone(this);
826c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
827c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
828c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
829c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void handlePasswordError(int res) {
830c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        state = State.FAILED;
831c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder(getScString());
832c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("\n");
833c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append(context.getText(res));
834c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        message = sb;
835c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        phone.onMMIDone(this);
836c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
837c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
838c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
839c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Called from GSMPhone
840c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
841c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * An unsolicited USSD NOTIFY or REQUEST has come in matching
842c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * up with this pending USSD request
843c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
844c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Note: If REQUEST, this exchange is complete, but the session remains
845c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *       active (ie, the network expects user input).
846c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
847c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    void
848c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    onUssdFinished(String ussdMessage, boolean isUssdRequest) {
849c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (state == State.PENDING) {
850c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (ussdMessage == null) {
851c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                message = context.getText(com.android.internal.R.string.mmiComplete);
852c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
853c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                message = ussdMessage;
854c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
855c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            this.isUssdRequest = isUssdRequest;
856c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // If it's a request, leave it PENDING so that it's cancelable.
857c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (!isUssdRequest) {
858c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                state = State.COMPLETE;
859c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
860c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
861c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            phone.onMMIDone(this);
862c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
863c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
864c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
865c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
866c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Called from GSMPhone
867c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
868c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * The radio has reset, and this is still pending
869c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
870c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
871c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    void
872c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    onUssdFinishedError() {
873c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (state == State.PENDING) {
874c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            state = State.FAILED;
875c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            message = context.getText(com.android.internal.R.string.mmiError);
876c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
877c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            phone.onMMIDone(this);
878c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
879c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
880c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
881c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    void sendUssd(String ussdMessage) {
882c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Treat this as a USSD string
883c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        isPendingUSSD = true;
884c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
885c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Note that unlike most everything else, the USSD complete
886c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // response does not complete this MMI code...we wait for
887c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // an unsolicited USSD "Notify" or "Request".
888c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // The matching up of this is done in GSMPhone.
889c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
890c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        phone.mCM.sendUSSD(ussdMessage,
891c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            obtainMessage(EVENT_USSD_COMPLETE, this));
892c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
893c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
894c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Called from GSMPhone.handleMessage; not a Handler subclass */
895cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
896c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void
897c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    handleMessage (Message msg) {
898c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        AsyncResult ar;
899c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
900c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        switch (msg.what) {
901c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_SET_COMPLETE:
902c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
903c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
904c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                onSetComplete(ar);
905c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
906c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
907c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_SET_CFF_COMPLETE:
908c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
909c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
910c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                /*
911c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                * msg.arg1 = 1 means to set unconditional voice call forwarding
912c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                * msg.arg2 = 1 means to enable voice call forwarding
913c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                */
914c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if ((ar.exception == null) && (msg.arg1 == 1)) {
915c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    boolean cffEnabled = (msg.arg2 == 1);
916e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    if (mIccRecords != null) {
917e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                        mIccRecords.setVoiceCallForwardingFlag(1, cffEnabled);
918bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                    }
919c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
920c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
921c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                onSetComplete(ar);
922c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
923c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
924c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_GET_CLIR_COMPLETE:
925c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
926c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                onGetClirComplete(ar);
927c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
928c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
929c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_QUERY_CF_COMPLETE:
930c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
931c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                onQueryCfComplete(ar);
932c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
933c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
934c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_QUERY_COMPLETE:
935c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
936c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                onQueryComplete(ar);
937c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
938c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
939c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_USSD_COMPLETE:
940c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
941c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
942c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (ar.exception != null) {
943c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    state = State.FAILED;
944c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    message = getErrorMessage(ar);
945c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
946c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    phone.onMMIDone(this);
947c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
948c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
949c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // Note that unlike most everything else, the USSD complete
950c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // response does not complete this MMI code...we wait for
951c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // an unsolicited USSD "Notify" or "Request".
952c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // The matching up of this is done in GSMPhone.
953c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
954c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
955c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
956c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_USSD_CANCEL_COMPLETE:
957c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                phone.onMMIDone(this);
958c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
959c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
960c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
961c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Private instance methods
962c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
963c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence getErrorMessage(AsyncResult ar) {
964c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
965c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (ar.exception instanceof CommandException) {
966c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            CommandException.Error err = ((CommandException)(ar.exception)).getCommandError();
967c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (err == CommandException.Error.FDN_CHECK_FAILURE) {
968ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.i(LOG_TAG, "FDN_CHECK_FAILURE");
969c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return context.getText(com.android.internal.R.string.mmiFdnError);
970c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
971c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
972c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
973c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return context.getText(com.android.internal.R.string.mmiError);
974c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
975c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
976c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence getScString() {
977c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sc != null) {
978c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (isServiceCodeCallBarring(sc)) {
979c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return context.getText(com.android.internal.R.string.BaMmi);
980c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else if (isServiceCodeCallForwarding(sc)) {
981c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return context.getText(com.android.internal.R.string.CfMmi);
982c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else if (sc.equals(SC_CLIP)) {
983c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return context.getText(com.android.internal.R.string.ClipMmi);
984c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else if (sc.equals(SC_CLIR)) {
985c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return context.getText(com.android.internal.R.string.ClirMmi);
986c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else if (sc.equals(SC_PWD)) {
987c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return context.getText(com.android.internal.R.string.PwdMmi);
988c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else if (sc.equals(SC_WAIT)) {
989c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return context.getText(com.android.internal.R.string.CwMmi);
990c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else if (isPinCommand()) {
991c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return context.getText(com.android.internal.R.string.PinMmi);
992c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
993c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
994c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
995c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return "";
996c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
997c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
998c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void
999c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    onSetComplete(AsyncResult ar){
1000c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder(getScString());
1001c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("\n");
1002c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1003c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (ar.exception != null) {
1004c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            state = State.FAILED;
1005c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (ar.exception instanceof CommandException) {
1006c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                CommandException.Error err = ((CommandException)(ar.exception)).getCommandError();
1007c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (err == CommandException.Error.PASSWORD_INCORRECT) {
1008c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    if (isPinCommand()) {
1009c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // look specifically for the PUK commands and adjust
1010c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // the message accordingly.
1011c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        if (sc.equals(SC_PUK) || sc.equals(SC_PUK2)) {
1012c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            sb.append(context.getText(
1013c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.badPuk));
1014c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        } else {
1015c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            sb.append(context.getText(
1016c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.badPin));
1017c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        }
1018c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else {
1019c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        sb.append(context.getText(
1020c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                com.android.internal.R.string.passwordIncorrect));
1021c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
1022c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (err == CommandException.Error.SIM_PUK2) {
1023c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    sb.append(context.getText(
1024c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            com.android.internal.R.string.badPin));
1025c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    sb.append("\n");
1026c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    sb.append(context.getText(
1027c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            com.android.internal.R.string.needPuk2));
1028c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (err == CommandException.Error.FDN_CHECK_FAILURE) {
1029ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                    Rlog.i(LOG_TAG, "FDN_CHECK_FAILURE");
1030c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    sb.append(context.getText(com.android.internal.R.string.mmiFdnError));
1031c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
1032c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    sb.append(context.getText(
1033c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            com.android.internal.R.string.mmiError));
1034c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
1035c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
1036c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sb.append(context.getText(
1037c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.mmiError));
1038c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1039c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isActivate()) {
1040c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            state = State.COMPLETE;
10415f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li            if (isCallFwdReg) {
10425f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                sb.append(context.getText(
10435f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        com.android.internal.R.string.serviceRegistered));
10445f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li            } else {
10455f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                sb.append(context.getText(
10465f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        com.android.internal.R.string.serviceEnabled));
10475f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li            }
1048c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // Record CLIR setting
1049c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (sc.equals(SC_CLIR)) {
1050c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                phone.saveClirSetting(CommandsInterface.CLIR_INVOCATION);
1051c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1052c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isDeactivate()) {
1053c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            state = State.COMPLETE;
1054c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            sb.append(context.getText(
1055c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    com.android.internal.R.string.serviceDisabled));
1056c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // Record CLIR setting
1057c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (sc.equals(SC_CLIR)) {
1058c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                phone.saveClirSetting(CommandsInterface.CLIR_SUPPRESSION);
1059c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1060c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isRegister()) {
1061c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            state = State.COMPLETE;
1062c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            sb.append(context.getText(
1063c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    com.android.internal.R.string.serviceRegistered));
1064c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isErasure()) {
1065c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            state = State.COMPLETE;
1066c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            sb.append(context.getText(
1067c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    com.android.internal.R.string.serviceErased));
1068c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
1069c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            state = State.FAILED;
1070c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            sb.append(context.getText(
1071c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    com.android.internal.R.string.mmiError));
1072c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1073c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1074c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        message = sb;
1075c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        phone.onMMIDone(this);
1076c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1077c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1078c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void
1079c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    onGetClirComplete(AsyncResult ar) {
1080c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder(getScString());
1081c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("\n");
1082c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1083c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (ar.exception != null) {
1084c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            state = State.FAILED;
1085c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            sb.append(getErrorMessage(ar));
1086c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
1087c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            int clirArgs[];
1088c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1089c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            clirArgs = (int[])ar.result;
1090c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1091c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // the 'm' parameter from TS 27.007 7.7
1092c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            switch (clirArgs[1]) {
1093c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 0: // CLIR not provisioned
1094c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    sb.append(context.getText(
1095c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                com.android.internal.R.string.serviceNotProvisioned));
1096c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    state = State.COMPLETE;
1097c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1098c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1099c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 1: // CLIR provisioned in permanent mode
1100c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    sb.append(context.getText(
1101c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                com.android.internal.R.string.CLIRPermanent));
1102c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    state = State.COMPLETE;
1103c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1104c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1105c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 2: // unknown (e.g. no network, etc.)
1106c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    sb.append(context.getText(
1107c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                com.android.internal.R.string.mmiError));
1108c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    state = State.FAILED;
1109c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1110c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1111c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 3: // CLIR temporary mode presentation restricted
1112c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1113c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // the 'n' parameter from TS 27.007 7.7
1114c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    switch (clirArgs[0]) {
1115c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        default:
1116c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 0: // Default
1117c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            sb.append(context.getText(
1118c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOnNextCallOn));
1119c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1120c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 1: // CLIR invocation
1121c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            sb.append(context.getText(
1122c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOnNextCallOn));
1123c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1124c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 2: // CLIR suppression
1125c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            sb.append(context.getText(
1126c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOnNextCallOff));
1127c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1128c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
1129c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    state = State.COMPLETE;
1130c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1131c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1132c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 4: // CLIR temporary mode presentation allowed
1133c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // the 'n' parameter from TS 27.007 7.7
1134c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    switch (clirArgs[0]) {
1135c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        default:
1136c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 0: // Default
1137c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            sb.append(context.getText(
1138c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOffNextCallOff));
1139c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1140c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 1: // CLIR invocation
1141c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            sb.append(context.getText(
1142c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOffNextCallOn));
1143c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1144c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 2: // CLIR suppression
1145c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            sb.append(context.getText(
1146c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOffNextCallOff));
1147c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1148c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
1149c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1150c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    state = State.COMPLETE;
1151c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1152c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1153c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1154c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1155c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        message = sb;
1156c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        phone.onMMIDone(this);
1157c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1158c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1159c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
1160c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param serviceClass 1 bit of the service class bit vectory
1161c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @return String to be used for call forward query MMI response text.
1162c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *        Returns null if unrecognized
1163c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
1164c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1165c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence
1166c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    serviceClassToCFString (int serviceClass) {
1167c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        switch (serviceClass) {
1168c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_VOICE:
1169c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return context.getText(com.android.internal.R.string.serviceClassVoice);
1170c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_DATA:
1171c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return context.getText(com.android.internal.R.string.serviceClassData);
1172c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_FAX:
1173c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return context.getText(com.android.internal.R.string.serviceClassFAX);
1174c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_SMS:
1175c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return context.getText(com.android.internal.R.string.serviceClassSMS);
1176c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_DATA_SYNC:
1177c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return context.getText(com.android.internal.R.string.serviceClassDataSync);
1178c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_DATA_ASYNC:
1179c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return context.getText(com.android.internal.R.string.serviceClassDataAsync);
1180c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_PACKET:
1181c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return context.getText(com.android.internal.R.string.serviceClassPacket);
1182c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_PAD:
1183c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return context.getText(com.android.internal.R.string.serviceClassPAD);
1184c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            default:
1185c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return null;
1186c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1187c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1188c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1189c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1190c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** one CallForwardInfo + serviceClassMask -> one line of text */
1191c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence
1192c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    makeCFQueryResultMessage(CallForwardInfo info, int serviceClassMask) {
1193c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        CharSequence template;
1194c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        String sources[] = {"{0}", "{1}", "{2}"};
1195c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        CharSequence destinations[] = new CharSequence[3];
1196c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        boolean needTimeTemplate;
1197c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1198c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // CF_REASON_NO_REPLY also has a time value associated with
1199c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // it. All others don't.
1200c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1201c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        needTimeTemplate =
1202c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            (info.reason == CommandsInterface.CF_REASON_NO_REPLY);
1203c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1204c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (info.status == 1) {
1205c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (needTimeTemplate) {
1206c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                template = context.getText(
1207c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.cfTemplateForwardedTime);
1208c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
1209c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                template = context.getText(
1210c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.cfTemplateForwarded);
1211c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1212c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (info.status == 0 && isEmptyOrNull(info.number)) {
1213c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            template = context.getText(
1214c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.cfTemplateNotForwarded);
1215c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else { /* (info.status == 0) && !isEmptyOrNull(info.number) */
1216c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // A call forward record that is not active but contains
1217c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // a phone number is considered "registered"
1218c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1219c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (needTimeTemplate) {
1220c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                template = context.getText(
1221c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.cfTemplateRegisteredTime);
1222c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
1223c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                template = context.getText(
1224c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.cfTemplateRegistered);
1225c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1226c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1227c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1228c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // In the template (from strings.xmls)
1229c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        //         {0} is one of "bearerServiceCode*"
1230c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        //        {1} is dialing number
1231c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        //      {2} is time in seconds
1232c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1233c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        destinations[0] = serviceClassToCFString(info.serviceClass & serviceClassMask);
1234c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        destinations[1] = PhoneNumberUtils.stringFromStringAndTOA(info.number, info.toa);
1235c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        destinations[2] = Integer.toString(info.timeSeconds);
1236c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1237c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (info.reason == CommandsInterface.CF_REASON_UNCONDITIONAL &&
1238c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                (info.serviceClass & serviceClassMask)
1239c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        == CommandsInterface.SERVICE_CLASS_VOICE) {
1240c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            boolean cffEnabled = (info.status == 1);
1241e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (mIccRecords != null) {
1242e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                mIccRecords.setVoiceCallForwardingFlag(1, cffEnabled);
1243bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka            }
1244c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1245c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1246c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return TextUtils.replace(template, sources, destinations);
1247c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1248c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1249c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1250c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void
1251c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    onQueryCfComplete(AsyncResult ar) {
1252c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder(getScString());
1253c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("\n");
1254c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1255c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (ar.exception != null) {
1256c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            state = State.FAILED;
1257c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            sb.append(getErrorMessage(ar));
1258c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
1259c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            CallForwardInfo infos[];
1260c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1261c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            infos = (CallForwardInfo[]) ar.result;
1262c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1263c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (infos.length == 0) {
1264c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // Assume the default is not active
1265c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sb.append(context.getText(com.android.internal.R.string.serviceDisabled));
1266c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1267c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // Set unconditional CFF in SIM to false
1268e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if (mIccRecords != null) {
1269e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    mIccRecords.setVoiceCallForwardingFlag(1, false);
1270bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                }
1271c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
1272c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1273c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                SpannableStringBuilder tb = new SpannableStringBuilder();
1274c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1275c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // Each bit in the service class gets its own result line
1276c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // The service classes may be split up over multiple
1277c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // CallForwardInfos. So, for each service class, find out
1278c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // which CallForwardInfo represents it and then build
1279c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // the response text based on that
1280c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1281c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                for (int serviceClassMask = 1
1282c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            ; serviceClassMask <= SERVICE_CLASS_MAX
1283c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            ; serviceClassMask <<= 1
1284c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ) {
1285c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    for (int i = 0, s = infos.length; i < s ; i++) {
1286c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        if ((serviceClassMask & infos[i].serviceClass) != 0) {
1287c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            tb.append(makeCFQueryResultMessage(infos[i],
1288c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                            serviceClassMask));
1289c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            tb.append("\n");
1290c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        }
1291c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
1292c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
1293c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sb.append(tb);
1294c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1295c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1296c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            state = State.COMPLETE;
1297c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1298c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1299c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        message = sb;
1300c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        phone.onMMIDone(this);
1301c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1302c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1303c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1304c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void
1305c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    onQueryComplete(AsyncResult ar) {
1306c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder(getScString());
1307c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("\n");
1308c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1309c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (ar.exception != null) {
1310c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            state = State.FAILED;
1311c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            sb.append(getErrorMessage(ar));
1312c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
1313c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            int[] ints = (int[])ar.result;
1314c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1315c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (ints.length != 0) {
1316c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (ints[0] == 0) {
1317c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    sb.append(context.getText(com.android.internal.R.string.serviceDisabled));
1318c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (sc.equals(SC_WAIT)) {
1319c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // Call Waiting includes additional data in the response.
1320c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    sb.append(createQueryCallWaitingResultMessage(ints[1]));
1321c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (isServiceCodeCallBarring(sc)) {
1322c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // ints[0] for Call Barring is a bit vector of services
1323c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    sb.append(createQueryCallBarringResultMessage(ints[0]));
1324c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (ints[0] == 1) {
1325c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // for all other services, treat it as a boolean
1326c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    sb.append(context.getText(com.android.internal.R.string.serviceEnabled));
1327c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
1328c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    sb.append(context.getText(com.android.internal.R.string.mmiError));
1329c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
1330c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
1331c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sb.append(context.getText(com.android.internal.R.string.mmiError));
1332c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1333c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            state = State.COMPLETE;
1334c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1335c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1336c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        message = sb;
1337c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        phone.onMMIDone(this);
1338c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1339c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1340c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence
1341c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    createQueryCallWaitingResultMessage(int serviceClass) {
1342c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb =
1343c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                new StringBuilder(context.getText(com.android.internal.R.string.serviceEnabledFor));
1344c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1345c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        for (int classMask = 1
1346c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    ; classMask <= SERVICE_CLASS_MAX
1347c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    ; classMask <<= 1
1348c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        ) {
1349c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if ((classMask & serviceClass) != 0) {
1350c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sb.append("\n");
1351c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sb.append(serviceClassToCFString(classMask & serviceClass));
1352c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1353c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1354c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return sb;
1355c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1356c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence
1357c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    createQueryCallBarringResultMessage(int serviceClass)
1358c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    {
1359c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder(context.getText(com.android.internal.R.string.serviceEnabledFor));
1360c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1361c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        for (int classMask = 1
1362c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    ; classMask <= SERVICE_CLASS_MAX
1363c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    ; classMask <<= 1
1364c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        ) {
1365c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if ((classMask & serviceClass) != 0) {
1366c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sb.append("\n");
1367c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sb.append(serviceClassToCFString(classMask & serviceClass));
1368c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1369c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1370c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return sb;
1371c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1372c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1373c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /***
1374c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * TODO: It would be nice to have a method here that can take in a dialstring and
1375c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * figure out if there is an MMI code embedded within it.  This code would replace
1376c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * some of the string parsing functionality in the Phone App's
1377c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * SpecialCharSequenceMgr class.
1378c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
1379c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1380c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
1381c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public String toString() {
1382c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder("GsmMmiCode {");
1383c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1384c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("State=" + getState());
1385c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (action != null) sb.append(" action=" + action);
1386c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sc != null) sb.append(" sc=" + sc);
1387c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sia != null) sb.append(" sia=" + sia);
1388c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sib != null) sb.append(" sib=" + sib);
1389c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sic != null) sb.append(" sic=" + sic);
1390c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (poundString != null) sb.append(" poundString=" + poundString);
1391c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (dialingNumber != null) sb.append(" dialingNumber=" + dialingNumber);
1392c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (pwd != null) sb.append(" pwd=" + pwd);
1393c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("}");
1394c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return sb.toString();
1395c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1396c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville}
1397