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