GsmMmiCode.java revision a8467dd0c524787104b1ccdddc5e8af10ba729ed
1c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/*
2c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Copyright (C) 2006 The Android Open Source Project
3c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
4c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Licensed under the Apache License, Version 2.0 (the "License");
5c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * you may not use this file except in compliance with the License.
6c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * You may obtain a copy of the License at
7c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
8c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *      http://www.apache.org/licenses/LICENSE-2.0
9c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
10c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Unless required by applicable law or agreed to in writing, software
11c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * distributed under the License is distributed on an "AS IS" BASIS,
12c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * See the License for the specific language governing permissions and
14c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * limitations under the License.
15c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */
16c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
17c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savillepackage com.android.internal.telephony.gsm;
18c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
19c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.content.Context;
2021fe62acc2d11ace0410b2b6d83263a96081c092duho.roimport android.content.res.Resources;
21c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.*;
22d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccRecords;
23d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.UiccCardApplication;
24d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState;
25c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
26c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.os.*;
27c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.telephony.PhoneNumberUtils;
28c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.text.SpannableStringBuilder;
298697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlssonimport android.text.BidiFormatter;
308697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlssonimport android.text.TextDirectionHeuristics;
31c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.text.TextUtils;
32ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Savilleimport android.telephony.Rlog;
33c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
34c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport static com.android.internal.telephony.CommandsInterface.*;
35c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
36c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport java.util.regex.Pattern;
37c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport java.util.regex.Matcher;
38c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
39c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/**
40c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * The motto for this file is:
41c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
42c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * "NOTE:    By using the # as a separator, most cases are expected to be unambiguous."
43c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *   -- TS 22.030 6.5.2
44c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
45c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * {@hide}
46c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
47c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */
48c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savillepublic final class GsmMmiCode extends Handler implements MmiCode {
49cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    static final String LOG_TAG = "GsmMmiCode";
50c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
51c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Constants
52c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
53c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Max Size of the Short Code (aka Short String from TS 22.030 6.5.2)
54c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MAX_LENGTH_SHORT_CODE = 2;
55c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
56c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // TS 22.030 6.5.2 Every Short String USSD command will end with #-key
57c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // (known as #-String)
58c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final char END_OF_USSD_COMMAND = '#';
59c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
60c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // From TS 22.030 6.5.2
61c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String ACTION_ACTIVATE = "*";
62c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String ACTION_DEACTIVATE = "#";
63c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String ACTION_INTERROGATE = "*#";
64c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String ACTION_REGISTER = "**";
65c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String ACTION_ERASURE = "##";
66c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
67c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Supp Service codes from TS 22.030 Annex B
68c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
69c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //Called line presentation
70c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CLIP    = "30";
71c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CLIR    = "31";
72c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
73c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Call Forwarding
74c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CFU     = "21";
75c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CFB     = "67";
76c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CFNRy   = "61";
77c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CFNR    = "62";
78c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
79c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CF_All = "002";
80c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CF_All_Conditional = "004";
81c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
82c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Call Waiting
83c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_WAIT     = "43";
84c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
85c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Call Barring
86c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BAOC         = "33";
87c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BAOIC        = "331";
88c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BAOICxH      = "332";
89c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BAIC         = "35";
90c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BAICr        = "351";
91c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
92c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BA_ALL       = "330";
93c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BA_MO        = "333";
94c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BA_MT        = "353";
95c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
96c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Supp Service Password registration
97c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_PWD          = "03";
98c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
99c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // PIN/PIN2/PUK/PUK2
100c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_PIN          = "04";
101c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_PIN2         = "042";
102c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_PUK          = "05";
103c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_PUK2         = "052";
104c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
105c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Event Constants
106c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
107c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_SET_COMPLETE         = 1;
108c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_GET_CLIR_COMPLETE    = 2;
109c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_QUERY_CF_COMPLETE    = 3;
110c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_USSD_COMPLETE        = 4;
111c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_QUERY_COMPLETE       = 5;
112c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_SET_CFF_COMPLETE     = 6;
113c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_USSD_CANCEL_COMPLETE = 7;
114c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
115c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Instance Variables
116c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
11722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    GSMPhone mPhone;
11822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    Context mContext;
119e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    UiccCardApplication mUiccApplication;
120e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    IccRecords mIccRecords;
121c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
12222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    String mAction;              // One of ACTION_*
12322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    String mSc;                  // Service Code
12422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    String mSia, mSib, mSic;       // Service Info a,b,c
12522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    String mPoundString;         // Entire MMI string up to and including #
12622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    String mDialingNumber;
12722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    String mPwd;                 // For password registration
128c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
129c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Set to true in processCode, not at newFromDialString time */
13022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    private boolean mIsPendingUSSD;
131c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
13222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    private boolean mIsUssdRequest;
133c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
13422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    private boolean mIsCallFwdReg;
13522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    State mState = State.PENDING;
13622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    CharSequence mMessage;
137c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
138c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Class Variables
139c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
140c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
141c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // See TS 22.030 6.5.2 "Structure of the MMI"
142c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
143c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static Pattern sPatternSuppService = Pattern.compile(
1449225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang        "((\\*|#|\\*#|\\*\\*|##)(\\d{2,3})(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*))?)?)?)?#)(.*)");
145c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/*       1  2                    3          4  5       6   7         8    9     10  11             12
146c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
147c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         1 = Full string up to and including #
148c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         2 = action (activation/interrogation/registration/erasure)
149c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         3 = service code
150c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         5 = SIA
151c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         7 = SIB
152c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         9 = SIC
1539225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang         10 = dialing number
154c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville*/
155c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
156c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_POUND_STRING = 1;
157c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
158c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_ACTION = 2;
159c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        //(activation/interrogation/registration/erasure)
160c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
161c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_SERVICE_CODE = 3;
162c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_SIA = 5;
163c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_SIB = 7;
164c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_SIC = 9;
165c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_PWD_CONFIRM = 11;
166c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_DIALING_NUMBER = 12;
167c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static private String[] sTwoDigitNumberPattern;
168c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
169c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Public Class methods
170c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
171c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
172c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Some dial strings in GSM are defined to do non-call setup
173c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * things, such as modify or query supplementary service settings (eg, call
174c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * forwarding). These are generally referred to as "MMI codes".
175c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * We look to see if the dial string contains a valid MMI code (potentially
176c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * with a dial string at the end as well) and return info here.
177c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
178c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * If the dial string contains no MMI code, we return an instance with
179c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * only "dialingNumber" set
180c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
181c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Please see flow chart in TS 22.030 6.5.3.2
182c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
183c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
184c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static GsmMmiCode
185e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    newFromDialString(String dialString, GSMPhone phone, UiccCardApplication app) {
186c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        Matcher m;
187c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        GsmMmiCode ret = null;
188c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
189c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        m = sPatternSuppService.matcher(dialString);
190c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
191c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Is this formatted like a standard supplementary service code?
192c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (m.matches()) {
193e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            ret = new GsmMmiCode(phone, app);
19422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mPoundString = makeEmptyNull(m.group(MATCH_GROUP_POUND_STRING));
19522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mAction = makeEmptyNull(m.group(MATCH_GROUP_ACTION));
19622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mSc = makeEmptyNull(m.group(MATCH_GROUP_SERVICE_CODE));
19722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mSia = makeEmptyNull(m.group(MATCH_GROUP_SIA));
19822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mSib = makeEmptyNull(m.group(MATCH_GROUP_SIB));
19922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mSic = makeEmptyNull(m.group(MATCH_GROUP_SIC));
20022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mPwd = makeEmptyNull(m.group(MATCH_GROUP_PWD_CONFIRM));
20122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mDialingNumber = makeEmptyNull(m.group(MATCH_GROUP_DIALING_NUMBER));
2029225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            // According to TS 22.030 6.5.2 "Structure of the MMI",
2039225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            // the dialing number should not ending with #.
2049225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            // The dialing number ending # is treated as unique USSD,
2059225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            // eg, *400#16 digit number# to recharge the prepaid card
2069225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            // in India operator(Mumbai MTNL)
20722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            if(ret.mDialingNumber != null &&
20822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    ret.mDialingNumber.endsWith("#") &&
2099225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang                    dialString.endsWith("#")){
2109225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang                ret = new GsmMmiCode(phone, app);
21122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                ret.mPoundString = dialString;
2129225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            }
213c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (dialString.endsWith("#")) {
214c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // TS 22.030 sec 6.5.3.2
215c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // "Entry of any characters defined in the 3GPP TS 23.038 [8] Default Alphabet
216c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // (up to the maximum defined in 3GPP TS 24.080 [10]), followed by #SEND".
217c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
218e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            ret = new GsmMmiCode(phone, app);
21922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mPoundString = dialString;
220c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isTwoDigitShortCode(phone.getContext(), dialString)) {
221c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            //Is a country-specific exception to short codes as defined in TS 22.030, 6.5.3.2
222c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ret = null;
223c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isShortCode(dialString, phone)) {
224c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // this may be a short code, as defined in TS 22.030, 6.5.3.2
225e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            ret = new GsmMmiCode(phone, app);
22622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mDialingNumber = dialString;
227c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
228c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
229c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return ret;
230c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
231c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
232c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static GsmMmiCode
233c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    newNetworkInitiatedUssd (String ussdMessage,
234e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                                boolean isUssdRequest, GSMPhone phone, UiccCardApplication app) {
235c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        GsmMmiCode ret;
236c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
237e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        ret = new GsmMmiCode(phone, app);
238c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
23922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        ret.mMessage = ussdMessage;
24022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        ret.mIsUssdRequest = isUssdRequest;
241c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
242c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // If it's a request, set to PENDING so that it's cancelable.
243c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (isUssdRequest) {
24422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mIsPendingUSSD = true;
24522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mState = State.PENDING;
246c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
24722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mState = State.COMPLETE;
248c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
249c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
250c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return ret;
251c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
252c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
253e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    static GsmMmiCode newFromUssdUserInput(String ussdMessge,
254e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                                           GSMPhone phone,
255e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                                           UiccCardApplication app) {
256e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        GsmMmiCode ret = new GsmMmiCode(phone, app);
257c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
25822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        ret.mMessage = ussdMessge;
25922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        ret.mState = State.PENDING;
26022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        ret.mIsPendingUSSD = true;
261c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
262c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return ret;
263c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
264c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
265c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Private Class methods
266c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
267c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** make empty strings be null.
268c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  Regexp returns empty strings for empty groups
269c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
270c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static String
271c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    makeEmptyNull (String s) {
272c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (s != null && s.length() == 0) return null;
273c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
274c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return s;
275c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
276c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
277c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** returns true of the string is empty or null */
278c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static boolean
279c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isEmptyOrNull(CharSequence s) {
280c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return s == null || (s.length() == 0);
281c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
282c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
283c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
284c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static int
285c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    scToCallForwardReason(String sc) {
286c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sc == null) {
287c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            throw new RuntimeException ("invalid call forward sc");
288c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
289c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
290c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sc.equals(SC_CF_All)) {
291c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville           return CommandsInterface.CF_REASON_ALL;
292c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_CFU)) {
293c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CF_REASON_UNCONDITIONAL;
294c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_CFB)) {
295c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CF_REASON_BUSY;
296c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_CFNR)) {
297c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CF_REASON_NOT_REACHABLE;
298c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_CFNRy)) {
299c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CF_REASON_NO_REPLY;
300c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_CF_All_Conditional)) {
301c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville           return CommandsInterface.CF_REASON_ALL_CONDITIONAL;
302c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
303c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            throw new RuntimeException ("invalid call forward sc");
304c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
305c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
306c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
307c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static int
308c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    siToServiceClass(String si) {
309c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (si == null || si.length() == 0) {
310c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return  SERVICE_CLASS_NONE;
311c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
312c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // NumberFormatException should cause MMI fail
313c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            int serviceCode = Integer.parseInt(si, 10);
314c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
315c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            switch (serviceCode) {
316c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 10: return SERVICE_CLASS_SMS + SERVICE_CLASS_FAX  + SERVICE_CLASS_VOICE;
317c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 11: return SERVICE_CLASS_VOICE;
318c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 12: return SERVICE_CLASS_SMS + SERVICE_CLASS_FAX;
319c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 13: return SERVICE_CLASS_FAX;
320c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
321c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 16: return SERVICE_CLASS_SMS;
322c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
323c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 19: return SERVICE_CLASS_FAX + SERVICE_CLASS_VOICE;
324c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/*
325c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    Note for code 20:
326c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     From TS 22.030 Annex C:
327c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                "All GPRS bearer services" are not included in "All tele and bearer services"
328c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    and "All bearer services"."
329c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville....so SERVICE_CLASS_DATA, which (according to 27.007) includes GPRS
330c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville*/
331c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 20: return SERVICE_CLASS_DATA_ASYNC + SERVICE_CLASS_DATA_SYNC;
332c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
333c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 21: return SERVICE_CLASS_PAD + SERVICE_CLASS_DATA_ASYNC;
334c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 22: return SERVICE_CLASS_PACKET + SERVICE_CLASS_DATA_SYNC;
335c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 24: return SERVICE_CLASS_DATA_SYNC;
336c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 25: return SERVICE_CLASS_DATA_ASYNC;
337c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 26: return SERVICE_CLASS_DATA_SYNC + SERVICE_CLASS_VOICE;
338c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 99: return SERVICE_CLASS_PACKET;
339c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
340c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                default:
341c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException("unsupported MMI service code " + si);
342c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
343c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
344c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
345c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
346c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static int
347c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    siToTime (String si) {
348c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (si == null || si.length() == 0) {
349c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return 0;
350c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
351c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // NumberFormatException should cause MMI fail
352c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return Integer.parseInt(si, 10);
353c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
354c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
355c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
356c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static boolean
357c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isServiceCodeCallForwarding(String sc) {
358c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return sc != null &&
359c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                (sc.equals(SC_CFU)
360c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                || sc.equals(SC_CFB) || sc.equals(SC_CFNRy)
361c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                || sc.equals(SC_CFNR) || sc.equals(SC_CF_All)
362c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                || sc.equals(SC_CF_All_Conditional));
363c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
364c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
365c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static boolean
366c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isServiceCodeCallBarring(String sc) {
36721fe62acc2d11ace0410b2b6d83263a96081c092duho.ro        Resources resource = Resources.getSystem();
36821fe62acc2d11ace0410b2b6d83263a96081c092duho.ro        if (sc != null) {
36921fe62acc2d11ace0410b2b6d83263a96081c092duho.ro            String[] barringMMI = resource.getStringArray(
37021fe62acc2d11ace0410b2b6d83263a96081c092duho.ro                com.android.internal.R.array.config_callBarringMMI);
37121fe62acc2d11ace0410b2b6d83263a96081c092duho.ro            if (barringMMI != null) {
37221fe62acc2d11ace0410b2b6d83263a96081c092duho.ro                for (String match : barringMMI) {
37321fe62acc2d11ace0410b2b6d83263a96081c092duho.ro                    if (sc.equals(match)) return true;
37421fe62acc2d11ace0410b2b6d83263a96081c092duho.ro                }
37521fe62acc2d11ace0410b2b6d83263a96081c092duho.ro            }
37621fe62acc2d11ace0410b2b6d83263a96081c092duho.ro        }
37721fe62acc2d11ace0410b2b6d83263a96081c092duho.ro        return false;
378c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
379c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
380c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static String
381c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    scToBarringFacility(String sc) {
382c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sc == null) {
383c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            throw new RuntimeException ("invalid call barring sc");
384c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
385c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
386c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sc.equals(SC_BAOC)) {
387c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BAOC;
388c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BAOIC)) {
389c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BAOIC;
390c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BAOICxH)) {
391c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BAOICxH;
392c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BAIC)) {
393c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BAIC;
394c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BAICr)) {
395c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BAICr;
396c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BA_ALL)) {
397c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BA_ALL;
398c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BA_MO)) {
399c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BA_MO;
400c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BA_MT)) {
401c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BA_MT;
402c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
403c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            throw new RuntimeException ("invalid call barring sc");
404c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
405c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
406c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
407c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Constructor
408c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
409e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    GsmMmiCode (GSMPhone phone, UiccCardApplication app) {
410c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // The telephony unit-test cases may create GsmMmiCode's
411c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // in secondary threads
412c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        super(phone.getHandler().getLooper());
41322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mPhone = phone;
41422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mContext = phone.getContext();
415e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mUiccApplication = app;
416e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (app != null) {
417e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mIccRecords = app.getIccRecords();
418e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
419c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
420c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
421c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** MmiCode implementation
422c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
423cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
424c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public State
425c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    getState() {
42622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mState;
427c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
428c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
429cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
430c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public CharSequence
431c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    getMessage() {
43222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mMessage;
433c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
434c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
435a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public Phone
436a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    getPhone() {
437a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return ((Phone) mPhone);
438a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
439a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
440c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // inherited javadoc suffices
441cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
442c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void
443c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    cancel() {
444c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Complete or failed cannot be cancelled
44522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mState == State.COMPLETE || mState == State.FAILED) {
446c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return;
447c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
448c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
44922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mState = State.CANCELLED;
450c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
45122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mIsPendingUSSD) {
452c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            /*
453c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             * There can only be one pending USSD session, so tell the radio to
454c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             * cancel it.
455c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             */
45622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mPhone.mCi.cancelPendingUssd(obtainMessage(EVENT_USSD_CANCEL_COMPLETE, this));
457c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
458c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            /*
459c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             * Don't call phone.onMMIDone here; wait for CANCEL_COMPLETE notice
460c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             * from RIL.
461c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             */
462c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
463c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // TODO in cases other than USSD, it would be nice to cancel
464c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // the pending radio operation. This requires RIL cancellation
465c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // support, which does not presently exist.
466c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
46722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mPhone.onMMIDone (this);
468c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
469c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
470c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
471c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
472cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
473c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public boolean isCancelable() {
474c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        /* Can only cancel pending USSD sessions. */
47522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mIsPendingUSSD;
476c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
477c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
478c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Instance Methods
479c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
480c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Does this dial string contain a structured or unstructured MMI code? */
481c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean
482c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isMMI() {
48322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mPoundString != null;
484c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
485c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
486c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /* Is this a 1 or 2 digit "short code" as defined in TS 22.030 sec 6.5.3.2? */
487c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean
488c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isShortCode() {
48922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mPoundString == null
49022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    && mDialingNumber != null && mDialingNumber.length() <= 2;
491c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
492c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
493c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
494c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static private boolean
495c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isTwoDigitShortCode(Context context, String dialString) {
496ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville        Rlog.d(LOG_TAG, "isTwoDigitShortCode");
497c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
498c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (dialString == null || dialString.length() != 2) return false;
499c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
500c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sTwoDigitNumberPattern == null) {
501c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            sTwoDigitNumberPattern = context.getResources().getStringArray(
502c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    com.android.internal.R.array.config_twoDigitNumberPattern);
503c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
504c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
505c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        for (String dialnumber : sTwoDigitNumberPattern) {
506ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.d(LOG_TAG, "Two Digit Number Pattern " + dialnumber);
507c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (dialString.equals(dialnumber)) {
508ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.d(LOG_TAG, "Two Digit Number Pattern -true");
509c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return true;
510c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
511c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
512ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville        Rlog.d(LOG_TAG, "Two Digit Number Pattern -false");
513c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return false;
514c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
515c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
516c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
517c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Helper function for newFromDialString. Returns true if dialString appears
518c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * to be a short code AND conditions are correct for it to be treated as
519c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * such.
520c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
521c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static private boolean isShortCode(String dialString, GSMPhone phone) {
522c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Refer to TS 22.030 Figure 3.5.3.2:
523c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (dialString == null) {
524c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return false;
525c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
526c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
527c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Illegal dial string characters will give a ZERO length.
528c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // At this point we do not want to crash as any application with
529c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // call privileges may send a non dial string.
530c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // It return false as when the dialString is equal to NULL.
531c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (dialString.length() == 0) {
532c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return false;
533c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
534c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
535f4f5308a309d43fcfca8d0d5fbb54bc38c82ca3fYorke Lee        if (PhoneNumberUtils.isLocalEmergencyNumber(phone.getContext(), dialString)) {
536c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return false;
537c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
538c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return isShortCodeUSSD(dialString, phone);
539c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
540c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
541c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
542c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
543c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Helper function for isShortCode. Returns true if dialString appears to be
544c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * a short code and it is a USSD structure
545c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
546c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * According to the 3PGG TS 22.030 specification Figure 3.5.3.2: A 1 or 2
547c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * digit "short code" is treated as USSD if it is entered while on a call or
548c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * does not satisfy the condition (exactly 2 digits && starts with '1'), there
549c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * are however exceptions to this rule (see below)
550c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
551c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Exception (1) to Call initiation is: If the user of the device is already in a call
552c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * and enters a Short String without any #-key at the end and the length of the Short String is
553c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * equal or less then the MAX_LENGTH_SHORT_CODE [constant that is equal to 2]
554c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
555c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * The phone shall initiate a USSD/SS commands.
556c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
557c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static private boolean isShortCodeUSSD(String dialString, GSMPhone phone) {
55810e574acd0992d22abce257b420d333f5a49e71dJeevaka Badrappan        if (dialString != null && dialString.length() <= MAX_LENGTH_SHORT_CODE) {
559c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (phone.isInCall()) {
56010e574acd0992d22abce257b420d333f5a49e71dJeevaka Badrappan                return true;
561c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
562c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
56310e574acd0992d22abce257b420d333f5a49e71dJeevaka Badrappan            if (dialString.length() != MAX_LENGTH_SHORT_CODE ||
56410e574acd0992d22abce257b420d333f5a49e71dJeevaka Badrappan                    dialString.charAt(0) != '1') {
56510e574acd0992d22abce257b420d333f5a49e71dJeevaka Badrappan                return true;
566c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
567c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
568c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return false;
569c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
570c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
571c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
572c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @return true if the Service Code is PIN/PIN2/PUK/PUK2-related
573c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
5743522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville    boolean isPinPukCommand() {
57522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mSc != null && (mSc.equals(SC_PIN) || mSc.equals(SC_PIN2)
57622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                              || mSc.equals(SC_PUK) || mSc.equals(SC_PUK2));
577c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     }
578c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
579c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
580c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * See TS 22.030 Annex B.
581c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * In temporary mode, to suppress CLIR for a single call, enter:
582c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *      " * 31 # [called number] SEND "
583c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  In temporary mode, to invoke CLIR for a single call enter:
584c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *       " # 31 # [called number] SEND "
585c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
586c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean
587c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isTemporaryModeCLIR() {
58822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mSc != null && mSc.equals(SC_CLIR) && mDialingNumber != null
589c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                && (isActivate() || isDeactivate());
590c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
591c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
592c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
593c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * returns CommandsInterface.CLIR_*
594c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * See also isTemporaryModeCLIR()
595c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
596c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    int
597c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    getCLIRMode() {
59822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mSc != null && mSc.equals(SC_CLIR)) {
599c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (isActivate()) {
600c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return CommandsInterface.CLIR_SUPPRESSION;
601c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else if (isDeactivate()) {
602c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return CommandsInterface.CLIR_INVOCATION;
603c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
604c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
605c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
606c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return CommandsInterface.CLIR_DEFAULT;
607c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
608c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
609c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean isActivate() {
61022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mAction != null && mAction.equals(ACTION_ACTIVATE);
611c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
612c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
613c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean isDeactivate() {
61422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mAction != null && mAction.equals(ACTION_DEACTIVATE);
615c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
616c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
617c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean isInterrogate() {
61822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mAction != null && mAction.equals(ACTION_INTERROGATE);
619c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
620c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
621c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean isRegister() {
62222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mAction != null && mAction.equals(ACTION_REGISTER);
623c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
624c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
625c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean isErasure() {
62622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mAction != null && mAction.equals(ACTION_ERASURE);
627c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
628c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
629c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
630c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Returns true if this is a USSD code that's been submitted to the
631c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * network...eg, after processCode() is called
632c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
633c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public boolean isPendingUSSD() {
63422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mIsPendingUSSD;
635c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
636c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
637cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
638c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public boolean isUssdRequest() {
63922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mIsUssdRequest;
640c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
641c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
642c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Process a MMI code or short code...anything that isn't a dialing number */
643c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    void
644c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    processCode () {
645c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        try {
646c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (isShortCode()) {
647ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.d(LOG_TAG, "isShortCode");
648c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // These just get treated as USSD.
64922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sendUssd(mDialingNumber);
65022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mDialingNumber != null) {
651c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // We should have no dialing numbers here
652c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                throw new RuntimeException ("Invalid or Unsupported MMI Code");
65322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc != null && mSc.equals(SC_CLIP)) {
654ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.d(LOG_TAG, "is CLIP");
655c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isInterrogate()) {
65622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.queryCLIP(
657c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            obtainMessage(EVENT_QUERY_COMPLETE, this));
658c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
659c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException ("Invalid or Unsupported MMI Code");
660c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
66122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc != null && mSc.equals(SC_CLIR)) {
662ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.d(LOG_TAG, "is CLIR");
663c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isActivate()) {
66422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.setCLIR(CommandsInterface.CLIR_INVOCATION,
665c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        obtainMessage(EVENT_SET_COMPLETE, this));
666c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (isDeactivate()) {
66722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.setCLIR(CommandsInterface.CLIR_SUPPRESSION,
668c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        obtainMessage(EVENT_SET_COMPLETE, this));
669c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (isInterrogate()) {
67022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.getCLIR(
671c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        obtainMessage(EVENT_GET_CLIR_COMPLETE, this));
672c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
673c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException ("Invalid or Unsupported MMI Code");
674c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
67522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (isServiceCodeCallForwarding(mSc)) {
676ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.d(LOG_TAG, "is CF");
677c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
67822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                String dialingNumber = mSia;
67922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                int serviceClass = siToServiceClass(mSib);
68022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                int reason = scToCallForwardReason(mSc);
68122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                int time = siToTime(mSic);
682c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
683c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isInterrogate()) {
68422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.queryCallForwardStatus(
685c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            reason, serviceClass,  dialingNumber,
686c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                obtainMessage(EVENT_QUERY_CF_COMPLETE, this));
687c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
688c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    int cfAction;
689c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
690c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    if (isActivate()) {
6915f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        // 3GPP TS 22.030 6.5.2
6925f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        // a call forwarding request with a single * would be
6935f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        // interpreted as registration if containing a forwarded-to
6945f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        // number, or an activation if not
6955f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        if (isEmptyOrNull(dialingNumber)) {
6965f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                            cfAction = CommandsInterface.CF_ACTION_ENABLE;
69722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            mIsCallFwdReg = false;
6985f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        } else {
6995f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                            cfAction = CommandsInterface.CF_ACTION_REGISTRATION;
70022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            mIsCallFwdReg = true;
7015f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        }
702c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else if (isDeactivate()) {
703c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        cfAction = CommandsInterface.CF_ACTION_DISABLE;
704c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else if (isRegister()) {
705c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        cfAction = CommandsInterface.CF_ACTION_REGISTRATION;
706c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else if (isErasure()) {
707c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        cfAction = CommandsInterface.CF_ACTION_ERASURE;
708c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else {
709c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        throw new RuntimeException ("invalid action");
710c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
711c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
712c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    int isSettingUnconditionalVoice =
713c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        (((reason == CommandsInterface.CF_REASON_UNCONDITIONAL) ||
714c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                (reason == CommandsInterface.CF_REASON_ALL)) &&
715c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                (((serviceClass & CommandsInterface.SERVICE_CLASS_VOICE) != 0) ||
716c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                 (serviceClass == CommandsInterface.SERVICE_CLASS_NONE))) ? 1 : 0;
717c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
718c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    int isEnableDesired =
719c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        ((cfAction == CommandsInterface.CF_ACTION_ENABLE) ||
720c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                (cfAction == CommandsInterface.CF_ACTION_REGISTRATION)) ? 1 : 0;
721c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
722ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                    Rlog.d(LOG_TAG, "is CF setCallForward");
72322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.setCallForward(cfAction, reason, serviceClass,
724c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            dialingNumber, time, obtainMessage(
725c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    EVENT_SET_CFF_COMPLETE,
726c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    isSettingUnconditionalVoice,
727c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    isEnableDesired, this));
728c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
72922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (isServiceCodeCallBarring(mSc)) {
730c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sia = password
731c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sib = basic service group
732c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
73322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                String password = mSia;
73422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                int serviceClass = siToServiceClass(mSib);
73522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                String facility = scToBarringFacility(mSc);
736c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
737c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isInterrogate()) {
73822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.queryFacilityLock(facility, password,
739c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            serviceClass, obtainMessage(EVENT_QUERY_COMPLETE, this));
740c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (isActivate() || isDeactivate()) {
74122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.setFacilityLock(facility, isActivate(), password,
742c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            serviceClass, obtainMessage(EVENT_SET_COMPLETE, this));
743c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
744c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException ("Invalid or Unsupported MMI Code");
745c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
746c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
74722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc != null && mSc.equals(SC_PWD)) {
748c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sia = fac
749c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sib = old pwd
750c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sic = new pwd
751c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // pwd = new pwd
752c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                String facility;
75322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                String oldPwd = mSib;
75422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                String newPwd = mSic;
755c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isActivate() || isRegister()) {
756c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // Even though ACTIVATE is acceptable, this is really termed a REGISTER
75722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mAction = ACTION_REGISTER;
758c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
75922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    if (mSia == null) {
760c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // If sc was not specified, treat it as BA_ALL.
761c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        facility = CommandsInterface.CB_FACILITY_BA_ALL;
762c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else {
76322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        facility = scToBarringFacility(mSia);
764c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
76522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    if (newPwd.equals(mPwd)) {
76622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        mPhone.mCi.changeBarringPassword(facility, oldPwd,
767c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                newPwd, obtainMessage(EVENT_SET_COMPLETE, this));
768c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else {
769c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // password mismatch; return error
770c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        handlePasswordError(com.android.internal.R.string.passwordIncorrect);
771c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
772c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
773c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException ("Invalid or Unsupported MMI Code");
774c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
775c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
77622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc != null && mSc.equals(SC_WAIT)) {
777c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sia = basic service group
77822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                int serviceClass = siToServiceClass(mSia);
779c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
780c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isActivate() || isDeactivate()) {
78122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.setCallWaiting(isActivate(), serviceClass,
782c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            obtainMessage(EVENT_SET_COMPLETE, this));
783c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (isInterrogate()) {
78422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.queryCallWaiting(serviceClass,
785c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            obtainMessage(EVENT_QUERY_COMPLETE, this));
786c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
787c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException ("Invalid or Unsupported MMI Code");
788c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
7893522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville            } else if (isPinPukCommand()) {
7903522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                // TODO: This is the same as the code in CmdaMmiCode.java,
7913522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                // MmiCode should be an abstract or base class and this and
7923522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                // other common variables and code should be promoted.
7933522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville
794c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sia = old PIN or PUK
795c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sib = new PIN
796c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sic = new PIN
79722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                String oldPinOrPuk = mSia;
7983522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                String newPinOrPuk = mSib;
7993522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                int pinLen = newPinOrPuk.length();
800c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isRegister()) {
8013522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    if (!newPinOrPuk.equals(mSic)) {
802c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // password mismatch; return error
803c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        handlePasswordError(com.android.internal.R.string.mismatchPin);
804c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else if (pinLen < 4 || pinLen > 8 ) {
805c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // invalid length
806c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        handlePasswordError(com.android.internal.R.string.invalidPin);
8073522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    } else if (mSc.equals(SC_PIN)
8083522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            && mUiccApplication != null
8093522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            && mUiccApplication.getState() == AppState.APPSTATE_PUK) {
810c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // Sim is puk-locked
811c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        handlePasswordError(com.android.internal.R.string.needPuk);
8123522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    } else if (mUiccApplication != null) {
8133522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        Rlog.d(LOG_TAG, "process mmi service code using UiccApp sc=" + mSc);
8143522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville
8153522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        // We have an app and the pre-checks are OK
81622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        if (mSc.equals(SC_PIN)) {
8173522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            mUiccApplication.changeIccLockPassword(oldPinOrPuk, newPinOrPuk,
818c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    obtainMessage(EVENT_SET_COMPLETE, this));
81922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        } else if (mSc.equals(SC_PIN2)) {
8203522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            mUiccApplication.changeIccFdnPassword(oldPinOrPuk, newPinOrPuk,
821c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    obtainMessage(EVENT_SET_COMPLETE, this));
82222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        } else if (mSc.equals(SC_PUK)) {
8233522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            mUiccApplication.supplyPuk(oldPinOrPuk, newPinOrPuk,
824c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    obtainMessage(EVENT_SET_COMPLETE, this));
82522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        } else if (mSc.equals(SC_PUK2)) {
8263522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            mUiccApplication.supplyPuk2(oldPinOrPuk, newPinOrPuk,
827c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    obtainMessage(EVENT_SET_COMPLETE, this));
8283522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        } else {
8293522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            throw new RuntimeException("uicc unsupported service code=" + mSc);
830c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        }
8313522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    } else {
8323522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        throw new RuntimeException("No application mUiccApplicaiton is null");
833c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
834c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
8353522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    throw new RuntimeException ("Ivalid register/action=" + mAction);
836c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
83722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mPoundString != null) {
83822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sendUssd(mPoundString);
839c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
840c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                throw new RuntimeException ("Invalid or Unsupported MMI Code");
841c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
842c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } catch (RuntimeException exc) {
84322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.FAILED;
84422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mMessage = mContext.getText(com.android.internal.R.string.mmiError);
84522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mPhone.onMMIDone(this);
846c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
847c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
848c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
849c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void handlePasswordError(int res) {
85022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mState = State.FAILED;
851c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder(getScString());
852c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("\n");
85322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        sb.append(mContext.getText(res));
85422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mMessage = sb;
85522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mPhone.onMMIDone(this);
856c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
857c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
858c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
859c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Called from GSMPhone
860c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
861c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * An unsolicited USSD NOTIFY or REQUEST has come in matching
862c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * up with this pending USSD request
863c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
864c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Note: If REQUEST, this exchange is complete, but the session remains
865c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *       active (ie, the network expects user input).
866c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
867c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    void
868c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    onUssdFinished(String ussdMessage, boolean isUssdRequest) {
86922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mState == State.PENDING) {
870c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (ussdMessage == null) {
87122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mMessage = mContext.getText(com.android.internal.R.string.mmiComplete);
872c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
87322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mMessage = ussdMessage;
874c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
87522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mIsUssdRequest = isUssdRequest;
876c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // If it's a request, leave it PENDING so that it's cancelable.
877c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (!isUssdRequest) {
87822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mState = State.COMPLETE;
879c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
880c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
88122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mPhone.onMMIDone(this);
882c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
883c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
884c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
885c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
886c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Called from GSMPhone
887c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
888c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * The radio has reset, and this is still pending
889c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
890c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
891c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    void
892c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    onUssdFinishedError() {
89322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mState == State.PENDING) {
89422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.FAILED;
89522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mMessage = mContext.getText(com.android.internal.R.string.mmiError);
896c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
89722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mPhone.onMMIDone(this);
898c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
899c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
900c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
901c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    void sendUssd(String ussdMessage) {
902c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Treat this as a USSD string
90322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mIsPendingUSSD = true;
904c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
905c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Note that unlike most everything else, the USSD complete
906c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // response does not complete this MMI code...we wait for
907c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // an unsolicited USSD "Notify" or "Request".
908c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // The matching up of this is done in GSMPhone.
909c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
91022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mPhone.mCi.sendUSSD(ussdMessage,
911c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            obtainMessage(EVENT_USSD_COMPLETE, this));
912c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
913c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
914c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Called from GSMPhone.handleMessage; not a Handler subclass */
915cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
916c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void
917c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    handleMessage (Message msg) {
918c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        AsyncResult ar;
919c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
920c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        switch (msg.what) {
921c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_SET_COMPLETE:
922c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
923c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
9243522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                onSetComplete(msg, ar);
925c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
926c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
927c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_SET_CFF_COMPLETE:
928c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
929c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
930c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                /*
931c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                * msg.arg1 = 1 means to set unconditional voice call forwarding
932c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                * msg.arg2 = 1 means to enable voice call forwarding
933c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                */
934c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if ((ar.exception == null) && (msg.arg1 == 1)) {
935c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    boolean cffEnabled = (msg.arg2 == 1);
936e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    if (mIccRecords != null) {
93731ae682ff511ddde4073c3f94eff15da2f7fade6Wink Saville                        mIccRecords.setVoiceCallForwardingFlag(1, cffEnabled, mDialingNumber);
938bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                    }
939c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
940c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
9413522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                onSetComplete(msg, ar);
942c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
943c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
944c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_GET_CLIR_COMPLETE:
945c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
946c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                onGetClirComplete(ar);
947c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
948c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
949c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_QUERY_CF_COMPLETE:
950c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
951c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                onQueryCfComplete(ar);
952c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
953c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
954c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_QUERY_COMPLETE:
955c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
956c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                onQueryComplete(ar);
957c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
958c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
959c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_USSD_COMPLETE:
960c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
961c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
962c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (ar.exception != null) {
96322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mState = State.FAILED;
96422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mMessage = getErrorMessage(ar);
965c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
96622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.onMMIDone(this);
967c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
968c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
969c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // Note that unlike most everything else, the USSD complete
970c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // response does not complete this MMI code...we wait for
971c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // an unsolicited USSD "Notify" or "Request".
972c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // The matching up of this is done in GSMPhone.
973c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
974c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
975c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
976c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_USSD_CANCEL_COMPLETE:
97722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mPhone.onMMIDone(this);
978c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
979c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
980c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
981c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Private instance methods
982c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
983c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence getErrorMessage(AsyncResult ar) {
984c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
985c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (ar.exception instanceof CommandException) {
986c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            CommandException.Error err = ((CommandException)(ar.exception)).getCommandError();
987c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (err == CommandException.Error.FDN_CHECK_FAILURE) {
988ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.i(LOG_TAG, "FDN_CHECK_FAILURE");
98922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.mmiFdnError);
990c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
991c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
992c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
99322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mContext.getText(com.android.internal.R.string.mmiError);
994c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
995c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
996c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence getScString() {
99722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mSc != null) {
99822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            if (isServiceCodeCallBarring(mSc)) {
99922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.BaMmi);
100022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (isServiceCodeCallForwarding(mSc)) {
100122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.CfMmi);
100222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc.equals(SC_CLIP)) {
100322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.ClipMmi);
100422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc.equals(SC_CLIR)) {
100522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.ClirMmi);
100622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc.equals(SC_PWD)) {
100722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.PwdMmi);
100822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc.equals(SC_WAIT)) {
100922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.CwMmi);
10103522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville            } else if (isPinPukCommand()) {
101122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.PinMmi);
1012c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1013c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1014c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1015c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return "";
1016c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1017c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1018c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void
10193522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville    onSetComplete(Message msg, AsyncResult ar){
1020c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder(getScString());
1021c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("\n");
1022c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1023c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (ar.exception != null) {
102422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.FAILED;
1025c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (ar.exception instanceof CommandException) {
1026c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                CommandException.Error err = ((CommandException)(ar.exception)).getCommandError();
1027c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (err == CommandException.Error.PASSWORD_INCORRECT) {
10283522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    if (isPinPukCommand()) {
1029c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // look specifically for the PUK commands and adjust
1030c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // the message accordingly.
103122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        if (mSc.equals(SC_PUK) || mSc.equals(SC_PUK2)) {
103222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1033c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.badPuk));
1034c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        } else {
103522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1036c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.badPin));
1037c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        }
10383522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        // Get the No. of retries remaining to unlock PUK/PUK2
10393522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        int attemptsRemaining = msg.arg1;
10406d3c836bb8991e9cf7ffb322ebabf48c2446126dWink Saville                        if (attemptsRemaining <= 0) {
10416d3c836bb8991e9cf7ffb322ebabf48c2446126dWink Saville                            Rlog.d(LOG_TAG, "onSetComplete: PUK locked,"
10426d3c836bb8991e9cf7ffb322ebabf48c2446126dWink Saville                                    + " cancel as lock screen will handle this");
10436d3c836bb8991e9cf7ffb322ebabf48c2446126dWink Saville                            mState = State.CANCELLED;
10446d3c836bb8991e9cf7ffb322ebabf48c2446126dWink Saville                        } else if (attemptsRemaining > 0) {
10456d3c836bb8991e9cf7ffb322ebabf48c2446126dWink Saville                            Rlog.d(LOG_TAG, "onSetComplete: attemptsRemaining="+attemptsRemaining);
10463522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            sb.append(mContext.getResources().getQuantityString(
10473522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                                    com.android.internal.R.plurals.pinpuk_attempts,
10483522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                                    attemptsRemaining, attemptsRemaining));
10493522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        }
1050c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else {
105122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        sb.append(mContext.getText(
1052c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                com.android.internal.R.string.passwordIncorrect));
1053c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
1054c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (err == CommandException.Error.SIM_PUK2) {
105522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(
1056c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            com.android.internal.R.string.badPin));
1057c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    sb.append("\n");
105822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(
1059c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            com.android.internal.R.string.needPuk2));
10603522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                } else if (err == CommandException.Error.REQUEST_NOT_SUPPORTED) {
10613522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    if (mSc.equals(SC_PIN)) {
10623522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        sb.append(mContext.getText(com.android.internal.R.string.enablePin));
10633522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    }
1064c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (err == CommandException.Error.FDN_CHECK_FAILURE) {
1065ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                    Rlog.i(LOG_TAG, "FDN_CHECK_FAILURE");
106622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(com.android.internal.R.string.mmiFdnError));
1067c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
106822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(
1069c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            com.android.internal.R.string.mmiError));
1070c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
1071c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
107222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sb.append(mContext.getText(
1073c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.mmiError));
1074c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1075c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isActivate()) {
107622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.COMPLETE;
107722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            if (mIsCallFwdReg) {
107822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sb.append(mContext.getText(
10795f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        com.android.internal.R.string.serviceRegistered));
10805f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li            } else {
108122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sb.append(mContext.getText(
10825f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        com.android.internal.R.string.serviceEnabled));
10835f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li            }
1084c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // Record CLIR setting
108522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            if (mSc.equals(SC_CLIR)) {
108622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mPhone.saveClirSetting(CommandsInterface.CLIR_INVOCATION);
1087c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1088c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isDeactivate()) {
108922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.COMPLETE;
109022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            sb.append(mContext.getText(
1091c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    com.android.internal.R.string.serviceDisabled));
1092c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // Record CLIR setting
109322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            if (mSc.equals(SC_CLIR)) {
109422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mPhone.saveClirSetting(CommandsInterface.CLIR_SUPPRESSION);
1095c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1096c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isRegister()) {
109722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.COMPLETE;
109822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            sb.append(mContext.getText(
1099c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    com.android.internal.R.string.serviceRegistered));
1100c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isErasure()) {
110122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.COMPLETE;
110222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            sb.append(mContext.getText(
1103c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    com.android.internal.R.string.serviceErased));
1104c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
110522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.FAILED;
110622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            sb.append(mContext.getText(
1107c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    com.android.internal.R.string.mmiError));
1108c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1109c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
111022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mMessage = sb;
111122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mPhone.onMMIDone(this);
1112c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1113c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1114c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void
1115c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    onGetClirComplete(AsyncResult ar) {
1116c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder(getScString());
1117c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("\n");
1118c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1119c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (ar.exception != null) {
112022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.FAILED;
1121c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            sb.append(getErrorMessage(ar));
1122c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
1123c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            int clirArgs[];
1124c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1125c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            clirArgs = (int[])ar.result;
1126c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1127c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // the 'm' parameter from TS 27.007 7.7
1128c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            switch (clirArgs[1]) {
1129c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 0: // CLIR not provisioned
113022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(
1131c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                com.android.internal.R.string.serviceNotProvisioned));
113222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mState = State.COMPLETE;
1133c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1134c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1135c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 1: // CLIR provisioned in permanent mode
113622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(
1137c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                com.android.internal.R.string.CLIRPermanent));
113822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mState = State.COMPLETE;
1139c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1140c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1141c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 2: // unknown (e.g. no network, etc.)
114222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(
1143c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                com.android.internal.R.string.mmiError));
114422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mState = State.FAILED;
1145c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1146c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1147c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 3: // CLIR temporary mode presentation restricted
1148c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1149c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // the 'n' parameter from TS 27.007 7.7
1150c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    switch (clirArgs[0]) {
1151c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        default:
1152c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 0: // Default
115322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1154c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOnNextCallOn));
1155c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1156c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 1: // CLIR invocation
115722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1158c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOnNextCallOn));
1159c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1160c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 2: // CLIR suppression
116122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1162c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOnNextCallOff));
1163c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1164c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
116522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mState = State.COMPLETE;
1166c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1167c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1168c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 4: // CLIR temporary mode presentation allowed
1169c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // the 'n' parameter from TS 27.007 7.7
1170c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    switch (clirArgs[0]) {
1171c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        default:
1172c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 0: // Default
117322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1174c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOffNextCallOff));
1175c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1176c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 1: // CLIR invocation
117722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1178c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOffNextCallOn));
1179c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1180c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 2: // CLIR suppression
118122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1182c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOffNextCallOff));
1183c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1184c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
1185c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
118622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mState = State.COMPLETE;
1187c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1188c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1189c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1190c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
119122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mMessage = sb;
119222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mPhone.onMMIDone(this);
1193c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1194c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1195c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
1196c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param serviceClass 1 bit of the service class bit vectory
1197c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @return String to be used for call forward query MMI response text.
1198c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *        Returns null if unrecognized
1199c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
1200c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1201c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence
1202c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    serviceClassToCFString (int serviceClass) {
1203c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        switch (serviceClass) {
1204c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_VOICE:
120522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassVoice);
1206c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_DATA:
120722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassData);
1208c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_FAX:
120922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassFAX);
1210c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_SMS:
121122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassSMS);
1212c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_DATA_SYNC:
121322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassDataSync);
1214c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_DATA_ASYNC:
121522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassDataAsync);
1216c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_PACKET:
121722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassPacket);
1218c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_PAD:
121922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassPAD);
1220c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            default:
1221c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return null;
1222c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1223c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1224c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1225c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1226c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** one CallForwardInfo + serviceClassMask -> one line of text */
1227c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence
1228c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    makeCFQueryResultMessage(CallForwardInfo info, int serviceClassMask) {
1229c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        CharSequence template;
1230c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        String sources[] = {"{0}", "{1}", "{2}"};
1231c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        CharSequence destinations[] = new CharSequence[3];
1232c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        boolean needTimeTemplate;
1233c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1234c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // CF_REASON_NO_REPLY also has a time value associated with
1235c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // it. All others don't.
1236c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1237c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        needTimeTemplate =
1238c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            (info.reason == CommandsInterface.CF_REASON_NO_REPLY);
1239c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1240c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (info.status == 1) {
1241c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (needTimeTemplate) {
124222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                template = mContext.getText(
1243c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.cfTemplateForwardedTime);
1244c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
124522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                template = mContext.getText(
1246c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.cfTemplateForwarded);
1247c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1248c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (info.status == 0 && isEmptyOrNull(info.number)) {
124922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            template = mContext.getText(
1250c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.cfTemplateNotForwarded);
1251c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else { /* (info.status == 0) && !isEmptyOrNull(info.number) */
1252c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // A call forward record that is not active but contains
1253c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // a phone number is considered "registered"
1254c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1255c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (needTimeTemplate) {
125622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                template = mContext.getText(
1257c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.cfTemplateRegisteredTime);
1258c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
125922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                template = mContext.getText(
1260c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.cfTemplateRegistered);
1261c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1262c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1263c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1264c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // In the template (from strings.xmls)
1265c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        //         {0} is one of "bearerServiceCode*"
1266c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        //        {1} is dialing number
1267c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        //      {2} is time in seconds
1268c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1269c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        destinations[0] = serviceClassToCFString(info.serviceClass & serviceClassMask);
12708697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlsson        destinations[1] = formatLtr(
12718697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlsson                PhoneNumberUtils.stringFromStringAndTOA(info.number, info.toa));
1272c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        destinations[2] = Integer.toString(info.timeSeconds);
1273c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1274c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (info.reason == CommandsInterface.CF_REASON_UNCONDITIONAL &&
1275c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                (info.serviceClass & serviceClassMask)
1276c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        == CommandsInterface.SERVICE_CLASS_VOICE) {
1277c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            boolean cffEnabled = (info.status == 1);
1278e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (mIccRecords != null) {
127931ae682ff511ddde4073c3f94eff15da2f7fade6Wink Saville                mIccRecords.setVoiceCallForwardingFlag(1, cffEnabled, info.number);
1280bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka            }
1281c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1282c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1283c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return TextUtils.replace(template, sources, destinations);
1284c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1285c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
12868697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlsson    /**
12878697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlsson     * Used to format a string that should be displayed as LTR even in RTL locales
12888697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlsson     */
12898697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlsson    private String formatLtr(String str) {
12908697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlsson        BidiFormatter fmt = BidiFormatter.getInstance();
12918697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlsson        return str == null ? str : fmt.unicodeWrap(str, TextDirectionHeuristics.LTR, true);
12928697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlsson    }
1293c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1294c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void
1295c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    onQueryCfComplete(AsyncResult ar) {
1296c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder(getScString());
1297c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("\n");
1298c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1299c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (ar.exception != null) {
130022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.FAILED;
1301c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            sb.append(getErrorMessage(ar));
1302c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
1303c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            CallForwardInfo infos[];
1304c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1305c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            infos = (CallForwardInfo[]) ar.result;
1306c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1307c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (infos.length == 0) {
1308c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // Assume the default is not active
130922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sb.append(mContext.getText(com.android.internal.R.string.serviceDisabled));
1310c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1311c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // Set unconditional CFF in SIM to false
1312e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if (mIccRecords != null) {
131331ae682ff511ddde4073c3f94eff15da2f7fade6Wink Saville                    mIccRecords.setVoiceCallForwardingFlag(1, false, null);
1314bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                }
1315c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
1316c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1317c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                SpannableStringBuilder tb = new SpannableStringBuilder();
1318c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1319c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // Each bit in the service class gets its own result line
1320c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // The service classes may be split up over multiple
1321c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // CallForwardInfos. So, for each service class, find out
1322c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // which CallForwardInfo represents it and then build
1323c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // the response text based on that
1324c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1325c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                for (int serviceClassMask = 1
1326c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            ; serviceClassMask <= SERVICE_CLASS_MAX
1327c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            ; serviceClassMask <<= 1
1328c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ) {
1329c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    for (int i = 0, s = infos.length; i < s ; i++) {
1330c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        if ((serviceClassMask & infos[i].serviceClass) != 0) {
1331c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            tb.append(makeCFQueryResultMessage(infos[i],
1332c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                            serviceClassMask));
1333c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            tb.append("\n");
1334c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        }
1335c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
1336c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
1337c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sb.append(tb);
1338c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1339c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
134022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.COMPLETE;
1341c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1342c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
134322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mMessage = sb;
134422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mPhone.onMMIDone(this);
1345c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1346c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1347c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1348c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void
1349c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    onQueryComplete(AsyncResult ar) {
1350c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder(getScString());
1351c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("\n");
1352c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1353c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (ar.exception != null) {
135422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.FAILED;
1355c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            sb.append(getErrorMessage(ar));
1356c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
1357c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            int[] ints = (int[])ar.result;
1358c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1359c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (ints.length != 0) {
1360c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (ints[0] == 0) {
136122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(com.android.internal.R.string.serviceDisabled));
136222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                } else if (mSc.equals(SC_WAIT)) {
1363c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // Call Waiting includes additional data in the response.
1364c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    sb.append(createQueryCallWaitingResultMessage(ints[1]));
136522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                } else if (isServiceCodeCallBarring(mSc)) {
1366c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // ints[0] for Call Barring is a bit vector of services
1367c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    sb.append(createQueryCallBarringResultMessage(ints[0]));
1368c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (ints[0] == 1) {
1369c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // for all other services, treat it as a boolean
137022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(com.android.internal.R.string.serviceEnabled));
1371c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
137222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(com.android.internal.R.string.mmiError));
1373c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
1374c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
137522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sb.append(mContext.getText(com.android.internal.R.string.mmiError));
1376c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
137722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.COMPLETE;
1378c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1379c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
138022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mMessage = sb;
138122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mPhone.onMMIDone(this);
1382c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1383c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1384c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence
1385c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    createQueryCallWaitingResultMessage(int serviceClass) {
1386c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb =
138722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                new StringBuilder(mContext.getText(com.android.internal.R.string.serviceEnabledFor));
1388c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1389c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        for (int classMask = 1
1390c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    ; classMask <= SERVICE_CLASS_MAX
1391c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    ; classMask <<= 1
1392c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        ) {
1393c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if ((classMask & serviceClass) != 0) {
1394c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sb.append("\n");
1395c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sb.append(serviceClassToCFString(classMask & serviceClass));
1396c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1397c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1398c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return sb;
1399c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1400c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence
1401c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    createQueryCallBarringResultMessage(int serviceClass)
1402c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    {
140322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        StringBuilder sb = new StringBuilder(mContext.getText(com.android.internal.R.string.serviceEnabledFor));
1404c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1405c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        for (int classMask = 1
1406c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    ; classMask <= SERVICE_CLASS_MAX
1407c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    ; classMask <<= 1
1408c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        ) {
1409c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if ((classMask & serviceClass) != 0) {
1410c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sb.append("\n");
1411c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sb.append(serviceClassToCFString(classMask & serviceClass));
1412c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1413c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1414c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return sb;
1415c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1416c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1417c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /***
1418c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * TODO: It would be nice to have a method here that can take in a dialstring and
1419c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * figure out if there is an MMI code embedded within it.  This code would replace
1420c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * some of the string parsing functionality in the Phone App's
1421c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * SpecialCharSequenceMgr class.
1422c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
1423c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1424c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
1425c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public String toString() {
1426c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder("GsmMmiCode {");
1427c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1428c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("State=" + getState());
142922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mAction != null) sb.append(" action=" + mAction);
143022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mSc != null) sb.append(" sc=" + mSc);
143122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mSia != null) sb.append(" sia=" + mSia);
143222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mSib != null) sb.append(" sib=" + mSib);
143322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mSic != null) sb.append(" sic=" + mSic);
143422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mPoundString != null) sb.append(" poundString=" + mPoundString);
143522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mDialingNumber != null) sb.append(" dialingNumber=" + mDialingNumber);
143622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mPwd != null) sb.append(" pwd=" + mPwd);
1437c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("}");
1438c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return sb.toString();
1439c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1440c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville}
1441