RuimRecords.java revision 64bfd98578babdd437f1a83d2d5e1fc92c76e729
1c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/*
2c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Copyright (C) 2008 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
17d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkapackage com.android.internal.telephony.uicc;
18c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
19e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
20c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY;
21c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC;
22e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
23e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenkaimport static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA;
24e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenkaimport static com.android.internal.telephony.TelephonyProperties.PROPERTY_TEST_CSIM;
25e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
2605ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenkaimport java.io.FileDescriptor;
2705ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenkaimport java.io.PrintWriter;
28e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenkaimport java.util.ArrayList;
2905ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenkaimport java.util.Arrays;
30e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenkaimport java.util.Locale;
31c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.content.Context;
32c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.os.AsyncResult;
33c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.os.Handler;
34c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.os.Message;
35c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.os.Registrant;
36c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.os.SystemProperties;
37ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Savilleimport android.telephony.Rlog;
38c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
39c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.CommandsInterface;
40c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.IccCardConstants;
41e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenkaimport com.android.internal.telephony.GsmAlphabet;
42c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.PhoneBase;
43c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.TelephonyProperties;
44c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.MccTable;
45c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
46c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville// can't be used since VoiceMailConstants is not public
47c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville//import com.android.internal.telephony.gsm.VoiceMailConstants;
48c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.PhoneProxy;
49e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenkaimport com.android.internal.telephony.cdma.sms.UserData;
50d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
51c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
52c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
53c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/**
54c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * {@hide}
55c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */
56c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savillepublic final class RuimRecords extends IccRecords {
57c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static final String LOG_TAG = "CDMA";
58c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
59c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final boolean DBG = true;
60c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private boolean  m_ota_commited=false;
61c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
62c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // ***** Instance Variables
63c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
64c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private String mMyMobileNumber;
65c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private String mMin2Min1;
66c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
67c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private String mPrlVersion;
68e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    // From CSIM application
69e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private byte[] mEFpl = null;
70e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private byte[] mEFli = null;
71e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    boolean mCsimSpnDisplayCondition = false;
72e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private String mMdn;
73e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private String mMin;
74e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private String mHomeSystemId;
75e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private String mHomeNetworkId;
76c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
77c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // ***** Event Constants
78c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_GET_IMSI_DONE = 3;
79c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_GET_DEVICE_IDENTITY_DONE = 4;
80c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_GET_ICCID_DONE = 5;
81c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_GET_CDMA_SUBSCRIPTION_DONE = 10;
82c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_UPDATE_DONE = 14;
83c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_GET_SST_DONE = 17;
84c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_GET_ALL_SMS_DONE = 18;
85c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_MARK_SMS_READ_DONE = 19;
86c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
87c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_SMS_ON_RUIM = 21;
88c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_GET_SMS_DONE = 22;
89c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
90c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_RUIM_REFRESH = 31;
91c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
92e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public RuimRecords(UiccCardApplication app, Context c, CommandsInterface ci) {
93e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        super(app, c, ci);
94c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
95c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        adnCache = new AdnRecordCache(mFh);
96c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
97c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        recordsRequested = false;  // No load request is made till SIM ready
98c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
99c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // recordsToLoad is set to 0 because no requests are made yet
100c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        recordsToLoad = 0;
101c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
102c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // NOTE the EVENT_SMS_ON_RUIM is not registered
103c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        mCi.registerForIccRefresh(this, EVENT_RUIM_REFRESH, null);
104c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
105c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Start off by setting empty state
106e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        resetRecords();
107c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
108e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mParentApp.registerForReady(this, EVENT_APP_READY, null);
109c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
110c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
111c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
112c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void dispose() {
113c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (DBG) log("Disposing RuimRecords " + this);
114c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        //Unregister for all events
115c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        mCi.unregisterForIccRefresh(this);
116e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mParentApp.unregisterForReady(this);
117e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        resetRecords();
118c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        super.dispose();
119c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
120c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
121c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
122c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected void finalize() {
123c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if(DBG) log("RuimRecords finalized");
124c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
125c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
126e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    protected void resetRecords() {
127c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        countVoiceMessages = 0;
128c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        mncLength = UNINITIALIZED;
129c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        iccid = null;
130c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
131c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        adnCache.reset();
132c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
133c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Don't clean up PROPERTY_ICC_OPERATOR_ISO_COUNTRY and
134c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // PROPERTY_ICC_OPERATOR_NUMERIC here. Since not all CDMA
135c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // devices have RUIM, these properties should keep the original
136c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // values, e.g. build time settings, when there is no RUIM but
137c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // set new values when RUIM is available and loaded.
138c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
139c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // recordsRequested is set to false indicating that the SIM
140c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // read requests made so far are not valid. This is set to
141c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // true only when fresh set of read requests are made.
142c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        recordsRequested = false;
143c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
144c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
145e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    @Override
146e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public String getIMSI() {
147e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        return mImsi;
148e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
149e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
150c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public String getMdnNumber() {
151c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return mMyMobileNumber;
152c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
153c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
154c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public String getCdmaMin() {
155c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         return mMin2Min1;
156c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
157c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
158c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Returns null if RUIM is not yet ready */
159c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public String getPrlVersion() {
160c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return mPrlVersion;
161c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
162c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
163c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
164c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void setVoiceMailNumber(String alphaTag, String voiceNumber, Message onComplete){
165c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // In CDMA this is Operator/OEM dependent
166c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        AsyncResult.forMessage((onComplete)).exception =
167c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                new IccException("setVoiceMailNumber not implemented");
168c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        onComplete.sendToTarget();
169c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        loge("method setVoiceMailNumber is not implemented");
170c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
171c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
172c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
173c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Called by CCAT Service when REFRESH is received.
174c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param fileChanged indicates whether any files changed
175c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param fileList if non-null, a list of EF files that changed
176c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
177c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
178c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void onRefresh(boolean fileChanged, int[] fileList) {
179c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (fileChanged) {
180c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // A future optimization would be to inspect fileList and
181c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // only reload those files that we care about.  For now,
182c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // just re-fetch all RUIM records that we cache.
183c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            fetchRuimRecords();
184c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
185c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
186c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
187e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private int adjstMinDigits (int digits) {
188e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // Per C.S0005 section 2.3.1.
189e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        digits += 111;
190e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        digits = (digits % 10 == 0)?(digits - 10):digits;
191e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        digits = ((digits / 10) % 10 == 0)?(digits - 100):digits;
192e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        digits = ((digits / 100) % 10 == 0)?(digits - 1000):digits;
193e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        return digits;
194e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
195e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
196c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
197c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Returns the 5 or 6 digit MCC/MNC of the operator that
198c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  provided the RUIM card. Returns null of RUIM is not yet ready
199c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
200c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public String getRUIMOperatorNumeric() {
201c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (mImsi == null) {
202c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return null;
203c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
204c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
205c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (mncLength != UNINITIALIZED && mncLength != UNKNOWN) {
206c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // Length = length of MCC + length of MNC
207c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // length of mcc = 3 (3GPP2 C.S0005 - Section 2.3)
208c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return mImsi.substring(0, 3 + mncLength);
209c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
210c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
211c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Guess the MNC length based on the MCC if we don't
212c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // have a valid value in ef[ad]
213c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
214c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        int mcc = Integer.parseInt(mImsi.substring(0,3));
215c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return mImsi.substring(0, 3 + MccTable.smallestDigitsMccForMnc(mcc));
216c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
217c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
218e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    // Refer to ETSI TS 102.221
219e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private class EfPlLoaded implements IccRecordLoaded {
220e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public String getEfName() {
221e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return "EF_PL";
222e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
223e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
224e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public void onRecordLoaded(AsyncResult ar) {
225e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mEFpl = (byte[]) ar.result;
226e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (DBG) log("EF_PL=" + IccUtils.bytesToHexString(mEFpl));
227e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
228e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
229e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
230e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    // Refer to C.S0065 5.2.26
231e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private class EfCsimLiLoaded implements IccRecordLoaded {
232e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public String getEfName() {
233e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return "EF_CSIM_LI";
234e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
235e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
236e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public void onRecordLoaded(AsyncResult ar) {
237e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mEFli = (byte[]) ar.result;
238e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            // convert csim efli data to iso 639 format
239e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            for (int i = 0; i < mEFli.length; i+=2) {
240e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                switch(mEFli[i+1]) {
241e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case 0x01: mEFli[i] = 'e'; mEFli[i+1] = 'n';break;
242e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case 0x02: mEFli[i] = 'f'; mEFli[i+1] = 'r';break;
243e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case 0x03: mEFli[i] = 'e'; mEFli[i+1] = 's';break;
244e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case 0x04: mEFli[i] = 'j'; mEFli[i+1] = 'a';break;
245e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case 0x05: mEFli[i] = 'k'; mEFli[i+1] = 'o';break;
246e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case 0x06: mEFli[i] = 'z'; mEFli[i+1] = 'h';break;
247e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case 0x07: mEFli[i] = 'h'; mEFli[i+1] = 'e';break;
248e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                default: mEFli[i] = ' '; mEFli[i+1] = ' ';
249e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                }
250e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
251e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
252e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (DBG) log("EF_LI=" + IccUtils.bytesToHexString(mEFli));
253e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
254e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
255e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
256e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    // Refer to C.S0065 5.2.32
257e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private class EfCsimSpnLoaded implements IccRecordLoaded {
258e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public String getEfName() {
259e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return "EF_CSIM_SPN";
260e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
261e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
262e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public void onRecordLoaded(AsyncResult ar) {
263e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            byte[] data = (byte[]) ar.result;
264e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (DBG) log("CSIM_SPN=" +
265e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                         IccUtils.bytesToHexString(data));
266e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
267e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            // C.S0065 for EF_SPN decoding
268e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mCsimSpnDisplayCondition = ((0x01 & data[0]) != 0);
269e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
270e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            int encoding = data[1];
271e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            int language = data[2];
272e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            byte[] spnData = new byte[32];
273e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            int len = ((data.length - 3) < 32) ? (data.length - 3) : 32;
274e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            System.arraycopy(data, 3, spnData, 0, len);
275e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
276e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            int numBytes;
277e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            for (numBytes = 0; numBytes < spnData.length; numBytes++) {
278e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if ((spnData[numBytes] & 0xFF) == 0xFF) break;
279e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
280e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
281e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (numBytes == 0) {
282e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                spn = "";
283e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                return;
284e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
285e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            try {
286e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                switch (encoding) {
287e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case UserData.ENCODING_OCTET:
288e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case UserData.ENCODING_LATIN:
289e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    spn = new String(spnData, 0, numBytes, "ISO-8859-1");
290e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    break;
291e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case UserData.ENCODING_IA5:
292e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case UserData.ENCODING_GSM_7BIT_ALPHABET:
293e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case UserData.ENCODING_7BIT_ASCII:
294e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    spn = GsmAlphabet.gsm7BitPackedToString(spnData, 0, (numBytes*8)/7);
295e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    break;
296e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case UserData.ENCODING_UNICODE_16:
297e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    spn =  new String(spnData, 0, numBytes, "utf-16");
298e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    break;
299e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                default:
300e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    log("SPN encoding not supported");
301e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                }
302e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            } catch(Exception e) {
303e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                log("spn decode error: " + e);
304e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
305e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (DBG) log("spn=" + spn);
306e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (DBG) log("spnCondition=" + mCsimSpnDisplayCondition);
307e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            SystemProperties.set(PROPERTY_ICC_OPERATOR_ALPHA, spn);
308e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
309e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
310e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
311e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private class EfCsimMdnLoaded implements IccRecordLoaded {
312e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public String getEfName() {
313e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return "EF_CSIM_MDN";
314e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
315e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
316e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public void onRecordLoaded(AsyncResult ar) {
317e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            byte[] data = (byte[]) ar.result;
318e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (DBG) log("CSIM_MDN=" + IccUtils.bytesToHexString(data));
319e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            // Refer to C.S0065 5.2.35
320e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            int mdnDigitsNum = 0x0F & data[0];
321e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mMdn = IccUtils.cdmaBcdToString(data, 1, mdnDigitsNum);
322e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (DBG) log("CSIM MDN=" + mMdn);
323e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
324e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
325e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
326e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private class EfCsimImsimLoaded implements IccRecordLoaded {
327e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public String getEfName() {
328e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return "EF_CSIM_IMSIM";
329e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
330e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
331e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public void onRecordLoaded(AsyncResult ar) {
332e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            byte[] data = (byte[]) ar.result;
333e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (DBG) log("CSIM_IMSIM=" + IccUtils.bytesToHexString(data));
334e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            // C.S0065 section 5.2.2 for IMSI_M encoding
335e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            // C.S0005 section 2.3.1 for MIN encoding in IMSI_M.
336e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            boolean provisioned = ((data[7] & 0x80) == 0x80);
337e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
338e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (provisioned) {
339e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                int first3digits = ((0x03 & data[2]) << 8) + (0xFF & data[1]);
340e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                int second3digits = (((0xFF & data[5]) << 8) | (0xFF & data[4])) >> 6;
341e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                int digit7 = 0x0F & (data[4] >> 2);
342e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if (digit7 > 0x09) digit7 = 0;
343e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                int last3digits = ((0x03 & data[4]) << 8) | (0xFF & data[3]);
344e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                first3digits = adjstMinDigits(first3digits);
345e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                second3digits = adjstMinDigits(second3digits);
346e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                last3digits = adjstMinDigits(last3digits);
347e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
348e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                StringBuilder builder = new StringBuilder();
349e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                builder.append(String.format(Locale.US, "%03d", first3digits));
350e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                builder.append(String.format(Locale.US, "%03d", second3digits));
351e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                builder.append(String.format(Locale.US, "%d", digit7));
352e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                builder.append(String.format(Locale.US, "%03d", last3digits));
353e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                mMin = builder.toString();
354e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if (DBG) log("min present=" + mMin);
355e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            } else {
356e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if (DBG) log("min not present");
357e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
358e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
359e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
360e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
361e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private class EfCsimCdmaHomeLoaded implements IccRecordLoaded {
362e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public String getEfName() {
363e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return "EF_CSIM_CDMAHOME";
364e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
365e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
366e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public void onRecordLoaded(AsyncResult ar) {
367e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            // Per C.S0065 section 5.2.8
368e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            ArrayList<byte[]> dataList = (ArrayList<byte[]>) ar.result;
369e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (DBG) log("CSIM_CDMAHOME data size=" + dataList.size());
370e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (dataList.isEmpty()) {
371e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                return;
372e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
373e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            StringBuilder sidBuf = new StringBuilder();
374e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            StringBuilder nidBuf = new StringBuilder();
375e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
376e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            for (byte[] data : dataList) {
377e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if (data.length == 5) {
378e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    int sid = ((data[1] & 0xFF) << 8) | (data[0] & 0xFF);
379e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    int nid = ((data[3] & 0xFF) << 8) | (data[2] & 0xFF);
380e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    sidBuf.append(sid).append(',');
381e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    nidBuf.append(nid).append(',');
382e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                }
383e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
384e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            // remove trailing ","
385e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            sidBuf.setLength(sidBuf.length()-1);
386e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            nidBuf.setLength(nidBuf.length()-1);
387e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
388e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mHomeSystemId = sidBuf.toString();
389e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mHomeNetworkId = nidBuf.toString();
390e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
391e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
392e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
393e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private class EfCsimEprlLoaded implements IccRecordLoaded {
394e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public String getEfName() {
395e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return "EF_CSIM_EPRL";
396e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
397e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public void onRecordLoaded(AsyncResult ar) {
398e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            onGetCSimEprlDone(ar);
399e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
400e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
401e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
402e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private void onGetCSimEprlDone(AsyncResult ar) {
403e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // C.S0065 section 5.2.57 for EFeprl encoding
404e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // C.S0016 section 3.5.5 for PRL format.
405e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        byte[] data = (byte[]) ar.result;
406e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (DBG) log("CSIM_EPRL=" + IccUtils.bytesToHexString(data));
407e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
408e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // Only need the first 4 bytes of record
409e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (data.length > 3) {
410e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            int prlId = ((data[2] & 0xFF) << 8) | (data[3] & 0xFF);
411e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mPrlVersion = Integer.toString(prlId);
412e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
413e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (DBG) log("CSIM PRL version=" + mPrlVersion);
414e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
415e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
416c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
417c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void handleMessage(Message msg) {
418c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        AsyncResult ar;
419c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
420c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        byte data[];
421c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
422c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        boolean isRecordLoadResponse = false;
423c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
424bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        if (mDestroyed.get()) {
425c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            loge("Received message " + msg +
426c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    "[" + msg.what + "] while being destroyed. Ignoring.");
427c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return;
428c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
429c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
430c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        try { switch (msg.what) {
431e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            case EVENT_APP_READY:
432e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                onReady();
433e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                break;
434c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
435c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_GET_DEVICE_IDENTITY_DONE:
436c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                log("Event EVENT_GET_DEVICE_IDENTITY_DONE Received");
437c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
438c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
439c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            /* IO events */
440c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_GET_IMSI_DONE:
441c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                isRecordLoadResponse = true;
442c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
443c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult)msg.obj;
444c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (ar.exception != null) {
445c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    loge("Exception querying IMSI, Exception:" + ar.exception);
446c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    break;
447c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
448c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
449c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                mImsi = (String) ar.result;
450c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
451c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // IMSI (MCC+MNC+MSIN) is at least 6 digits, but not more
452c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // than 15 (and usually 15).
453c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (mImsi != null && (mImsi.length() < 6 || mImsi.length() > 15)) {
454c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    loge("invalid IMSI " + mImsi);
455c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    mImsi = null;
456c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
457c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
458c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                log("IMSI: " + mImsi.substring(0, 6) + "xxxxxxxxx");
459c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
460c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                String operatorNumeric = getRUIMOperatorNumeric();
461c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (operatorNumeric != null) {
462c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    if(operatorNumeric.length() <= 6){
463c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        MccTable.updateMccMncConfiguration(mContext, operatorNumeric);
464c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
465c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
466c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
467c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
468c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_GET_CDMA_SUBSCRIPTION_DONE:
469c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult)msg.obj;
470c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                String localTemp[] = (String[])ar.result;
471c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (ar.exception != null) {
472c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    break;
473c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
474c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
475c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                mMyMobileNumber = localTemp[0];
476c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                mMin2Min1 = localTemp[3];
477c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                mPrlVersion = localTemp[4];
478c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
479c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                log("MDN: " + mMyMobileNumber + " MIN: " + mMin2Min1);
480c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
481c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
482c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
483c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_GET_ICCID_DONE:
484c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                isRecordLoadResponse = true;
485c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
486c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult)msg.obj;
487c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                data = (byte[])ar.result;
488c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
489c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (ar.exception != null) {
490c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    break;
491c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
492c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
493c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                iccid = IccUtils.bcdToString(data, 0, data.length);
494c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
495c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                log("iccid: " + iccid);
496c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
497c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
498c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
499c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_UPDATE_DONE:
500c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult)msg.obj;
501c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (ar.exception != null) {
502ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                    Rlog.i(LOG_TAG, "RuimRecords update failed", ar.exception);
503c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
504c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
505c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
506c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_GET_ALL_SMS_DONE:
507c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_MARK_SMS_READ_DONE:
508c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_SMS_ON_RUIM:
509c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_GET_SMS_DONE:
510ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville                Rlog.w(LOG_TAG, "Event not supported: " + msg.what);
511c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
512c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
513c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // TODO: probably EF_CST should be read instead
514c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_GET_SST_DONE:
515c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                log("Event EVENT_GET_SST_DONE Received");
516c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
517c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
518c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_RUIM_REFRESH:
519c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                isRecordLoadResponse = false;
520c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult)msg.obj;
521c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (ar.exception == null) {
522c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    handleRuimRefresh((IccRefreshResponse)ar.result);
523c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
524c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
525c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
526e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            default:
527e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                super.handleMessage(msg);   // IccRecords handles generic record load responses
528e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
529c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }}catch (RuntimeException exc) {
530c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // I don't want these exceptions to be fatal
531ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville            Rlog.w(LOG_TAG, "Exception parsing RUIM record", exc);
532c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } finally {
533c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // Count up record load responses even if they are fails
534c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (isRecordLoadResponse) {
535c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                onRecordLoaded();
536c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
537c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
538c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
539c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
540e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private String findBestLanguage(byte[] languages) {
541e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        String bestMatch = null;
542e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        String[] locales = mContext.getAssets().getLocales();
543e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
544e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if ((languages == null) || (locales == null)) return null;
545e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
546e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // Each 2-bytes consists of one language
547e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        for (int i = 0; (i + 1) < languages.length; i += 2) {
548e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            try {
549e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                String lang = new String(languages, i, 2, "ISO-8859-1");
550e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                for (int j = 0; j < locales.length; j++) {
551e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    if (locales[j] != null && locales[j].length() >= 2 &&
552e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                        locales[j].substring(0, 2).equals(lang)) {
553e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                        return lang;
554e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    }
555e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                }
556e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if (bestMatch != null) break;
557e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            } catch(java.io.UnsupportedEncodingException e) {
558e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                log ("Failed to parse SIM language records");
559e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
560e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
561e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // no match found. return null
562e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        return null;
563e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
564e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
565e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private void setLocaleFromCsim() {
566e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        String prefLang = null;
567e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // check EFli then EFpl
568e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        prefLang = findBestLanguage(mEFli);
569e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
570e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (prefLang == null) {
571e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            prefLang = findBestLanguage(mEFpl);
572e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
573e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
574e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (prefLang != null) {
575e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            // check country code from SIM
576e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            String imsi = getIMSI();
577e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            String country = null;
578e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (imsi != null) {
579e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                country = MccTable.countryCodeForMcc(
580e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                                    Integer.parseInt(imsi.substring(0,3)));
581e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
582e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            log("Setting locale to " + prefLang + "_" + country);
583e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            MccTable.setSystemLocale(mContext, prefLang, country);
584e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        } else {
585e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            log ("No suitable CSIM selected locale");
586e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
587e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
588e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
589c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
590c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected void onRecordLoaded() {
591c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // One record loaded successfully or failed, In either case
592c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // we need to update the recordsToLoad count
593c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        recordsToLoad -= 1;
594bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        if (DBG) log("onRecordLoaded " + recordsToLoad + " requested: " + recordsRequested);
595c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
596c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (recordsToLoad == 0 && recordsRequested == true) {
597c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            onAllRecordsLoaded();
598c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (recordsToLoad < 0) {
599bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka            loge("recordsToLoad <0, programmer error suspected");
600c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            recordsToLoad = 0;
601c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
602c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
603c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
604c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
605c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected void onAllRecordsLoaded() {
606bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        if (DBG) log("record load complete");
607bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka
608c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Further records that can be inserted are Operator/OEM dependent
609c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
610c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        String operator = getRUIMOperatorNumeric();
611c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        log("RuimRecords: onAllRecordsLoaded set 'gsm.sim.operator.numeric' to operator='" +
612c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                operator + "'");
613c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        SystemProperties.set(PROPERTY_ICC_OPERATOR_NUMERIC, operator);
614c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
615c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (mImsi != null) {
616c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            SystemProperties.set(PROPERTY_ICC_OPERATOR_ISO_COUNTRY,
617c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    MccTable.countryCodeForMcc(Integer.parseInt(mImsi.substring(0,3))));
618c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
619e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
620e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        setLocaleFromCsim();
621c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        recordsLoadedRegistrants.notifyRegistrants(
622c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            new AsyncResult(null, null, null));
623c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
624c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
625c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
626c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void onReady() {
627c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        fetchRuimRecords();
628c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
629c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        mCi.getCDMASubscription(obtainMessage(EVENT_GET_CDMA_SUBSCRIPTION_DONE));
630c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
631c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
632c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
633c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void fetchRuimRecords() {
634c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        recordsRequested = true;
635c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
636bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        if (DBG) log("fetchRuimRecords " + recordsToLoad);
637c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
638e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mCi.getIMSIForApp(mParentApp.getAid(), obtainMessage(EVENT_GET_IMSI_DONE));
639c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        recordsToLoad++;
640c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
641c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        mFh.loadEFTransparent(EF_ICCID,
642c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                obtainMessage(EVENT_GET_ICCID_DONE));
643c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        recordsToLoad++;
644c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
645e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mFh.loadEFTransparent(EF_PL,
646e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfPlLoaded()));
647e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        recordsToLoad++;
648e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
649e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mFh.loadEFTransparent(EF_CSIM_LI,
650e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimLiLoaded()));
651e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        recordsToLoad++;
652e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
653e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mFh.loadEFTransparent(EF_CSIM_SPN,
654e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimSpnLoaded()));
655e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        recordsToLoad++;
656e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
657e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mFh.loadEFLinearFixed(EF_CSIM_MDN, 1,
658e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimMdnLoaded()));
659e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        recordsToLoad++;
660e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
661e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mFh.loadEFTransparent(EF_CSIM_IMSIM,
662e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimImsimLoaded()));
663e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        recordsToLoad++;
664e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
665e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mFh.loadEFLinearFixedAll(EF_CSIM_CDMAHOME,
666e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimCdmaHomeLoaded()));
667e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        recordsToLoad++;
668e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
669e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // Entire PRL could be huge. We are only interested in
670e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // the first 4 bytes of the record.
671e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mFh.loadEFTransparent(EF_CSIM_EPRL, 4,
672e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimEprlLoaded()));
673e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        recordsToLoad++;
674e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
675bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        if (DBG) log("fetchRuimRecords " + recordsToLoad + " requested: " + recordsRequested);
676c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Further records that can be inserted are Operator/OEM dependent
677c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
678c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
679c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
680c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * {@inheritDoc}
681c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
682c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * No Display rule for RUIMs yet.
683c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
684c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
685c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public int getDisplayRule(String plmn) {
686c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // TODO together with spn
687c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return 0;
688c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
689c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
690c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
691e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public boolean isProvisioned() {
692e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // If UICC card has CSIM app, look for MDN and MIN field
693e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // to determine if the SIM is provisioned.  Otherwise,
694e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // consider the SIM is provisioned. (for case of ordinal
695e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // USIM only UICC.)
696e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // If PROPERTY_TEST_CSIM is defined, bypess provision check
697e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // and consider the SIM is provisioned.
698e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (SystemProperties.getBoolean(PROPERTY_TEST_CSIM, false)) {
699e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return true;
700e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
701e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
702e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (mParentApp == null) {
703e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return false;
704e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
705e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
706e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (mParentApp.getType() == AppType.APPTYPE_CSIM &&
707e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            ((mMdn == null) || (mMin == null))) {
708e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return false;
709e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
710e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        return true;
711e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
712e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
713e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    @Override
714c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void setVoiceMessageWaiting(int line, int countWaiting) {
715c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (line != 1) {
716c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // only profile 1 is supported
717c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return;
718c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
719c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
720c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // range check
721c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (countWaiting < 0) {
722c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            countWaiting = -1;
723c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (countWaiting > 0xff) {
724c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // C.S0015-B v2, 4.5.12
725c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // range: 0-99
726c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            countWaiting = 0xff;
727c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
728c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        countVoiceMessages = countWaiting;
729c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
730c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        mRecordsEventsRegistrants.notifyResult(EVENT_MWI);
731c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
732c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
733c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void handleRuimRefresh(IccRefreshResponse refreshResponse) {
734c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (refreshResponse == null) {
735c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (DBG) log("handleRuimRefresh received without input");
736c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return;
737c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
738c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
739c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (refreshResponse.aid != null &&
740e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                !refreshResponse.aid.equals(mParentApp.getAid())) {
741c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // This is for different app. Ignore.
742c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return;
743c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
744c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
745c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        switch (refreshResponse.refreshResult) {
746c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case IccRefreshResponse.REFRESH_RESULT_FILE_UPDATE:
747c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (DBG) log("handleRuimRefresh with SIM_REFRESH_FILE_UPDATED");
748c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                adnCache.reset();
749c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                fetchRuimRecords();
750c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
751c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case IccRefreshResponse.REFRESH_RESULT_INIT:
752c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (DBG) log("handleRuimRefresh with SIM_REFRESH_INIT");
753c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // need to reload all files (that we care about)
75464bfd98578babdd437f1a83d2d5e1fc92c76e729Alex Yakavenka                onIccRefreshInit();
755c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
756c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case IccRefreshResponse.REFRESH_RESULT_RESET:
757c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (DBG) log("handleRuimRefresh with SIM_REFRESH_RESET");
758c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                mCi.setRadioPower(false, null);
759c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                /* Note: no need to call setRadioPower(true).  Assuming the desired
760c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                * radio power state is still ON (as tracked by ServiceStateTracker),
761c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                * ServiceStateTracker will call setRadioPower when it receives the
762c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                * RADIO_STATE_CHANGED notification for the power off.  And if the
763c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                * desired power state has changed in the interim, we don't want to
764c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                * override it with an unconditional power on.
765c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                */
766c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
767c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            default:
768c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // unknown refresh operation
769c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (DBG) log("handleRuimRefresh with unknown operation");
770c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
771c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
772c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
773c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
774e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public String getMdn() {
775e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        return mMdn;
776e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
777e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
778e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public String getMin() {
779e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        return mMin;
780e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
781e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
782e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public String getSid() {
783e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        return mHomeSystemId;
784e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
785e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
786e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public String getNid() {
787e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        return mHomeNetworkId;
788e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
789e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
790e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public boolean getCsimSpnDisplayCondition() {
791e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        return mCsimSpnDisplayCondition;
792e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
793c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
794c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected void log(String s) {
795ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville        Rlog.d(LOG_TAG, "[RuimRecords] " + s);
796c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
797c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
798c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
799c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected void loge(String s) {
800ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville        Rlog.e(LOG_TAG, "[RuimRecords] " + s);
801c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
80205ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka
80305ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka    @Override
80405ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
80505ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println("RuimRecords: " + this);
80605ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" extends:");
80705ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        super.dump(fd, pw, args);
80805ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" m_ota_commited=" + m_ota_commited);
80905ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mMyMobileNumber=" + mMyMobileNumber);
81005ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mMin2Min1=" + mMin2Min1);
81105ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mPrlVersion=" + mPrlVersion);
81205ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mEFpl[]=" + Arrays.toString(mEFpl));
81305ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mEFli[]=" + Arrays.toString(mEFli));
81405ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mCsimSpnDisplayCondition=" + mCsimSpnDisplayCondition);
81505ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mMdn=" + mMdn);
81605ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mMin=" + mMin);
81705ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mHomeSystemId=" + mHomeSystemId);
81805ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mHomeNetworkId=" + mHomeNetworkId);
81905ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.flush();
82005ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka    }
821c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville}
822