GsmMmiCode.java revision 58dd6858dc8013b680ea003d22063fd65ed5fe1c
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.*;
3509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahujaimport com.android.internal.telephony.gsm.SsData;
36c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
37c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport java.util.regex.Pattern;
38c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport java.util.regex.Matcher;
39c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
40c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/**
41c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * The motto for this file is:
42c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
43c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * "NOTE:    By using the # as a separator, most cases are expected to be unambiguous."
44c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *   -- TS 22.030 6.5.2
45c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
46c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * {@hide}
47c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
48c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */
49c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savillepublic final class GsmMmiCode extends Handler implements MmiCode {
50cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    static final String LOG_TAG = "GsmMmiCode";
51c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
52c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Constants
53c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
54c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Max Size of the Short Code (aka Short String from TS 22.030 6.5.2)
55c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MAX_LENGTH_SHORT_CODE = 2;
56c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
57c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // TS 22.030 6.5.2 Every Short String USSD command will end with #-key
58c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // (known as #-String)
59c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final char END_OF_USSD_COMMAND = '#';
60c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
61c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // From TS 22.030 6.5.2
62c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String ACTION_ACTIVATE = "*";
63c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String ACTION_DEACTIVATE = "#";
64c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String ACTION_INTERROGATE = "*#";
65c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String ACTION_REGISTER = "**";
66c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String ACTION_ERASURE = "##";
67c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
68c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Supp Service codes from TS 22.030 Annex B
69c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
70c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //Called line presentation
71c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CLIP    = "30";
72c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CLIR    = "31";
73c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
74c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Call Forwarding
75c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CFU     = "21";
76c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CFB     = "67";
77c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CFNRy   = "61";
78c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CFNR    = "62";
79c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
80c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CF_All = "002";
81c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_CF_All_Conditional = "004";
82c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
83c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Call Waiting
84c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_WAIT     = "43";
85c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
86c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Call Barring
87c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BAOC         = "33";
88c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BAOIC        = "331";
89c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BAOICxH      = "332";
90c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BAIC         = "35";
91c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BAICr        = "351";
92c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
93c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BA_ALL       = "330";
94c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BA_MO        = "333";
95c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_BA_MT        = "353";
96c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
97c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // Supp Service Password registration
98c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_PWD          = "03";
99c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
100c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // PIN/PIN2/PUK/PUK2
101c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_PIN          = "04";
102c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_PIN2         = "042";
103c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_PUK          = "05";
104c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String SC_PUK2         = "052";
105c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
106c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Event Constants
107c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
108c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_SET_COMPLETE         = 1;
109c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_GET_CLIR_COMPLETE    = 2;
110c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_QUERY_CF_COMPLETE    = 3;
111c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_USSD_COMPLETE        = 4;
112c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_QUERY_COMPLETE       = 5;
113c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_SET_CFF_COMPLETE     = 6;
114c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int EVENT_USSD_CANCEL_COMPLETE = 7;
115c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
116c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Instance Variables
117c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1183a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    GsmCdmaPhone mPhone;
11922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    Context mContext;
120e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    UiccCardApplication mUiccApplication;
121e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    IccRecords mIccRecords;
122c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
12322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    String mAction;              // One of ACTION_*
12422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    String mSc;                  // Service Code
12522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    String mSia, mSib, mSic;       // Service Info a,b,c
12622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    String mPoundString;         // Entire MMI string up to and including #
1273a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    public String mDialingNumber;
12822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    String mPwd;                 // For password registration
129c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
130c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Set to true in processCode, not at newFromDialString time */
13122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    private boolean mIsPendingUSSD;
132c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
13322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    private boolean mIsUssdRequest;
134c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
13522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    private boolean mIsCallFwdReg;
13622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    State mState = State.PENDING;
13722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    CharSequence mMessage;
13809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja    private boolean mIsSsInfo = false;
13909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja
140c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
141c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Class Variables
142c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
143c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
144c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // See TS 22.030 6.5.2 "Structure of the MMI"
145c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
146c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static Pattern sPatternSuppService = Pattern.compile(
1479225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang        "((\\*|#|\\*#|\\*\\*|##)(\\d{2,3})(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*))?)?)?)?#)(.*)");
148c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/*       1  2                    3          4  5       6   7         8    9     10  11             12
149c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
150c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         1 = Full string up to and including #
151c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         2 = action (activation/interrogation/registration/erasure)
152c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         3 = service code
153c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         5 = SIA
154c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         7 = SIB
155c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         9 = SIC
1569225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang         10 = dialing number
157c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville*/
158c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
159c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_POUND_STRING = 1;
160c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
161c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_ACTION = 2;
162c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        //(activation/interrogation/registration/erasure)
163c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
164c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_SERVICE_CODE = 3;
165c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_SIA = 5;
166c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_SIB = 7;
167c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_SIC = 9;
168c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_PWD_CONFIRM = 11;
169c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final int MATCH_GROUP_DIALING_NUMBER = 12;
170c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static private String[] sTwoDigitNumberPattern;
171c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
172c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Public Class methods
173c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
174c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
175c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Some dial strings in GSM are defined to do non-call setup
176c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * things, such as modify or query supplementary service settings (eg, call
177c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * forwarding). These are generally referred to as "MMI codes".
178c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * We look to see if the dial string contains a valid MMI code (potentially
179c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * with a dial string at the end as well) and return info here.
180c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
181c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * If the dial string contains no MMI code, we return an instance with
182c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * only "dialingNumber" set
183c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
184c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Please see flow chart in TS 22.030 6.5.3.2
185c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
186c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1873a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    public static GsmMmiCode
1883a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    newFromDialString(String dialString, GsmCdmaPhone phone, UiccCardApplication app) {
189c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        Matcher m;
190c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        GsmMmiCode ret = null;
191c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
192c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        m = sPatternSuppService.matcher(dialString);
193c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
194c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Is this formatted like a standard supplementary service code?
195c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (m.matches()) {
196e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            ret = new GsmMmiCode(phone, app);
19722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mPoundString = makeEmptyNull(m.group(MATCH_GROUP_POUND_STRING));
19822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mAction = makeEmptyNull(m.group(MATCH_GROUP_ACTION));
19922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mSc = makeEmptyNull(m.group(MATCH_GROUP_SERVICE_CODE));
20022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mSia = makeEmptyNull(m.group(MATCH_GROUP_SIA));
20122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mSib = makeEmptyNull(m.group(MATCH_GROUP_SIB));
20222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mSic = makeEmptyNull(m.group(MATCH_GROUP_SIC));
20322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mPwd = makeEmptyNull(m.group(MATCH_GROUP_PWD_CONFIRM));
20422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mDialingNumber = makeEmptyNull(m.group(MATCH_GROUP_DIALING_NUMBER));
2059225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            // According to TS 22.030 6.5.2 "Structure of the MMI",
2069225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            // the dialing number should not ending with #.
2079225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            // The dialing number ending # is treated as unique USSD,
2089225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            // eg, *400#16 digit number# to recharge the prepaid card
2099225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            // in India operator(Mumbai MTNL)
21022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            if(ret.mDialingNumber != null &&
21122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    ret.mDialingNumber.endsWith("#") &&
2129225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang                    dialString.endsWith("#")){
2139225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang                ret = new GsmMmiCode(phone, app);
21422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                ret.mPoundString = dialString;
2159225578f29e449d30380fcf71defb1ac7e8a59dbJohn Wang            }
216c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (dialString.endsWith("#")) {
217c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // TS 22.030 sec 6.5.3.2
218c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // "Entry of any characters defined in the 3GPP TS 23.038 [8] Default Alphabet
219c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // (up to the maximum defined in 3GPP TS 24.080 [10]), followed by #SEND".
220c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
221e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            ret = new GsmMmiCode(phone, app);
22222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mPoundString = dialString;
223c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isTwoDigitShortCode(phone.getContext(), dialString)) {
224c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            //Is a country-specific exception to short codes as defined in TS 22.030, 6.5.3.2
225c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ret = null;
226c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isShortCode(dialString, phone)) {
227c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // this may be a short code, as defined in TS 22.030, 6.5.3.2
228e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            ret = new GsmMmiCode(phone, app);
22922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mDialingNumber = dialString;
230c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
231c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
232c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return ret;
233c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
234c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
2353a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    public static GsmMmiCode
2363a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    newNetworkInitiatedUssd(String ussdMessage,
2373a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan                            boolean isUssdRequest, GsmCdmaPhone phone, UiccCardApplication app) {
238c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        GsmMmiCode ret;
239c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
240e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        ret = new GsmMmiCode(phone, app);
241c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
24222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        ret.mMessage = ussdMessage;
24322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        ret.mIsUssdRequest = isUssdRequest;
244c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
245c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // If it's a request, set to PENDING so that it's cancelable.
246c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (isUssdRequest) {
24722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mIsPendingUSSD = true;
24822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mState = State.PENDING;
249c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
25022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            ret.mState = State.COMPLETE;
251c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
252c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
253c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return ret;
254c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
255c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
2563a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    public static GsmMmiCode newFromUssdUserInput(String ussdMessge,
2573a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan                                                  GsmCdmaPhone phone,
2583a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan                                                  UiccCardApplication app) {
259e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        GsmMmiCode ret = new GsmMmiCode(phone, app);
260c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
26122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        ret.mMessage = ussdMessge;
26222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        ret.mState = State.PENDING;
26322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        ret.mIsPendingUSSD = true;
264c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
265c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return ret;
266c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
267c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
26809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja    /** Process SS Data */
2693a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    public void
27009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja    processSsData(AsyncResult data) {
27109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        Rlog.d(LOG_TAG, "In processSsData");
27209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja
27309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        mIsSsInfo = true;
27409b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        try {
27509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            SsData ssData = (SsData)data.result;
27609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            parseSsData(ssData);
27709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        } catch (ClassCastException ex) {
27809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            Rlog.e(LOG_TAG, "Class Cast Exception in parsing SS Data : " + ex);
27909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        } catch (NullPointerException ex) {
28009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            Rlog.e(LOG_TAG, "Null Pointer Exception in parsing SS Data : " + ex);
28109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        }
28209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja    }
28309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja
28409b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja    void parseSsData(SsData ssData) {
28509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        CommandException ex;
28609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja
28709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        ex = CommandException.fromRilErrno(ssData.result);
28809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        mSc = getScStringFromScType(ssData.serviceType);
28909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        mAction = getActionStringFromReqType(ssData.requestType);
29009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        Rlog.d(LOG_TAG, "parseSsData msc = " + mSc + ", action = " + mAction + ", ex = " + ex);
29109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja
29209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        switch (ssData.requestType) {
29309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_ACTIVATION:
29409b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_DEACTIVATION:
29509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_REGISTRATION:
29609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_ERASURE:
29709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                if ((ssData.result == RILConstants.SUCCESS) &&
29809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                      ssData.serviceType.isTypeUnConditional()) {
29909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                    /*
30009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                     * When ServiceType is SS_CFU/SS_CF_ALL and RequestType is activate/register
30109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                     * and ServiceClass is Voice/None, set IccRecords.setVoiceCallForwardingFlag.
30209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                     * Only CF status can be set here since number is not available.
30309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                     */
30409b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                    boolean cffEnabled = ((ssData.requestType == SsData.RequestType.SS_ACTIVATION ||
30509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                            ssData.requestType == SsData.RequestType.SS_REGISTRATION) &&
30609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                            isServiceClassVoiceorNone(ssData.serviceClass));
30709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja
30809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                    Rlog.d(LOG_TAG, "setVoiceCallForwardingFlag cffEnabled: " + cffEnabled);
309a1fd99a6910a97470cab01fbc28bfea82e832dabNarayan Kamath                    if (mIccRecords != null) {
310eadee84166d397b6425cfd56f89fa1569f6a93f5Amit Mahajan                        mPhone.setVoiceCallForwardingFlag(1, cffEnabled, null);
31109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                        Rlog.d(LOG_TAG, "setVoiceCallForwardingFlag done from SS Info.");
31209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                    } else {
31309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                        Rlog.e(LOG_TAG, "setVoiceCallForwardingFlag aborted. sim records is null.");
31409b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                    }
31509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                }
31609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                onSetComplete(null, new AsyncResult(null, ssData.cfInfo, ex));
31709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                break;
31809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_INTERROGATION:
31909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                if (ssData.serviceType.isTypeClir()) {
32009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                    Rlog.d(LOG_TAG, "CLIR INTERROGATION");
32109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                    onGetClirComplete(new AsyncResult(null, ssData.ssInfo, ex));
32209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                } else if (ssData.serviceType.isTypeCF()) {
32309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                    Rlog.d(LOG_TAG, "CALL FORWARD INTERROGATION");
32409b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                    onQueryCfComplete(new AsyncResult(null, ssData.cfInfo, ex));
32509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                } else {
32609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                    onQueryComplete(new AsyncResult(null, ssData.ssInfo, ex));
32709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                }
32809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                break;
32909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            default:
33009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                Rlog.e(LOG_TAG, "Invaid requestType in SSData : " + ssData.requestType);
33109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                break;
33209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        }
33309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja    }
33409b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja
33509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja    private String getScStringFromScType(SsData.ServiceType sType) {
33609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        switch (sType) {
33709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_CFU:
33809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_CFU;
33909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_CF_BUSY:
34009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_CFB;
34109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_CF_NO_REPLY:
34209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_CFNRy;
34309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_CF_NOT_REACHABLE:
34409b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_CFNR;
34509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_CF_ALL:
34609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_CF_All;
34709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_CF_ALL_CONDITIONAL:
34809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_CF_All_Conditional;
34909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_CLIP:
35009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_CLIP;
35109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_CLIR:
35209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_CLIR;
35309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_WAIT:
35409b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_WAIT;
35509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_BAOC:
35609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_BAOC;
35709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_BAOIC:
35809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_BAOIC;
35909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_BAOIC_EXC_HOME:
36009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_BAOICxH;
36109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_BAIC:
36209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_BAIC;
36309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_BAIC_ROAMING:
36409b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_BAICr;
36509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_ALL_BARRING:
36609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_BA_ALL;
36709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_OUTGOING_BARRING:
36809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_BA_MO;
36909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_INCOMING_BARRING:
37009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return SC_BA_MT;
37109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        }
37209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja
37309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        return "";
37409b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja    }
37509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja
37609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja    private String getActionStringFromReqType(SsData.RequestType rType) {
37709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        switch (rType) {
37809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_ACTIVATION:
37909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return ACTION_ACTIVATE;
38009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_DEACTIVATION:
38109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return ACTION_DEACTIVATE;
38209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_INTERROGATION:
38309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return ACTION_INTERROGATE;
38409b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_REGISTRATION:
38509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return ACTION_REGISTER;
38609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            case SS_ERASURE:
38709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return ACTION_ERASURE;
38809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        }
38909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja
39009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        return "";
39109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja    }
39209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja
39309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja    private boolean isServiceClassVoiceorNone(int serviceClass) {
39409b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        return (((serviceClass & CommandsInterface.SERVICE_CLASS_VOICE) != 0) ||
39509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                (serviceClass == CommandsInterface.SERVICE_CLASS_NONE));
39609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja    }
39709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja
398c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Private Class methods
399c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
400c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** make empty strings be null.
401c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  Regexp returns empty strings for empty groups
402c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
403c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static String
404c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    makeEmptyNull (String s) {
405c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (s != null && s.length() == 0) return null;
406c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
407c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return s;
408c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
409c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
410c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** returns true of the string is empty or null */
411c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static boolean
412c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isEmptyOrNull(CharSequence s) {
413c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return s == null || (s.length() == 0);
414c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
415c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
416c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
417c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static int
418c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    scToCallForwardReason(String sc) {
419c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sc == null) {
420c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            throw new RuntimeException ("invalid call forward sc");
421c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
422c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
423c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sc.equals(SC_CF_All)) {
424c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville           return CommandsInterface.CF_REASON_ALL;
425c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_CFU)) {
426c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CF_REASON_UNCONDITIONAL;
427c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_CFB)) {
428c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CF_REASON_BUSY;
429c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_CFNR)) {
430c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CF_REASON_NOT_REACHABLE;
431c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_CFNRy)) {
432c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CF_REASON_NO_REPLY;
433c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_CF_All_Conditional)) {
434c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville           return CommandsInterface.CF_REASON_ALL_CONDITIONAL;
435c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
436c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            throw new RuntimeException ("invalid call forward sc");
437c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
438c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
439c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
440c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static int
441c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    siToServiceClass(String si) {
442c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (si == null || si.length() == 0) {
443c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return  SERVICE_CLASS_NONE;
444c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
445c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // NumberFormatException should cause MMI fail
446c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            int serviceCode = Integer.parseInt(si, 10);
447c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
448c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            switch (serviceCode) {
449c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 10: return SERVICE_CLASS_SMS + SERVICE_CLASS_FAX  + SERVICE_CLASS_VOICE;
450c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 11: return SERVICE_CLASS_VOICE;
451c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 12: return SERVICE_CLASS_SMS + SERVICE_CLASS_FAX;
452c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 13: return SERVICE_CLASS_FAX;
453c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
454c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 16: return SERVICE_CLASS_SMS;
455c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
456c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 19: return SERVICE_CLASS_FAX + SERVICE_CLASS_VOICE;
457c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/*
458c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    Note for code 20:
459c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     From TS 22.030 Annex C:
460c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                "All GPRS bearer services" are not included in "All tele and bearer services"
461c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    and "All bearer services"."
462c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville....so SERVICE_CLASS_DATA, which (according to 27.007) includes GPRS
463c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville*/
464c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 20: return SERVICE_CLASS_DATA_ASYNC + SERVICE_CLASS_DATA_SYNC;
465c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
466c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 21: return SERVICE_CLASS_PAD + SERVICE_CLASS_DATA_ASYNC;
467c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 22: return SERVICE_CLASS_PACKET + SERVICE_CLASS_DATA_SYNC;
468c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 24: return SERVICE_CLASS_DATA_SYNC;
469c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 25: return SERVICE_CLASS_DATA_ASYNC;
470c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 26: return SERVICE_CLASS_DATA_SYNC + SERVICE_CLASS_VOICE;
471c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 99: return SERVICE_CLASS_PACKET;
472c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
473c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                default:
474c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException("unsupported MMI service code " + si);
475c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
476c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
477c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
478c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
479c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static int
480c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    siToTime (String si) {
481c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (si == null || si.length() == 0) {
482c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return 0;
483c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
484c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // NumberFormatException should cause MMI fail
485c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return Integer.parseInt(si, 10);
486c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
487c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
488c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
489c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static boolean
490c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isServiceCodeCallForwarding(String sc) {
491c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return sc != null &&
492c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                (sc.equals(SC_CFU)
493c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                || sc.equals(SC_CFB) || sc.equals(SC_CFNRy)
494c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                || sc.equals(SC_CFNR) || sc.equals(SC_CF_All)
495c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                || sc.equals(SC_CF_All_Conditional));
496c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
497c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
498c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static boolean
499c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isServiceCodeCallBarring(String sc) {
50021fe62acc2d11ace0410b2b6d83263a96081c092duho.ro        Resources resource = Resources.getSystem();
50121fe62acc2d11ace0410b2b6d83263a96081c092duho.ro        if (sc != null) {
50221fe62acc2d11ace0410b2b6d83263a96081c092duho.ro            String[] barringMMI = resource.getStringArray(
50321fe62acc2d11ace0410b2b6d83263a96081c092duho.ro                com.android.internal.R.array.config_callBarringMMI);
50421fe62acc2d11ace0410b2b6d83263a96081c092duho.ro            if (barringMMI != null) {
50521fe62acc2d11ace0410b2b6d83263a96081c092duho.ro                for (String match : barringMMI) {
50621fe62acc2d11ace0410b2b6d83263a96081c092duho.ro                    if (sc.equals(match)) return true;
50721fe62acc2d11ace0410b2b6d83263a96081c092duho.ro                }
50821fe62acc2d11ace0410b2b6d83263a96081c092duho.ro            }
50921fe62acc2d11ace0410b2b6d83263a96081c092duho.ro        }
51021fe62acc2d11ace0410b2b6d83263a96081c092duho.ro        return false;
511c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
512c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
513c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static String
514c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    scToBarringFacility(String sc) {
515c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sc == null) {
516c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            throw new RuntimeException ("invalid call barring sc");
517c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
518c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
519c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sc.equals(SC_BAOC)) {
520c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BAOC;
521c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BAOIC)) {
522c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BAOIC;
523c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BAOICxH)) {
524c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BAOICxH;
525c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BAIC)) {
526c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BAIC;
527c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BAICr)) {
528c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BAICr;
529c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BA_ALL)) {
530c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BA_ALL;
531c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BA_MO)) {
532c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BA_MO;
533c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (sc.equals(SC_BA_MT)) {
534c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return CommandsInterface.CB_FACILITY_BA_MT;
535c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
536c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            throw new RuntimeException ("invalid call barring sc");
537c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
538c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
539c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
540c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Constructor
541c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
5423a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    public GsmMmiCode(GsmCdmaPhone phone, UiccCardApplication app) {
543c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // The telephony unit-test cases may create GsmMmiCode's
544c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // in secondary threads
545c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        super(phone.getHandler().getLooper());
54622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mPhone = phone;
54722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mContext = phone.getContext();
548e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mUiccApplication = app;
549e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (app != null) {
550e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mIccRecords = app.getIccRecords();
551e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
552c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
553c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
554c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** MmiCode implementation
555c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
556cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
557c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public State
558c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    getState() {
55922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mState;
560c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
561c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
562cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
563c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public CharSequence
564c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    getMessage() {
56522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mMessage;
566c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
567c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
568a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public Phone
569a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    getPhone() {
570a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return ((Phone) mPhone);
571a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
572a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
573c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // inherited javadoc suffices
574cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
575c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void
576c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    cancel() {
577c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Complete or failed cannot be cancelled
57822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mState == State.COMPLETE || mState == State.FAILED) {
579c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return;
580c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
581c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
58222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mState = State.CANCELLED;
583c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
58422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mIsPendingUSSD) {
585c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            /*
586c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             * There can only be one pending USSD session, so tell the radio to
587c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             * cancel it.
588c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             */
58922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mPhone.mCi.cancelPendingUssd(obtainMessage(EVENT_USSD_CANCEL_COMPLETE, this));
590c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
591c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            /*
592c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             * Don't call phone.onMMIDone here; wait for CANCEL_COMPLETE notice
593c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             * from RIL.
594c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville             */
595c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
596c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // TODO in cases other than USSD, it would be nice to cancel
597c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // the pending radio operation. This requires RIL cancellation
598c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // support, which does not presently exist.
599c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
60022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mPhone.onMMIDone (this);
601c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
602c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
603c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
604c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
605cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
606c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public boolean isCancelable() {
607c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        /* Can only cancel pending USSD sessions. */
60822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mIsPendingUSSD;
609c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
610c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
611c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Instance Methods
612c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
613c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Does this dial string contain a structured or unstructured MMI code? */
614c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean
615c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isMMI() {
61622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mPoundString != null;
617c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
618c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
619c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /* Is this a 1 or 2 digit "short code" as defined in TS 22.030 sec 6.5.3.2? */
620c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean
621c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isShortCode() {
62222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mPoundString == null
62322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    && mDialingNumber != null && mDialingNumber.length() <= 2;
624c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
625c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
626c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
627c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static private boolean
628c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isTwoDigitShortCode(Context context, String dialString) {
629ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville        Rlog.d(LOG_TAG, "isTwoDigitShortCode");
630c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
6316103b5df6705c89193f452c35eaf5e9a26c188cfJing Zhao        if (dialString == null || dialString.length() > 2) return false;
632c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
633c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (sTwoDigitNumberPattern == null) {
634c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            sTwoDigitNumberPattern = context.getResources().getStringArray(
635c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    com.android.internal.R.array.config_twoDigitNumberPattern);
636c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
637c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
638c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        for (String dialnumber : sTwoDigitNumberPattern) {
639ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.d(LOG_TAG, "Two Digit Number Pattern " + dialnumber);
640c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (dialString.equals(dialnumber)) {
641ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.d(LOG_TAG, "Two Digit Number Pattern -true");
642c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return true;
643c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
644c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
645ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville        Rlog.d(LOG_TAG, "Two Digit Number Pattern -false");
646c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return false;
647c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
648c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
649c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
650c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Helper function for newFromDialString. Returns true if dialString appears
651c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * to be a short code AND conditions are correct for it to be treated as
652c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * such.
653c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
6543a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    static private boolean isShortCode(String dialString, GsmCdmaPhone phone) {
655c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Refer to TS 22.030 Figure 3.5.3.2:
656c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (dialString == null) {
657c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return false;
658c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
659c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
660c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Illegal dial string characters will give a ZERO length.
661c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // At this point we do not want to crash as any application with
662c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // call privileges may send a non dial string.
663c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // It return false as when the dialString is equal to NULL.
664c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (dialString.length() == 0) {
665c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return false;
666c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
667c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
668f4f5308a309d43fcfca8d0d5fbb54bc38c82ca3fYorke Lee        if (PhoneNumberUtils.isLocalEmergencyNumber(phone.getContext(), dialString)) {
669c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return false;
670c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
671c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return isShortCodeUSSD(dialString, phone);
672c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
673c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
674c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
675c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
676c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Helper function for isShortCode. Returns true if dialString appears to be
677c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * a short code and it is a USSD structure
678c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
679c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * According to the 3PGG TS 22.030 specification Figure 3.5.3.2: A 1 or 2
680c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * digit "short code" is treated as USSD if it is entered while on a call or
681c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * does not satisfy the condition (exactly 2 digits && starts with '1'), there
682c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * are however exceptions to this rule (see below)
683c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
684c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Exception (1) to Call initiation is: If the user of the device is already in a call
685c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * and enters a Short String without any #-key at the end and the length of the Short String is
686c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * equal or less then the MAX_LENGTH_SHORT_CODE [constant that is equal to 2]
687c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
688c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * The phone shall initiate a USSD/SS commands.
689c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
6903a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    static private boolean isShortCodeUSSD(String dialString, GsmCdmaPhone phone) {
69110e574acd0992d22abce257b420d333f5a49e71dJeevaka Badrappan        if (dialString != null && dialString.length() <= MAX_LENGTH_SHORT_CODE) {
692c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (phone.isInCall()) {
69310e574acd0992d22abce257b420d333f5a49e71dJeevaka Badrappan                return true;
694c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
695c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
69610e574acd0992d22abce257b420d333f5a49e71dJeevaka Badrappan            if (dialString.length() != MAX_LENGTH_SHORT_CODE ||
69710e574acd0992d22abce257b420d333f5a49e71dJeevaka Badrappan                    dialString.charAt(0) != '1') {
69810e574acd0992d22abce257b420d333f5a49e71dJeevaka Badrappan                return true;
699c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
700c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
701c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return false;
702c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
703c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
704c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
705c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @return true if the Service Code is PIN/PIN2/PUK/PUK2-related
706c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
7073a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    public boolean isPinPukCommand() {
70822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mSc != null && (mSc.equals(SC_PIN) || mSc.equals(SC_PIN2)
70922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                              || mSc.equals(SC_PUK) || mSc.equals(SC_PUK2));
710c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     }
711c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
712c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
713c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * See TS 22.030 Annex B.
714c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * In temporary mode, to suppress CLIR for a single call, enter:
715c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *      " * 31 # [called number] SEND "
716c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  In temporary mode, to invoke CLIR for a single call enter:
717c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *       " # 31 # [called number] SEND "
718c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
7193a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    public boolean
720c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    isTemporaryModeCLIR() {
72122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mSc != null && mSc.equals(SC_CLIR) && mDialingNumber != null
722c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                && (isActivate() || isDeactivate());
723c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
724c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
725c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
726c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * returns CommandsInterface.CLIR_*
727c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * See also isTemporaryModeCLIR()
728c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
7293a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    public int
730c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    getCLIRMode() {
73122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mSc != null && mSc.equals(SC_CLIR)) {
732c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (isActivate()) {
733c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return CommandsInterface.CLIR_SUPPRESSION;
734c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else if (isDeactivate()) {
735c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return CommandsInterface.CLIR_INVOCATION;
736c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
737c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
738c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
739c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return CommandsInterface.CLIR_DEFAULT;
740c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
741c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
742c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean isActivate() {
74322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mAction != null && mAction.equals(ACTION_ACTIVATE);
744c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
745c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
746c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean isDeactivate() {
74722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mAction != null && mAction.equals(ACTION_DEACTIVATE);
748c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
749c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
750c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean isInterrogate() {
75122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mAction != null && mAction.equals(ACTION_INTERROGATE);
752c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
753c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
754c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean isRegister() {
75522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mAction != null && mAction.equals(ACTION_REGISTER);
756c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
757c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
758c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    boolean isErasure() {
75922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mAction != null && mAction.equals(ACTION_ERASURE);
760c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
761c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
762c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
763c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Returns true if this is a USSD code that's been submitted to the
764c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * network...eg, after processCode() is called
765c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
766c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public boolean isPendingUSSD() {
76722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mIsPendingUSSD;
768c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
769c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
770cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
771c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public boolean isUssdRequest() {
77222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mIsUssdRequest;
773c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
774c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
77509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja    public boolean isSsInfo() {
77609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja        return mIsSsInfo;
77709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja    }
77809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja
779c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Process a MMI code or short code...anything that isn't a dialing number */
7803a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    public void
7813a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    processCode() throws CallStateException {
782c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        try {
783c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (isShortCode()) {
784ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.d(LOG_TAG, "isShortCode");
785c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // These just get treated as USSD.
78622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sendUssd(mDialingNumber);
78722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mDialingNumber != null) {
788c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // We should have no dialing numbers here
789c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                throw new RuntimeException ("Invalid or Unsupported MMI Code");
79022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc != null && mSc.equals(SC_CLIP)) {
791ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.d(LOG_TAG, "is CLIP");
792c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isInterrogate()) {
79322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.queryCLIP(
794c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            obtainMessage(EVENT_QUERY_COMPLETE, this));
795c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
796c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException ("Invalid or Unsupported MMI Code");
797c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
79822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc != null && mSc.equals(SC_CLIR)) {
799ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.d(LOG_TAG, "is CLIR");
800c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isActivate()) {
80122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.setCLIR(CommandsInterface.CLIR_INVOCATION,
802c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        obtainMessage(EVENT_SET_COMPLETE, this));
803c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (isDeactivate()) {
80422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.setCLIR(CommandsInterface.CLIR_SUPPRESSION,
805c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        obtainMessage(EVENT_SET_COMPLETE, this));
806c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (isInterrogate()) {
80722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.getCLIR(
808c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        obtainMessage(EVENT_GET_CLIR_COMPLETE, this));
809c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
810c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException ("Invalid or Unsupported MMI Code");
811c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
81222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (isServiceCodeCallForwarding(mSc)) {
813ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.d(LOG_TAG, "is CF");
814c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
81522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                String dialingNumber = mSia;
81622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                int serviceClass = siToServiceClass(mSib);
81722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                int reason = scToCallForwardReason(mSc);
81822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                int time = siToTime(mSic);
819c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
820c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isInterrogate()) {
82122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.queryCallForwardStatus(
822c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            reason, serviceClass,  dialingNumber,
823c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                obtainMessage(EVENT_QUERY_CF_COMPLETE, this));
824c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
825c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    int cfAction;
826c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
827c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    if (isActivate()) {
8285f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        // 3GPP TS 22.030 6.5.2
8295f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        // a call forwarding request with a single * would be
8305f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        // interpreted as registration if containing a forwarded-to
8315f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        // number, or an activation if not
8325f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        if (isEmptyOrNull(dialingNumber)) {
8335f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                            cfAction = CommandsInterface.CF_ACTION_ENABLE;
83422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            mIsCallFwdReg = false;
8355f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        } else {
8365f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                            cfAction = CommandsInterface.CF_ACTION_REGISTRATION;
83722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            mIsCallFwdReg = true;
8385f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        }
839c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else if (isDeactivate()) {
840c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        cfAction = CommandsInterface.CF_ACTION_DISABLE;
841c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else if (isRegister()) {
842c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        cfAction = CommandsInterface.CF_ACTION_REGISTRATION;
843c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else if (isErasure()) {
844c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        cfAction = CommandsInterface.CF_ACTION_ERASURE;
845c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else {
846c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        throw new RuntimeException ("invalid action");
847c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
848c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
849c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    int isSettingUnconditionalVoice =
850c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        (((reason == CommandsInterface.CF_REASON_UNCONDITIONAL) ||
851c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                (reason == CommandsInterface.CF_REASON_ALL)) &&
852c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                (((serviceClass & CommandsInterface.SERVICE_CLASS_VOICE) != 0) ||
853c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                 (serviceClass == CommandsInterface.SERVICE_CLASS_NONE))) ? 1 : 0;
854c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
855c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    int isEnableDesired =
856c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        ((cfAction == CommandsInterface.CF_ACTION_ENABLE) ||
857c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                (cfAction == CommandsInterface.CF_ACTION_REGISTRATION)) ? 1 : 0;
858c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
859ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                    Rlog.d(LOG_TAG, "is CF setCallForward");
86022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.setCallForward(cfAction, reason, serviceClass,
861c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            dialingNumber, time, obtainMessage(
862c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    EVENT_SET_CFF_COMPLETE,
863c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    isSettingUnconditionalVoice,
864c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    isEnableDesired, this));
865c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
86622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (isServiceCodeCallBarring(mSc)) {
867c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sia = password
868c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sib = basic service group
869c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
87022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                String password = mSia;
87122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                int serviceClass = siToServiceClass(mSib);
87222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                String facility = scToBarringFacility(mSc);
873c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
874c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isInterrogate()) {
87522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.queryFacilityLock(facility, password,
876c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            serviceClass, obtainMessage(EVENT_QUERY_COMPLETE, this));
877c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (isActivate() || isDeactivate()) {
87822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.setFacilityLock(facility, isActivate(), password,
879c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            serviceClass, obtainMessage(EVENT_SET_COMPLETE, this));
880c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
881c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException ("Invalid or Unsupported MMI Code");
882c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
883c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
88422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc != null && mSc.equals(SC_PWD)) {
885c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sia = fac
886c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sib = old pwd
887c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sic = new pwd
888c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // pwd = new pwd
889c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                String facility;
89022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                String oldPwd = mSib;
89122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                String newPwd = mSic;
892c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isActivate() || isRegister()) {
893c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // Even though ACTIVATE is acceptable, this is really termed a REGISTER
89422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mAction = ACTION_REGISTER;
895c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
89622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    if (mSia == null) {
897c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // If sc was not specified, treat it as BA_ALL.
898c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        facility = CommandsInterface.CB_FACILITY_BA_ALL;
899c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else {
90022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        facility = scToBarringFacility(mSia);
901c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
90222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    if (newPwd.equals(mPwd)) {
90322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        mPhone.mCi.changeBarringPassword(facility, oldPwd,
904c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                newPwd, obtainMessage(EVENT_SET_COMPLETE, this));
905c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else {
906c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // password mismatch; return error
907c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        handlePasswordError(com.android.internal.R.string.passwordIncorrect);
908c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
909c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
910c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException ("Invalid or Unsupported MMI Code");
911c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
912c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
91322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc != null && mSc.equals(SC_WAIT)) {
914c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sia = basic service group
91522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                int serviceClass = siToServiceClass(mSia);
916c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
917c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isActivate() || isDeactivate()) {
91822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.setCallWaiting(isActivate(), serviceClass,
919c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            obtainMessage(EVENT_SET_COMPLETE, this));
920c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (isInterrogate()) {
92122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.mCi.queryCallWaiting(serviceClass,
922c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            obtainMessage(EVENT_QUERY_COMPLETE, this));
923c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
924c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    throw new RuntimeException ("Invalid or Unsupported MMI Code");
925c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
9263522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville            } else if (isPinPukCommand()) {
9273522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                // TODO: This is the same as the code in CmdaMmiCode.java,
9283522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                // MmiCode should be an abstract or base class and this and
9293522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                // other common variables and code should be promoted.
9303522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville
931c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sia = old PIN or PUK
932c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sib = new PIN
933c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // sic = new PIN
93422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                String oldPinOrPuk = mSia;
9353522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                String newPinOrPuk = mSib;
9363522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                int pinLen = newPinOrPuk.length();
937c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (isRegister()) {
9383522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    if (!newPinOrPuk.equals(mSic)) {
939c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // password mismatch; return error
940c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        handlePasswordError(com.android.internal.R.string.mismatchPin);
941c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else if (pinLen < 4 || pinLen > 8 ) {
942c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // invalid length
943c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        handlePasswordError(com.android.internal.R.string.invalidPin);
9443522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    } else if (mSc.equals(SC_PIN)
9453522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            && mUiccApplication != null
9463522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            && mUiccApplication.getState() == AppState.APPSTATE_PUK) {
947c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // Sim is puk-locked
948c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        handlePasswordError(com.android.internal.R.string.needPuk);
9493522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    } else if (mUiccApplication != null) {
9503522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        Rlog.d(LOG_TAG, "process mmi service code using UiccApp sc=" + mSc);
9513522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville
9523522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        // We have an app and the pre-checks are OK
95322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        if (mSc.equals(SC_PIN)) {
9543522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            mUiccApplication.changeIccLockPassword(oldPinOrPuk, newPinOrPuk,
955c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    obtainMessage(EVENT_SET_COMPLETE, this));
95622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        } else if (mSc.equals(SC_PIN2)) {
9573522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            mUiccApplication.changeIccFdnPassword(oldPinOrPuk, newPinOrPuk,
958c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    obtainMessage(EVENT_SET_COMPLETE, this));
95922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        } else if (mSc.equals(SC_PUK)) {
9603522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            mUiccApplication.supplyPuk(oldPinOrPuk, newPinOrPuk,
961c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    obtainMessage(EVENT_SET_COMPLETE, this));
96222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        } else if (mSc.equals(SC_PUK2)) {
9633522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            mUiccApplication.supplyPuk2(oldPinOrPuk, newPinOrPuk,
964c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    obtainMessage(EVENT_SET_COMPLETE, this));
9653522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        } else {
9663522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            throw new RuntimeException("uicc unsupported service code=" + mSc);
967c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        }
9683522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    } else {
9693522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        throw new RuntimeException("No application mUiccApplicaiton is null");
970c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
971c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
9723522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    throw new RuntimeException ("Ivalid register/action=" + mAction);
973c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
97422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mPoundString != null) {
97522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sendUssd(mPoundString);
976c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
977c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                throw new RuntimeException ("Invalid or Unsupported MMI Code");
978c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
979c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } catch (RuntimeException exc) {
98022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.FAILED;
98122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mMessage = mContext.getText(com.android.internal.R.string.mmiError);
98222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mPhone.onMMIDone(this);
983c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
984c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
985c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
986c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void handlePasswordError(int res) {
98722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mState = State.FAILED;
988c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder(getScString());
989c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("\n");
99022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        sb.append(mContext.getText(res));
99122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mMessage = sb;
99222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mPhone.onMMIDone(this);
993c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
994c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
995c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
99658dd6858dc8013b680ea003d22063fd65ed5fe1cAmit Mahajan     * Called from GsmCdmaPhone
997c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
998c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * An unsolicited USSD NOTIFY or REQUEST has come in matching
999c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * up with this pending USSD request
1000c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
1001c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Note: If REQUEST, this exchange is complete, but the session remains
1002c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *       active (ie, the network expects user input).
1003c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
10043a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    public void
1005c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    onUssdFinished(String ussdMessage, boolean isUssdRequest) {
100622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mState == State.PENDING) {
1007c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (ussdMessage == null) {
100822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mMessage = mContext.getText(com.android.internal.R.string.mmiComplete);
1009c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
101022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mMessage = ussdMessage;
1011c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
101222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mIsUssdRequest = isUssdRequest;
1013c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // If it's a request, leave it PENDING so that it's cancelable.
1014c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (!isUssdRequest) {
101522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mState = State.COMPLETE;
1016c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1017c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
101822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mPhone.onMMIDone(this);
1019c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1020c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1021c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1022c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
102358dd6858dc8013b680ea003d22063fd65ed5fe1cAmit Mahajan     * Called from GsmCdmaPhone
1024c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
1025c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * The radio has reset, and this is still pending
1026c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
1027c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
10283a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    public void
1029c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    onUssdFinishedError() {
103022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mState == State.PENDING) {
103122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.FAILED;
103222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mMessage = mContext.getText(com.android.internal.R.string.mmiError);
1033c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
103422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mPhone.onMMIDone(this);
1035c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1036c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1037c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
10380aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati    /**
103958dd6858dc8013b680ea003d22063fd65ed5fe1cAmit Mahajan     * Called from GsmCdmaPhone
10400aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati     *
10410aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati     * An unsolicited USSD NOTIFY or REQUEST has come in matching
10420aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati     * up with this pending USSD request
10430aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati     *
10440aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati     * Note: If REQUEST, this exchange is complete, but the session remains
10450aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati     *       active (ie, the network expects user input).
10460aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati     */
10473a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    public void
10480aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati    onUssdRelease() {
10490aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati        if (mState == State.PENDING) {
10500aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati            mState = State.COMPLETE;
10510aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati            mMessage = null;
10520aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati
10530aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati            mPhone.onMMIDone(this);
10540aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati        }
10550aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati    }
10560aa03d22e29d57d1064c292bcdb4e762e9abca01Anju Mathapati
10573a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan    public void sendUssd(String ussdMessage) {
1058c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Treat this as a USSD string
105922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mIsPendingUSSD = true;
1060c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1061c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Note that unlike most everything else, the USSD complete
1062c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // response does not complete this MMI code...we wait for
1063c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // an unsolicited USSD "Notify" or "Request".
106458dd6858dc8013b680ea003d22063fd65ed5fe1cAmit Mahajan        // The matching up of this is done in GsmCdmaPhone.
1065c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
106622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mPhone.mCi.sendUSSD(ussdMessage,
1067c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            obtainMessage(EVENT_USSD_COMPLETE, this));
1068c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1069c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
107058dd6858dc8013b680ea003d22063fd65ed5fe1cAmit Mahajan    /** Called from GsmCdmaPhone.handleMessage; not a Handler subclass */
1071cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
1072c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void
1073c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    handleMessage (Message msg) {
1074c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        AsyncResult ar;
1075c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1076c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        switch (msg.what) {
1077c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_SET_COMPLETE:
1078c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
1079c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
10803522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                onSetComplete(msg, ar);
1081c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1082c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1083c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_SET_CFF_COMPLETE:
1084c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
1085c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1086c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                /*
1087c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                * msg.arg1 = 1 means to set unconditional voice call forwarding
1088c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                * msg.arg2 = 1 means to enable voice call forwarding
1089c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                */
1090c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if ((ar.exception == null) && (msg.arg1 == 1)) {
1091c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    boolean cffEnabled = (msg.arg2 == 1);
1092e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    if (mIccRecords != null) {
1093eadee84166d397b6425cfd56f89fa1569f6a93f5Amit Mahajan                        mPhone.setVoiceCallForwardingFlag(1, cffEnabled, mDialingNumber);
1094bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                    }
1095c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
1096c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
10973522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                onSetComplete(msg, ar);
1098c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1099c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1100c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_GET_CLIR_COMPLETE:
1101c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
1102c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                onGetClirComplete(ar);
1103c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
1104c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1105c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_QUERY_CF_COMPLETE:
1106c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
1107c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                onQueryCfComplete(ar);
1108c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
1109c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1110c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_QUERY_COMPLETE:
1111c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
1112c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                onQueryComplete(ar);
1113c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
1114c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1115c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_USSD_COMPLETE:
1116c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult) (msg.obj);
1117c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1118c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (ar.exception != null) {
111922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mState = State.FAILED;
112022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mMessage = getErrorMessage(ar);
1121c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
112222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mPhone.onMMIDone(this);
1123c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
1124c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1125c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // Note that unlike most everything else, the USSD complete
1126c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // response does not complete this MMI code...we wait for
1127c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // an unsolicited USSD "Notify" or "Request".
112858dd6858dc8013b680ea003d22063fd65ed5fe1cAmit Mahajan                // The matching up of this is done in GsmCdmaPhone.
1129c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1130c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
1131c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1132c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_USSD_CANCEL_COMPLETE:
113322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mPhone.onMMIDone(this);
1134c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
1135c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1136c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1137c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    //***** Private instance methods
1138c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1139c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence getErrorMessage(AsyncResult ar) {
1140c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1141c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (ar.exception instanceof CommandException) {
1142c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            CommandException.Error err = ((CommandException)(ar.exception)).getCommandError();
1143c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (err == CommandException.Error.FDN_CHECK_FAILURE) {
1144ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.i(LOG_TAG, "FDN_CHECK_FAILURE");
114522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.mmiFdnError);
114609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            } else if (err == CommandException.Error.USSD_MODIFIED_TO_DIAL) {
114709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                Rlog.i(LOG_TAG, "USSD_MODIFIED_TO_DIAL");
114809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return mContext.getText(com.android.internal.R.string.stk_cc_ussd_to_dial);
114909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            } else if (err == CommandException.Error.USSD_MODIFIED_TO_SS) {
115009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                Rlog.i(LOG_TAG, "USSD_MODIFIED_TO_SS");
115109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return mContext.getText(com.android.internal.R.string.stk_cc_ussd_to_ss);
115209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            } else if (err == CommandException.Error.USSD_MODIFIED_TO_USSD) {
115309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                Rlog.i(LOG_TAG, "USSD_MODIFIED_TO_USSD");
115409b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return mContext.getText(com.android.internal.R.string.stk_cc_ussd_to_ussd);
115509b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            } else if (err == CommandException.Error.SS_MODIFIED_TO_DIAL) {
115609b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                Rlog.i(LOG_TAG, "SS_MODIFIED_TO_DIAL");
115709b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return mContext.getText(com.android.internal.R.string.stk_cc_ss_to_dial);
115809b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            } else if (err == CommandException.Error.SS_MODIFIED_TO_USSD) {
115909b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                Rlog.i(LOG_TAG, "SS_MODIFIED_TO_USSD");
116009b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return mContext.getText(com.android.internal.R.string.stk_cc_ss_to_ussd);
116109b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja            } else if (err == CommandException.Error.SS_MODIFIED_TO_SS) {
116209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                Rlog.i(LOG_TAG, "SS_MODIFIED_TO_SS");
116309b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                return mContext.getText(com.android.internal.R.string.stk_cc_ss_to_ss);
1164c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1165c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1166c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
116722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        return mContext.getText(com.android.internal.R.string.mmiError);
1168c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1169c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1170c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence getScString() {
117122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mSc != null) {
117222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            if (isServiceCodeCallBarring(mSc)) {
117322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.BaMmi);
117422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (isServiceCodeCallForwarding(mSc)) {
117522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.CfMmi);
117622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc.equals(SC_CLIP)) {
117722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.ClipMmi);
117822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc.equals(SC_CLIR)) {
117922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.ClirMmi);
118022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc.equals(SC_PWD)) {
118122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.PwdMmi);
118222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            } else if (mSc.equals(SC_WAIT)) {
118322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.CwMmi);
11843522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville            } else if (isPinPukCommand()) {
118522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.PinMmi);
1186c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1187c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1188c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1189c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return "";
1190c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1191c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1192c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void
11933522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville    onSetComplete(Message msg, AsyncResult ar){
1194c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder(getScString());
1195c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("\n");
1196c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1197c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (ar.exception != null) {
119822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.FAILED;
1199c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (ar.exception instanceof CommandException) {
1200c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                CommandException.Error err = ((CommandException)(ar.exception)).getCommandError();
1201c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (err == CommandException.Error.PASSWORD_INCORRECT) {
12023522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    if (isPinPukCommand()) {
1203c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // look specifically for the PUK commands and adjust
1204c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        // the message accordingly.
120522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        if (mSc.equals(SC_PUK) || mSc.equals(SC_PUK2)) {
120622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1207c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.badPuk));
1208c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        } else {
120922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1210c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.badPin));
1211c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        }
12123522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        // Get the No. of retries remaining to unlock PUK/PUK2
12133522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        int attemptsRemaining = msg.arg1;
12146d3c836bb8991e9cf7ffb322ebabf48c2446126dWink Saville                        if (attemptsRemaining <= 0) {
12156d3c836bb8991e9cf7ffb322ebabf48c2446126dWink Saville                            Rlog.d(LOG_TAG, "onSetComplete: PUK locked,"
12166d3c836bb8991e9cf7ffb322ebabf48c2446126dWink Saville                                    + " cancel as lock screen will handle this");
12176d3c836bb8991e9cf7ffb322ebabf48c2446126dWink Saville                            mState = State.CANCELLED;
12186d3c836bb8991e9cf7ffb322ebabf48c2446126dWink Saville                        } else if (attemptsRemaining > 0) {
12196d3c836bb8991e9cf7ffb322ebabf48c2446126dWink Saville                            Rlog.d(LOG_TAG, "onSetComplete: attemptsRemaining="+attemptsRemaining);
12203522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                            sb.append(mContext.getResources().getQuantityString(
12213522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                                    com.android.internal.R.plurals.pinpuk_attempts,
12223522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                                    attemptsRemaining, attemptsRemaining));
12233522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        }
1224c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    } else {
122522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        sb.append(mContext.getText(
1226c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                com.android.internal.R.string.passwordIncorrect));
1227c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
1228c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (err == CommandException.Error.SIM_PUK2) {
122922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(
1230c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            com.android.internal.R.string.badPin));
1231c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    sb.append("\n");
123222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(
1233c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            com.android.internal.R.string.needPuk2));
12343522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                } else if (err == CommandException.Error.REQUEST_NOT_SUPPORTED) {
12353522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    if (mSc.equals(SC_PIN)) {
12363522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                        sb.append(mContext.getText(com.android.internal.R.string.enablePin));
12373522c54a64f577f2b657a775dae9b4eb2d8003d5Wink Saville                    }
1238c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (err == CommandException.Error.FDN_CHECK_FAILURE) {
1239ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                    Rlog.i(LOG_TAG, "FDN_CHECK_FAILURE");
124022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(com.android.internal.R.string.mmiFdnError));
1241c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
124209b65da3b46e18c8acc146d722047ba2fb161bfePreeti Ahuja                    sb.append(getErrorMessage(ar));
1243c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
1244c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
124522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sb.append(mContext.getText(
1246c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.mmiError));
1247c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1248c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isActivate()) {
124922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.COMPLETE;
125022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            if (mIsCallFwdReg) {
125122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sb.append(mContext.getText(
12525f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        com.android.internal.R.string.serviceRegistered));
12535f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li            } else {
125422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sb.append(mContext.getText(
12555f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li                        com.android.internal.R.string.serviceEnabled));
12565f6b9345f8fe5545f576d29fb7ff9f3405d9dc05Bin Li            }
1257c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // Record CLIR setting
125822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            if (mSc.equals(SC_CLIR)) {
125922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mPhone.saveClirSetting(CommandsInterface.CLIR_INVOCATION);
1260c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1261c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isDeactivate()) {
126222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.COMPLETE;
126322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            sb.append(mContext.getText(
1264c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    com.android.internal.R.string.serviceDisabled));
1265c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // Record CLIR setting
126622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            if (mSc.equals(SC_CLIR)) {
126722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mPhone.saveClirSetting(CommandsInterface.CLIR_SUPPRESSION);
1268c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1269c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isRegister()) {
127022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.COMPLETE;
127122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            sb.append(mContext.getText(
1272c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    com.android.internal.R.string.serviceRegistered));
1273c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (isErasure()) {
127422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.COMPLETE;
127522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            sb.append(mContext.getText(
1276c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    com.android.internal.R.string.serviceErased));
1277c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
127822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.FAILED;
127922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            sb.append(mContext.getText(
1280c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    com.android.internal.R.string.mmiError));
1281c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1282c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
128322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mMessage = sb;
128422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mPhone.onMMIDone(this);
1285c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1286c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1287c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void
1288c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    onGetClirComplete(AsyncResult ar) {
1289c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder(getScString());
1290c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("\n");
1291c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1292c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (ar.exception != null) {
129322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.FAILED;
1294c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            sb.append(getErrorMessage(ar));
1295c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
1296c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            int clirArgs[];
1297c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1298c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            clirArgs = (int[])ar.result;
1299c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1300c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // the 'm' parameter from TS 27.007 7.7
1301c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            switch (clirArgs[1]) {
1302c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 0: // CLIR not provisioned
130322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(
1304c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                com.android.internal.R.string.serviceNotProvisioned));
130522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mState = State.COMPLETE;
1306c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1307c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1308c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 1: // CLIR provisioned in permanent mode
130922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(
1310c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                com.android.internal.R.string.CLIRPermanent));
131122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mState = State.COMPLETE;
1312c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1313c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1314c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 2: // unknown (e.g. no network, etc.)
131522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(
1316c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                com.android.internal.R.string.mmiError));
131722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mState = State.FAILED;
1318c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1319c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1320c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 3: // CLIR temporary mode presentation restricted
1321c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1322c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // the 'n' parameter from TS 27.007 7.7
1323c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    switch (clirArgs[0]) {
1324c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        default:
1325c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 0: // Default
132622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1327c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOnNextCallOn));
1328c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1329c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 1: // CLIR invocation
133022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1331c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOnNextCallOn));
1332c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1333c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 2: // CLIR suppression
133422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1335c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOnNextCallOff));
1336c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1337c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
133822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mState = State.COMPLETE;
1339c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1340c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1341c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                case 4: // CLIR temporary mode presentation allowed
1342c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // the 'n' parameter from TS 27.007 7.7
1343c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    switch (clirArgs[0]) {
1344c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        default:
1345c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 0: // Default
134622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1347c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOffNextCallOff));
1348c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1349c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 1: // CLIR invocation
135022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1351c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOffNextCallOn));
1352c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1353c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        case 2: // CLIR suppression
135422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            sb.append(mContext.getText(
1355c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                    com.android.internal.R.string.CLIRDefaultOffNextCallOff));
1356c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        break;
1357c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
1358c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
135922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    mState = State.COMPLETE;
1360c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
1361c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1362c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1363c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
136422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mMessage = sb;
136522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mPhone.onMMIDone(this);
1366c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1367c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1368c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
1369c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param serviceClass 1 bit of the service class bit vectory
1370c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @return String to be used for call forward query MMI response text.
1371c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *        Returns null if unrecognized
1372c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
1373c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1374c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence
1375c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    serviceClassToCFString (int serviceClass) {
1376c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        switch (serviceClass) {
1377c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_VOICE:
137822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassVoice);
1379c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_DATA:
138022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassData);
1381c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_FAX:
138222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassFAX);
1383c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_SMS:
138422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassSMS);
1385c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_DATA_SYNC:
138622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassDataSync);
1387c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_DATA_ASYNC:
138822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassDataAsync);
1389c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_PACKET:
139022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassPacket);
1391c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case SERVICE_CLASS_PAD:
139222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                return mContext.getText(com.android.internal.R.string.serviceClassPAD);
1393c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            default:
1394c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                return null;
1395c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1396c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1397c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1398c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1399c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** one CallForwardInfo + serviceClassMask -> one line of text */
1400c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence
1401c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    makeCFQueryResultMessage(CallForwardInfo info, int serviceClassMask) {
1402c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        CharSequence template;
1403c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        String sources[] = {"{0}", "{1}", "{2}"};
1404c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        CharSequence destinations[] = new CharSequence[3];
1405c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        boolean needTimeTemplate;
1406c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1407c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // CF_REASON_NO_REPLY also has a time value associated with
1408c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // it. All others don't.
1409c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1410c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        needTimeTemplate =
1411c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            (info.reason == CommandsInterface.CF_REASON_NO_REPLY);
1412c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1413c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (info.status == 1) {
1414c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (needTimeTemplate) {
141522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                template = mContext.getText(
1416c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.cfTemplateForwardedTime);
1417c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
141822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                template = mContext.getText(
1419c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.cfTemplateForwarded);
1420c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1421c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (info.status == 0 && isEmptyOrNull(info.number)) {
142222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            template = mContext.getText(
1423c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.cfTemplateNotForwarded);
1424c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else { /* (info.status == 0) && !isEmptyOrNull(info.number) */
1425c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // A call forward record that is not active but contains
1426c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // a phone number is considered "registered"
1427c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1428c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (needTimeTemplate) {
142922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                template = mContext.getText(
1430c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.cfTemplateRegisteredTime);
1431c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
143222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                template = mContext.getText(
1433c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        com.android.internal.R.string.cfTemplateRegistered);
1434c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1435c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1436c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1437c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // In the template (from strings.xmls)
1438c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        //         {0} is one of "bearerServiceCode*"
1439c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        //        {1} is dialing number
1440c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        //      {2} is time in seconds
1441c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1442c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        destinations[0] = serviceClassToCFString(info.serviceClass & serviceClassMask);
14438697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlsson        destinations[1] = formatLtr(
14448697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlsson                PhoneNumberUtils.stringFromStringAndTOA(info.number, info.toa));
1445c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        destinations[2] = Integer.toString(info.timeSeconds);
1446c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1447c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (info.reason == CommandsInterface.CF_REASON_UNCONDITIONAL &&
1448c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                (info.serviceClass & serviceClassMask)
1449c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        == CommandsInterface.SERVICE_CLASS_VOICE) {
1450c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            boolean cffEnabled = (info.status == 1);
1451e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (mIccRecords != null) {
1452eadee84166d397b6425cfd56f89fa1569f6a93f5Amit Mahajan                mPhone.setVoiceCallForwardingFlag(1, cffEnabled, info.number);
1453bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka            }
1454c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1455c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1456c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return TextUtils.replace(template, sources, destinations);
1457c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1458c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
14598697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlsson    /**
14608697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlsson     * Used to format a string that should be displayed as LTR even in RTL locales
14618697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlsson     */
14628697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlsson    private String formatLtr(String str) {
14638697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlsson        BidiFormatter fmt = BidiFormatter.getInstance();
14648697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlsson        return str == null ? str : fmt.unicodeWrap(str, TextDirectionHeuristics.LTR, true);
14658697e0eb16fd00420efaf626ba4da3d548de3b59Magnus Karlsson    }
1466c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1467c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void
1468c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    onQueryCfComplete(AsyncResult ar) {
1469c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder(getScString());
1470c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("\n");
1471c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1472c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (ar.exception != null) {
147322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.FAILED;
1474c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            sb.append(getErrorMessage(ar));
1475c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
1476c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            CallForwardInfo infos[];
1477c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1478c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            infos = (CallForwardInfo[]) ar.result;
1479c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1480c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (infos.length == 0) {
1481c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // Assume the default is not active
148222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sb.append(mContext.getText(com.android.internal.R.string.serviceDisabled));
1483c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1484c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // Set unconditional CFF in SIM to false
1485e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if (mIccRecords != null) {
1486eadee84166d397b6425cfd56f89fa1569f6a93f5Amit Mahajan                    mPhone.setVoiceCallForwardingFlag(1, false, null);
1487bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka                }
1488c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
1489c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1490c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                SpannableStringBuilder tb = new SpannableStringBuilder();
1491c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1492c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // Each bit in the service class gets its own result line
1493c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // The service classes may be split up over multiple
1494c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // CallForwardInfos. So, for each service class, find out
1495c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // which CallForwardInfo represents it and then build
1496c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // the response text based on that
1497c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1498c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                for (int serviceClassMask = 1
1499c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            ; serviceClassMask <= SERVICE_CLASS_MAX
1500c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            ; serviceClassMask <<= 1
1501c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ) {
1502c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    for (int i = 0, s = infos.length; i < s ; i++) {
1503c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        if ((serviceClassMask & infos[i].serviceClass) != 0) {
1504c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            tb.append(makeCFQueryResultMessage(infos[i],
1505c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                                            serviceClassMask));
1506c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            tb.append("\n");
1507c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        }
1508c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
1509c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
1510c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sb.append(tb);
1511c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1512c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
151322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.COMPLETE;
1514c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1515c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
151622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mMessage = sb;
151722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mPhone.onMMIDone(this);
1518c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1519c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1520c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1521c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void
1522c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    onQueryComplete(AsyncResult ar) {
1523c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder(getScString());
1524c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("\n");
1525c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1526c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (ar.exception != null) {
152722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.FAILED;
1528c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            sb.append(getErrorMessage(ar));
1529c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
1530c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            int[] ints = (int[])ar.result;
1531c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1532c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (ints.length != 0) {
1533c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (ints[0] == 0) {
153422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(com.android.internal.R.string.serviceDisabled));
153522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                } else if (mSc.equals(SC_WAIT)) {
1536c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // Call Waiting includes additional data in the response.
1537c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    sb.append(createQueryCallWaitingResultMessage(ints[1]));
153822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                } else if (isServiceCodeCallBarring(mSc)) {
1539c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // ints[0] for Call Barring is a bit vector of services
1540c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    sb.append(createQueryCallBarringResultMessage(ints[0]));
1541c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (ints[0] == 1) {
1542c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // for all other services, treat it as a boolean
154322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(com.android.internal.R.string.serviceEnabled));
1544c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
154522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sb.append(mContext.getText(com.android.internal.R.string.mmiError));
1546c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
1547c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } else {
154822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sb.append(mContext.getText(com.android.internal.R.string.mmiError));
1549c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
155022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mState = State.COMPLETE;
1551c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1552c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
155322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mMessage = sb;
155422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mPhone.onMMIDone(this);
1555c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1556c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1557c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence
1558c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    createQueryCallWaitingResultMessage(int serviceClass) {
1559c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb =
156022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                new StringBuilder(mContext.getText(com.android.internal.R.string.serviceEnabledFor));
1561c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1562c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        for (int classMask = 1
1563c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    ; classMask <= SERVICE_CLASS_MAX
1564c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    ; classMask <<= 1
1565c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        ) {
1566c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if ((classMask & serviceClass) != 0) {
1567c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sb.append("\n");
1568c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sb.append(serviceClassToCFString(classMask & serviceClass));
1569c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1570c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1571c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return sb;
1572c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1573c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private CharSequence
1574c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    createQueryCallBarringResultMessage(int serviceClass)
1575c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    {
157622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        StringBuilder sb = new StringBuilder(mContext.getText(com.android.internal.R.string.serviceEnabledFor));
1577c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1578c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        for (int classMask = 1
1579c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    ; classMask <= SERVICE_CLASS_MAX
1580c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    ; classMask <<= 1
1581c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        ) {
1582c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if ((classMask & serviceClass) != 0) {
1583c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sb.append("\n");
1584c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sb.append(serviceClassToCFString(classMask & serviceClass));
1585c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
1586c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
1587c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return sb;
1588c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1589c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1590c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /***
1591c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * TODO: It would be nice to have a method here that can take in a dialstring and
1592c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * figure out if there is an MMI code embedded within it.  This code would replace
1593c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * some of the string parsing functionality in the Phone App's
1594c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * SpecialCharSequenceMgr class.
1595c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
1596c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1597c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
1598c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public String toString() {
1599c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        StringBuilder sb = new StringBuilder("GsmMmiCode {");
1600c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1601c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("State=" + getState());
160222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mAction != null) sb.append(" action=" + mAction);
160322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mSc != null) sb.append(" sc=" + mSc);
160422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mSia != null) sb.append(" sia=" + mSia);
160522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mSib != null) sb.append(" sib=" + mSib);
160622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mSic != null) sb.append(" sic=" + mSic);
160722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mPoundString != null) sb.append(" poundString=" + mPoundString);
160822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mDialingNumber != null) sb.append(" dialingNumber=" + mDialingNumber);
160922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mPwd != null) sb.append(" pwd=" + mPwd);
1610c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        sb.append("}");
1611c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return sb.toString();
1612c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1613c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville}
1614