RuimRecords.java revision 153077e0b2d9ff6f115a0739dac1d64931bffb91
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 Yakavenkaimport static com.android.internal.telephony.TelephonyProperties.PROPERTY_TEST_CSIM;
20e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
2105ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenkaimport java.io.FileDescriptor;
2205ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenkaimport java.io.PrintWriter;
23e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenkaimport java.util.ArrayList;
2405ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenkaimport java.util.Arrays;
25e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenkaimport java.util.Locale;
26c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.content.Context;
27c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.os.AsyncResult;
28c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.os.Message;
29c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.os.SystemProperties;
30c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yuimport android.telephony.SubscriptionInfo;
315866914ae9798adebcb84cd710bca660b797bff0Amit Mahajanimport android.telephony.SubscriptionManager;
3299c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Savilleimport android.telephony.Rlog;
33e9070e6d48d1389987650fa2c3e1f90aab860684Wink Savilleimport android.text.TextUtils;
342351b17aba5350004fc76707f3b3d2859ce773c8xinheimport android.util.Log;
35e409b02a691d5bb0515aab41cfa597c725eb9174duho.roimport android.content.res.Resources;
36c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
37c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.CommandsInterface;
38e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenkaimport com.android.internal.telephony.GsmAlphabet;
39c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.MccTable;
40062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawalimport com.android.internal.telephony.SubscriptionController;
41c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
42e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenkaimport com.android.internal.telephony.cdma.sms.UserData;
43d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
442351b17aba5350004fc76707f3b3d2859ce773c8xinheimport com.android.internal.util.BitwiseInputStream;
45c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
46c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/**
47c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * {@hide}
48c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */
49153077e0b2d9ff6f115a0739dac1d64931bffb91Amit Mahajanpublic class RuimRecords extends IccRecords {
50cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    static final String LOG_TAG = "RuimRecords";
51c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
5222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    private boolean  mOtaCommited=false;
53c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
54c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // ***** Instance Variables
55c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
56c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private String mMyMobileNumber;
57c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private String mMin2Min1;
58c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
59c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private String mPrlVersion;
60e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    // From CSIM application
61e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private byte[] mEFpl = null;
62e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private byte[] mEFli = null;
63e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    boolean mCsimSpnDisplayCondition = false;
64e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private String mMdn;
65e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private String mMin;
66e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private String mHomeSystemId;
67e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private String mHomeNetworkId;
682351b17aba5350004fc76707f3b3d2859ce773c8xinhe    private String mNai;
69c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
70f92cb4bd5519427a0db673709d94683a8baf203aWink Saville    @Override
71f92cb4bd5519427a0db673709d94683a8baf203aWink Saville    public String toString() {
72f92cb4bd5519427a0db673709d94683a8baf203aWink Saville        return "RuimRecords: " + super.toString()
7322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                + " m_ota_commited" + mOtaCommited
74f92cb4bd5519427a0db673709d94683a8baf203aWink Saville                + " mMyMobileNumber=" + "xxxx"
75f92cb4bd5519427a0db673709d94683a8baf203aWink Saville                + " mMin2Min1=" + mMin2Min1
76f92cb4bd5519427a0db673709d94683a8baf203aWink Saville                + " mPrlVersion=" + mPrlVersion
77f92cb4bd5519427a0db673709d94683a8baf203aWink Saville                + " mEFpl=" + mEFpl
78f92cb4bd5519427a0db673709d94683a8baf203aWink Saville                + " mEFli=" + mEFli
79f92cb4bd5519427a0db673709d94683a8baf203aWink Saville                + " mCsimSpnDisplayCondition=" + mCsimSpnDisplayCondition
80f92cb4bd5519427a0db673709d94683a8baf203aWink Saville                + " mMdn=" + mMdn
81f92cb4bd5519427a0db673709d94683a8baf203aWink Saville                + " mMin=" + mMin
82f92cb4bd5519427a0db673709d94683a8baf203aWink Saville                + " mHomeSystemId=" + mHomeSystemId
83f92cb4bd5519427a0db673709d94683a8baf203aWink Saville                + " mHomeNetworkId=" + mHomeNetworkId;
84f92cb4bd5519427a0db673709d94683a8baf203aWink Saville    }
85f92cb4bd5519427a0db673709d94683a8baf203aWink Saville
86c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // ***** Event Constants
87c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_GET_IMSI_DONE = 3;
88c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_GET_DEVICE_IDENTITY_DONE = 4;
89c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_GET_ICCID_DONE = 5;
90c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_GET_CDMA_SUBSCRIPTION_DONE = 10;
91c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_UPDATE_DONE = 14;
92c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_GET_SST_DONE = 17;
93c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_GET_ALL_SMS_DONE = 18;
94c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_MARK_SMS_READ_DONE = 19;
95c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
96c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_SMS_ON_RUIM = 21;
97c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_GET_SMS_DONE = 22;
98c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
99c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_RUIM_REFRESH = 31;
100c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
101e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public RuimRecords(UiccCardApplication app, Context c, CommandsInterface ci) {
102e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        super(app, c, ci);
103c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
10422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mAdnCache = new AdnRecordCache(mFh);
105c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
10622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mRecordsRequested = false;  // No load request is made till SIM ready
107c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
108c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // recordsToLoad is set to 0 because no requests are made yet
10922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mRecordsToLoad = 0;
110c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
111c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // NOTE the EVENT_SMS_ON_RUIM is not registered
112c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        mCi.registerForIccRefresh(this, EVENT_RUIM_REFRESH, null);
113c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
114c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Start off by setting empty state
115e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        resetRecords();
116c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
117e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mParentApp.registerForReady(this, EVENT_APP_READY, null);
118f92cb4bd5519427a0db673709d94683a8baf203aWink Saville        if (DBG) log("RuimRecords X ctor this=" + this);
119c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
120c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
121c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
122c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void dispose() {
123c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (DBG) log("Disposing RuimRecords " + this);
124c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        //Unregister for all events
125c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        mCi.unregisterForIccRefresh(this);
126e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mParentApp.unregisterForReady(this);
127e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        resetRecords();
128c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        super.dispose();
129c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
130c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
131c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
132c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected void finalize() {
133c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if(DBG) log("RuimRecords finalized");
134c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
135c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
136e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    protected void resetRecords() {
13722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mMncLength = UNINITIALIZED;
138a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        log("setting0 mMncLength" + mMncLength);
139b7881d6e7e4e79491376bedf151c3412dfdc4121Wink Saville        mIccId = null;
140c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
14122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mAdnCache.reset();
142c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
143c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Don't clean up PROPERTY_ICC_OPERATOR_ISO_COUNTRY and
144c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // PROPERTY_ICC_OPERATOR_NUMERIC here. Since not all CDMA
145c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // devices have RUIM, these properties should keep the original
146c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // values, e.g. build time settings, when there is no RUIM but
147c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // set new values when RUIM is available and loaded.
148c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
149c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // recordsRequested is set to false indicating that the SIM
150c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // read requests made so far are not valid. This is set to
151c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // true only when fresh set of read requests are made.
15222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mRecordsRequested = false;
153c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
154c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
155e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    @Override
156e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public String getIMSI() {
157e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        return mImsi;
158e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
159e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
160c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public String getMdnNumber() {
161c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return mMyMobileNumber;
162c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
163c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
164c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public String getCdmaMin() {
165c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         return mMin2Min1;
166c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
167c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
168c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Returns null if RUIM is not yet ready */
169c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public String getPrlVersion() {
170c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return mPrlVersion;
171c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
172c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
173c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
1742351b17aba5350004fc76707f3b3d2859ce773c8xinhe    /** Returns null if RUIM is not yet ready */
1752351b17aba5350004fc76707f3b3d2859ce773c8xinhe    public String getNAI() {
1762351b17aba5350004fc76707f3b3d2859ce773c8xinhe        return mNai;
1772351b17aba5350004fc76707f3b3d2859ce773c8xinhe    }
1782351b17aba5350004fc76707f3b3d2859ce773c8xinhe
1792351b17aba5350004fc76707f3b3d2859ce773c8xinhe    @Override
180c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void setVoiceMailNumber(String alphaTag, String voiceNumber, Message onComplete){
181c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // In CDMA this is Operator/OEM dependent
182c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        AsyncResult.forMessage((onComplete)).exception =
183c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                new IccException("setVoiceMailNumber not implemented");
184c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        onComplete.sendToTarget();
185c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        loge("method setVoiceMailNumber is not implemented");
186c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
187c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
188c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
189c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Called by CCAT Service when REFRESH is received.
190c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param fileChanged indicates whether any files changed
191c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param fileList if non-null, a list of EF files that changed
192c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
193c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
194c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void onRefresh(boolean fileChanged, int[] fileList) {
195c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (fileChanged) {
196c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // A future optimization would be to inspect fileList and
197c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // only reload those files that we care about.  For now,
198c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // just re-fetch all RUIM records that we cache.
199c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            fetchRuimRecords();
200c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
201c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
202c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
203e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private int adjstMinDigits (int digits) {
204e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // Per C.S0005 section 2.3.1.
205e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        digits += 111;
206e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        digits = (digits % 10 == 0)?(digits - 10):digits;
207e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        digits = ((digits / 10) % 10 == 0)?(digits - 100):digits;
208e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        digits = ((digits / 100) % 10 == 0)?(digits - 1000):digits;
209e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        return digits;
210e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
211e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
212c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
213c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Returns the 5 or 6 digit MCC/MNC of the operator that
214c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  provided the RUIM card. Returns null of RUIM is not yet ready
215c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
216c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public String getRUIMOperatorNumeric() {
217c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (mImsi == null) {
218c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return null;
219c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
220c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
22122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mMncLength != UNINITIALIZED && mMncLength != UNKNOWN) {
222c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // Length = length of MCC + length of MNC
223c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // length of mcc = 3 (3GPP2 C.S0005 - Section 2.3)
22422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            return mImsi.substring(0, 3 + mMncLength);
225c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
226c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
227c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Guess the MNC length based on the MCC if we don't
228c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // have a valid value in ef[ad]
229c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
230c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        int mcc = Integer.parseInt(mImsi.substring(0,3));
231c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return mImsi.substring(0, 3 + MccTable.smallestDigitsMccForMnc(mcc));
232c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
233c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
234e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    // Refer to ETSI TS 102.221
235e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private class EfPlLoaded implements IccRecordLoaded {
236cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        @Override
237e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public String getEfName() {
238e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return "EF_PL";
239e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
240e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
241cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        @Override
242e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public void onRecordLoaded(AsyncResult ar) {
243e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mEFpl = (byte[]) ar.result;
244e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (DBG) log("EF_PL=" + IccUtils.bytesToHexString(mEFpl));
245e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
246e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
247e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
248e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    // Refer to C.S0065 5.2.26
249e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private class EfCsimLiLoaded implements IccRecordLoaded {
250cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        @Override
251e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public String getEfName() {
252e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return "EF_CSIM_LI";
253e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
254e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
255cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        @Override
256e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public void onRecordLoaded(AsyncResult ar) {
257e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mEFli = (byte[]) ar.result;
258e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            // convert csim efli data to iso 639 format
259e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            for (int i = 0; i < mEFli.length; i+=2) {
260e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                switch(mEFli[i+1]) {
261e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case 0x01: mEFli[i] = 'e'; mEFli[i+1] = 'n';break;
262e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case 0x02: mEFli[i] = 'f'; mEFli[i+1] = 'r';break;
263e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case 0x03: mEFli[i] = 'e'; mEFli[i+1] = 's';break;
264e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case 0x04: mEFli[i] = 'j'; mEFli[i+1] = 'a';break;
265e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case 0x05: mEFli[i] = 'k'; mEFli[i+1] = 'o';break;
266e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case 0x06: mEFli[i] = 'z'; mEFli[i+1] = 'h';break;
267e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case 0x07: mEFli[i] = 'h'; mEFli[i+1] = 'e';break;
268e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                default: mEFli[i] = ' '; mEFli[i+1] = ' ';
269e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                }
270e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
271e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
272e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (DBG) log("EF_LI=" + IccUtils.bytesToHexString(mEFli));
273e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
274e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
275e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
276e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    // Refer to C.S0065 5.2.32
277e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private class EfCsimSpnLoaded implements IccRecordLoaded {
278cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        @Override
279e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public String getEfName() {
280e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return "EF_CSIM_SPN";
281e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
282e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
283cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        @Override
284e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public void onRecordLoaded(AsyncResult ar) {
285e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            byte[] data = (byte[]) ar.result;
286e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (DBG) log("CSIM_SPN=" +
287e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                         IccUtils.bytesToHexString(data));
288e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
289e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            // C.S0065 for EF_SPN decoding
290e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mCsimSpnDisplayCondition = ((0x01 & data[0]) != 0);
291e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
292e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            int encoding = data[1];
293e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            int language = data[2];
294e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            byte[] spnData = new byte[32];
295e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            int len = ((data.length - 3) < 32) ? (data.length - 3) : 32;
296e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            System.arraycopy(data, 3, spnData, 0, len);
297e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
298e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            int numBytes;
299e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            for (numBytes = 0; numBytes < spnData.length; numBytes++) {
300e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if ((spnData[numBytes] & 0xFF) == 0xFF) break;
301e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
302e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
303e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (numBytes == 0) {
304b93bb3538c55f173f94a4ee7510d9d1521d8f731Shishir Agrawal                setServiceProviderName("");
305e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                return;
306e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
307e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            try {
308e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                switch (encoding) {
309e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case UserData.ENCODING_OCTET:
310e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case UserData.ENCODING_LATIN:
311b93bb3538c55f173f94a4ee7510d9d1521d8f731Shishir Agrawal                    setServiceProviderName(new String(spnData, 0, numBytes, "ISO-8859-1"));
312e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    break;
313e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case UserData.ENCODING_IA5:
314e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case UserData.ENCODING_GSM_7BIT_ALPHABET:
315b93bb3538c55f173f94a4ee7510d9d1521d8f731Shishir Agrawal                    setServiceProviderName(
316b93bb3538c55f173f94a4ee7510d9d1521d8f731Shishir Agrawal                            GsmAlphabet.gsm7BitPackedToString(spnData, 0, (numBytes*8)/7));
317e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    break;
31860e3a52dad667a094af0c269176ee30da739ee84Sandeep Gutta                case UserData.ENCODING_7BIT_ASCII:
319b5d27d8e567ef835e961548b144cdad95d2361deJing Zhao                    String spn = new String(spnData, 0, numBytes, "US-ASCII");
320b5d27d8e567ef835e961548b144cdad95d2361deJing Zhao                    // To address issues with incorrect encoding scheme
321b5d27d8e567ef835e961548b144cdad95d2361deJing Zhao                    // programmed in some commercial CSIM cards, the decoded
322b5d27d8e567ef835e961548b144cdad95d2361deJing Zhao                    // SPN is checked to have characters in printable ASCII
323b5d27d8e567ef835e961548b144cdad95d2361deJing Zhao                    // range. If not, they are decoded with
324b5d27d8e567ef835e961548b144cdad95d2361deJing Zhao                    // ENCODING_GSM_7BIT_ALPHABET scheme.
325b5d27d8e567ef835e961548b144cdad95d2361deJing Zhao                    if (TextUtils.isPrintableAsciiOnly(spn)) {
326b5d27d8e567ef835e961548b144cdad95d2361deJing Zhao                        setServiceProviderName(spn);
327b5d27d8e567ef835e961548b144cdad95d2361deJing Zhao                    } else {
328b5d27d8e567ef835e961548b144cdad95d2361deJing Zhao                        if (DBG) log("Some corruption in SPN decoding = " + spn);
329b5d27d8e567ef835e961548b144cdad95d2361deJing Zhao                        if (DBG) log("Using ENCODING_GSM_7BIT_ALPHABET scheme...");
330b5d27d8e567ef835e961548b144cdad95d2361deJing Zhao                        setServiceProviderName(
331b5d27d8e567ef835e961548b144cdad95d2361deJing Zhao                                GsmAlphabet.gsm7BitPackedToString(spnData, 0, (numBytes * 8) / 7));
332b5d27d8e567ef835e961548b144cdad95d2361deJing Zhao                    }
33360e3a52dad667a094af0c269176ee30da739ee84Sandeep Gutta                break;
334e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case UserData.ENCODING_UNICODE_16:
335b93bb3538c55f173f94a4ee7510d9d1521d8f731Shishir Agrawal                    setServiceProviderName(new String(spnData, 0, numBytes, "utf-16"));
336e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    break;
337e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                default:
338e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    log("SPN encoding not supported");
339e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                }
340e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            } catch(Exception e) {
341e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                log("spn decode error: " + e);
342e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
343b93bb3538c55f173f94a4ee7510d9d1521d8f731Shishir Agrawal            if (DBG) log("spn=" + getServiceProviderName());
344e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (DBG) log("spnCondition=" + mCsimSpnDisplayCondition);
345e70617d81dcd42350a737b11c25532e1d43df4ffLegler Wu            mTelephonyManager.setSimOperatorNameForPhone(
346e70617d81dcd42350a737b11c25532e1d43df4ffLegler Wu                    mParentApp.getPhoneId(), getServiceProviderName());
347e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
348e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
349e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
350e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private class EfCsimMdnLoaded implements IccRecordLoaded {
351cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        @Override
352e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public String getEfName() {
353e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return "EF_CSIM_MDN";
354e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
355e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
356cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        @Override
357e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public void onRecordLoaded(AsyncResult ar) {
358e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            byte[] data = (byte[]) ar.result;
359e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (DBG) log("CSIM_MDN=" + IccUtils.bytesToHexString(data));
360e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            // Refer to C.S0065 5.2.35
361e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            int mdnDigitsNum = 0x0F & data[0];
362e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mMdn = IccUtils.cdmaBcdToString(data, 1, mdnDigitsNum);
363e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (DBG) log("CSIM MDN=" + mMdn);
364e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
365e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
366e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
367e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private class EfCsimImsimLoaded implements IccRecordLoaded {
368cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        @Override
369e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public String getEfName() {
370e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return "EF_CSIM_IMSIM";
371e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
372e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
373cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        @Override
374e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public void onRecordLoaded(AsyncResult ar) {
375e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            byte[] data = (byte[]) ar.result;
376f9f73e5f5125df262b8c2bec21de5600dc4d1801Etan Cohen            if (VDBG) log("CSIM_IMSIM=" + IccUtils.bytesToHexString(data));
377e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            // C.S0065 section 5.2.2 for IMSI_M encoding
378e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            // C.S0005 section 2.3.1 for MIN encoding in IMSI_M.
379e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            boolean provisioned = ((data[7] & 0x80) == 0x80);
380e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
381e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (provisioned) {
382e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                int first3digits = ((0x03 & data[2]) << 8) + (0xFF & data[1]);
383e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                int second3digits = (((0xFF & data[5]) << 8) | (0xFF & data[4])) >> 6;
384e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                int digit7 = 0x0F & (data[4] >> 2);
385e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if (digit7 > 0x09) digit7 = 0;
386e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                int last3digits = ((0x03 & data[4]) << 8) | (0xFF & data[3]);
387e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                first3digits = adjstMinDigits(first3digits);
388e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                second3digits = adjstMinDigits(second3digits);
389e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                last3digits = adjstMinDigits(last3digits);
390e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
391e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                StringBuilder builder = new StringBuilder();
392e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                builder.append(String.format(Locale.US, "%03d", first3digits));
393e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                builder.append(String.format(Locale.US, "%03d", second3digits));
394e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                builder.append(String.format(Locale.US, "%d", digit7));
395e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                builder.append(String.format(Locale.US, "%03d", last3digits));
396e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                mMin = builder.toString();
397e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if (DBG) log("min present=" + mMin);
398e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            } else {
399e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if (DBG) log("min not present");
400e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
401e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
402e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
403e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
404e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private class EfCsimCdmaHomeLoaded implements IccRecordLoaded {
405cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        @Override
406e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public String getEfName() {
407e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return "EF_CSIM_CDMAHOME";
408e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
409e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
410cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        @Override
411e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public void onRecordLoaded(AsyncResult ar) {
412e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            // Per C.S0065 section 5.2.8
413e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            ArrayList<byte[]> dataList = (ArrayList<byte[]>) ar.result;
414e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (DBG) log("CSIM_CDMAHOME data size=" + dataList.size());
415e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (dataList.isEmpty()) {
416e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                return;
417e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
418e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            StringBuilder sidBuf = new StringBuilder();
419e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            StringBuilder nidBuf = new StringBuilder();
420e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
421e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            for (byte[] data : dataList) {
422e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if (data.length == 5) {
423e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    int sid = ((data[1] & 0xFF) << 8) | (data[0] & 0xFF);
424e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    int nid = ((data[3] & 0xFF) << 8) | (data[2] & 0xFF);
425e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    sidBuf.append(sid).append(',');
426e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    nidBuf.append(nid).append(',');
427e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                }
428e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
429e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            // remove trailing ","
430e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            sidBuf.setLength(sidBuf.length()-1);
431e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            nidBuf.setLength(nidBuf.length()-1);
432e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
433e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mHomeSystemId = sidBuf.toString();
434e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mHomeNetworkId = nidBuf.toString();
435e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
436e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
437e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
438e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private class EfCsimEprlLoaded implements IccRecordLoaded {
439cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        @Override
440e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public String getEfName() {
441e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return "EF_CSIM_EPRL";
442e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
443cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        @Override
444e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public void onRecordLoaded(AsyncResult ar) {
445e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            onGetCSimEprlDone(ar);
446e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
447e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
448e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
449e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private void onGetCSimEprlDone(AsyncResult ar) {
450e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // C.S0065 section 5.2.57 for EFeprl encoding
451e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // C.S0016 section 3.5.5 for PRL format.
452e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        byte[] data = (byte[]) ar.result;
453e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (DBG) log("CSIM_EPRL=" + IccUtils.bytesToHexString(data));
454e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
455e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // Only need the first 4 bytes of record
456e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (data.length > 3) {
457e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            int prlId = ((data[2] & 0xFF) << 8) | (data[3] & 0xFF);
458e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mPrlVersion = Integer.toString(prlId);
459e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
460e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (DBG) log("CSIM PRL version=" + mPrlVersion);
461e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
462e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
4632351b17aba5350004fc76707f3b3d2859ce773c8xinhe    private class EfCsimMipUppLoaded implements IccRecordLoaded {
4642351b17aba5350004fc76707f3b3d2859ce773c8xinhe        @Override
4652351b17aba5350004fc76707f3b3d2859ce773c8xinhe        public String getEfName() {
4662351b17aba5350004fc76707f3b3d2859ce773c8xinhe            return "EF_CSIM_MIPUPP";
4672351b17aba5350004fc76707f3b3d2859ce773c8xinhe        }
4682351b17aba5350004fc76707f3b3d2859ce773c8xinhe
4692351b17aba5350004fc76707f3b3d2859ce773c8xinhe        boolean checkLengthLegal(int length, int expectLength) {
4702351b17aba5350004fc76707f3b3d2859ce773c8xinhe            if(length < expectLength) {
4712351b17aba5350004fc76707f3b3d2859ce773c8xinhe                Log.e(LOG_TAG, "CSIM MIPUPP format error, length = " + length  +
4722351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        "expected length at least =" + expectLength);
4732351b17aba5350004fc76707f3b3d2859ce773c8xinhe                return false;
4742351b17aba5350004fc76707f3b3d2859ce773c8xinhe            } else {
4752351b17aba5350004fc76707f3b3d2859ce773c8xinhe                return true;
4762351b17aba5350004fc76707f3b3d2859ce773c8xinhe            }
4772351b17aba5350004fc76707f3b3d2859ce773c8xinhe        }
4782351b17aba5350004fc76707f3b3d2859ce773c8xinhe
4792351b17aba5350004fc76707f3b3d2859ce773c8xinhe        @Override
4802351b17aba5350004fc76707f3b3d2859ce773c8xinhe        public void onRecordLoaded(AsyncResult ar) {
4812351b17aba5350004fc76707f3b3d2859ce773c8xinhe            // 3GPP2 C.S0065 section 5.2.24
4822351b17aba5350004fc76707f3b3d2859ce773c8xinhe            byte[] data = (byte[]) ar.result;
4832351b17aba5350004fc76707f3b3d2859ce773c8xinhe
4842351b17aba5350004fc76707f3b3d2859ce773c8xinhe            if(data.length < 1) {
4852351b17aba5350004fc76707f3b3d2859ce773c8xinhe                Log.e(LOG_TAG,"MIPUPP read error");
4862351b17aba5350004fc76707f3b3d2859ce773c8xinhe                return;
4872351b17aba5350004fc76707f3b3d2859ce773c8xinhe            }
4882351b17aba5350004fc76707f3b3d2859ce773c8xinhe
4892351b17aba5350004fc76707f3b3d2859ce773c8xinhe            BitwiseInputStream bitStream = new BitwiseInputStream(data);
4902351b17aba5350004fc76707f3b3d2859ce773c8xinhe            try {
4912351b17aba5350004fc76707f3b3d2859ce773c8xinhe                int  mipUppLength = bitStream.read(8);
4922351b17aba5350004fc76707f3b3d2859ce773c8xinhe                //transfer length from byte to bit
4932351b17aba5350004fc76707f3b3d2859ce773c8xinhe                mipUppLength = (mipUppLength << 3);
4942351b17aba5350004fc76707f3b3d2859ce773c8xinhe
4952351b17aba5350004fc76707f3b3d2859ce773c8xinhe                if (!checkLengthLegal(mipUppLength, 1)) {
4962351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    return;
4972351b17aba5350004fc76707f3b3d2859ce773c8xinhe                }
4982351b17aba5350004fc76707f3b3d2859ce773c8xinhe                //parse the MIPUPP body 3GPP2 C.S0016-C 3.5.8.6
4992351b17aba5350004fc76707f3b3d2859ce773c8xinhe                int retryInfoInclude = bitStream.read(1);
5002351b17aba5350004fc76707f3b3d2859ce773c8xinhe                mipUppLength--;
5012351b17aba5350004fc76707f3b3d2859ce773c8xinhe
5022351b17aba5350004fc76707f3b3d2859ce773c8xinhe                if(retryInfoInclude == 1) {
5032351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    if (!checkLengthLegal(mipUppLength, 11)) {
5042351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        return;
5052351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    }
5062351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    bitStream.skip(11); //not used now
5072351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    //transfer length from byte to bit
5082351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    mipUppLength -= 11;
5092351b17aba5350004fc76707f3b3d2859ce773c8xinhe                }
5102351b17aba5350004fc76707f3b3d2859ce773c8xinhe
5112351b17aba5350004fc76707f3b3d2859ce773c8xinhe                if (!checkLengthLegal(mipUppLength, 4)) {
5122351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    return;
5132351b17aba5350004fc76707f3b3d2859ce773c8xinhe                }
5142351b17aba5350004fc76707f3b3d2859ce773c8xinhe                int numNai = bitStream.read(4);
5152351b17aba5350004fc76707f3b3d2859ce773c8xinhe                mipUppLength -= 4;
5162351b17aba5350004fc76707f3b3d2859ce773c8xinhe
5172351b17aba5350004fc76707f3b3d2859ce773c8xinhe                //start parse NAI body
5182351b17aba5350004fc76707f3b3d2859ce773c8xinhe                for(int index = 0; index < numNai; index++) {
5192351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    if (!checkLengthLegal(mipUppLength, 4)) {
5202351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        return;
5212351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    }
5222351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    int naiEntryIndex = bitStream.read(4);
5232351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    mipUppLength -= 4;
5242351b17aba5350004fc76707f3b3d2859ce773c8xinhe
5252351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    if (!checkLengthLegal(mipUppLength, 8)) {
5262351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        return;
5272351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    }
5282351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    int naiLength = bitStream.read(8);
5292351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    mipUppLength -= 8;
5302351b17aba5350004fc76707f3b3d2859ce773c8xinhe
5312351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    if(naiEntryIndex == 0) {
5322351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        //we find the one!
5332351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        if (!checkLengthLegal(mipUppLength, naiLength << 3)) {
5342351b17aba5350004fc76707f3b3d2859ce773c8xinhe                            return;
5352351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        }
5362351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        char naiCharArray[] = new char[naiLength];
5372351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        for(int index1 = 0; index1 < naiLength; index1++) {
5382351b17aba5350004fc76707f3b3d2859ce773c8xinhe                            naiCharArray[index1] = (char)(bitStream.read(8) & 0xFF);
5392351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        }
5402351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        mNai =  new String(naiCharArray);
541e9fdc85df2111a0a0d7d240bbc11ed5b14b01376xinhe                        if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
542e9fdc85df2111a0a0d7d240bbc11ed5b14b01376xinhe                            Log.v(LOG_TAG,"MIPUPP Nai = " + mNai);
543e9fdc85df2111a0a0d7d240bbc11ed5b14b01376xinhe                        }
5442351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        return; //need not parsing further
5452351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    } else {
5462351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        //ignore this NAI body
5472351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        if (!checkLengthLegal(mipUppLength, (naiLength << 3) + 102)) {
5482351b17aba5350004fc76707f3b3d2859ce773c8xinhe                            return;
5492351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        }
5502351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        bitStream.skip((naiLength << 3) + 101);//not used
5512351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        int mnAaaSpiIndicator = bitStream.read(1);
5522351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        mipUppLength -= ((naiLength << 3) + 102);
5532351b17aba5350004fc76707f3b3d2859ce773c8xinhe
5542351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        if(mnAaaSpiIndicator == 1) {
5552351b17aba5350004fc76707f3b3d2859ce773c8xinhe                            if (!checkLengthLegal(mipUppLength, 32)) {
5562351b17aba5350004fc76707f3b3d2859ce773c8xinhe                                return;
5572351b17aba5350004fc76707f3b3d2859ce773c8xinhe                            }
5582351b17aba5350004fc76707f3b3d2859ce773c8xinhe                            bitStream.skip(32); //not used
5592351b17aba5350004fc76707f3b3d2859ce773c8xinhe                            mipUppLength -= 32;
5602351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        }
5612351b17aba5350004fc76707f3b3d2859ce773c8xinhe
5622351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        //MN-HA_AUTH_ALGORITHM
5632351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        if (!checkLengthLegal(mipUppLength, 5)) {
5642351b17aba5350004fc76707f3b3d2859ce773c8xinhe                            return;
5652351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        }
5662351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        bitStream.skip(4);
5672351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        mipUppLength -= 4;
5682351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        int mnHaSpiIndicator = bitStream.read(1);
5692351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        mipUppLength--;
5702351b17aba5350004fc76707f3b3d2859ce773c8xinhe
5712351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        if(mnHaSpiIndicator == 1) {
5722351b17aba5350004fc76707f3b3d2859ce773c8xinhe                            if (!checkLengthLegal(mipUppLength, 32)) {
5732351b17aba5350004fc76707f3b3d2859ce773c8xinhe                                return;
5742351b17aba5350004fc76707f3b3d2859ce773c8xinhe                            }
5752351b17aba5350004fc76707f3b3d2859ce773c8xinhe                            bitStream.skip(32);
5762351b17aba5350004fc76707f3b3d2859ce773c8xinhe                            mipUppLength -= 32;
5772351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        }
5782351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    }
5792351b17aba5350004fc76707f3b3d2859ce773c8xinhe                }
5802351b17aba5350004fc76707f3b3d2859ce773c8xinhe            } catch(Exception e) {
5812351b17aba5350004fc76707f3b3d2859ce773c8xinhe              Log.e(LOG_TAG,"MIPUPP read Exception error!");
5822351b17aba5350004fc76707f3b3d2859ce773c8xinhe                return;
5832351b17aba5350004fc76707f3b3d2859ce773c8xinhe            }
5842351b17aba5350004fc76707f3b3d2859ce773c8xinhe        }
5852351b17aba5350004fc76707f3b3d2859ce773c8xinhe    }
5862351b17aba5350004fc76707f3b3d2859ce773c8xinhe
587c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
588c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void handleMessage(Message msg) {
589c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        AsyncResult ar;
590c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
591c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        byte data[];
592c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
593c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        boolean isRecordLoadResponse = false;
594c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
595bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        if (mDestroyed.get()) {
596c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            loge("Received message " + msg +
597c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    "[" + msg.what + "] while being destroyed. Ignoring.");
598c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return;
599c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
600c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
601c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        try { switch (msg.what) {
602e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            case EVENT_APP_READY:
603e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                onReady();
604e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                break;
605c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
606c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_GET_DEVICE_IDENTITY_DONE:
607c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                log("Event EVENT_GET_DEVICE_IDENTITY_DONE Received");
608c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
609c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
610c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            /* IO events */
611c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_GET_IMSI_DONE:
612c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                isRecordLoadResponse = true;
613c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
614c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult)msg.obj;
615c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (ar.exception != null) {
616c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    loge("Exception querying IMSI, Exception:" + ar.exception);
617c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    break;
618c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
619c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
620c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                mImsi = (String) ar.result;
621c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
622c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // IMSI (MCC+MNC+MSIN) is at least 6 digits, but not more
623c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // than 15 (and usually 15).
624c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (mImsi != null && (mImsi.length() < 6 || mImsi.length() > 15)) {
625c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    loge("invalid IMSI " + mImsi);
626c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    mImsi = null;
627c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
628c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
629f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby                // FIXME: CSIM IMSI may not contain the MNC.
630f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby                if (false) {
631f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby                    log("IMSI: " + mImsi.substring(0, 6) + "xxxxxxxxx");
632f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby
633f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby                    String operatorNumeric = getRUIMOperatorNumeric();
634f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby                    if (operatorNumeric != null) {
635f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby                        if (operatorNumeric.length() <= 6) {
636a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                            log("update mccmnc=" + operatorNumeric);
637f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby                            MccTable.updateMccMncConfiguration(mContext, operatorNumeric, false);
638f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby                        }
639c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
640a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                } else {
641a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    String operatorNumeric = getRUIMOperatorNumeric();
642a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    log("NO update mccmnc=" + operatorNumeric);
643c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
644f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby
645c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
646c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
647c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_GET_CDMA_SUBSCRIPTION_DONE:
648c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult)msg.obj;
649c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                String localTemp[] = (String[])ar.result;
650c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (ar.exception != null) {
651c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    break;
652c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
653c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
654c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                mMyMobileNumber = localTemp[0];
655c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                mMin2Min1 = localTemp[3];
656c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                mPrlVersion = localTemp[4];
657c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
658c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                log("MDN: " + mMyMobileNumber + " MIN: " + mMin2Min1);
659c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
660c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
661c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
662c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_GET_ICCID_DONE:
663c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                isRecordLoadResponse = true;
664c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
665c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult)msg.obj;
666c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                data = (byte[])ar.result;
667c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
668c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (ar.exception != null) {
669c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    break;
670c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
671c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
672b7881d6e7e4e79491376bedf151c3412dfdc4121Wink Saville                mIccId = IccUtils.bcdToString(data, 0, data.length);
673c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
674c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                log("iccid: " + SubscriptionInfo.givePrintableIccid(mIccId));
675c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
676c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
677c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
678c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_UPDATE_DONE:
679c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult)msg.obj;
680c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (ar.exception != null) {
68199c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Saville                    Rlog.i(LOG_TAG, "RuimRecords update failed", ar.exception);
682c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
683c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
684c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
685c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_GET_ALL_SMS_DONE:
686c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_MARK_SMS_READ_DONE:
687c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_SMS_ON_RUIM:
688c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_GET_SMS_DONE:
68999c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Saville                Rlog.w(LOG_TAG, "Event not supported: " + msg.what);
690c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
691c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
692c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // TODO: probably EF_CST should be read instead
693c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_GET_SST_DONE:
694c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                log("Event EVENT_GET_SST_DONE Received");
695c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
696c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
697c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_RUIM_REFRESH:
698c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                isRecordLoadResponse = false;
699c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult)msg.obj;
700c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (ar.exception == null) {
701c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    handleRuimRefresh((IccRefreshResponse)ar.result);
702c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
703c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
704c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
705e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            default:
706e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                super.handleMessage(msg);   // IccRecords handles generic record load responses
707e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
708c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }}catch (RuntimeException exc) {
709c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // I don't want these exceptions to be fatal
71099c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Saville            Rlog.w(LOG_TAG, "Exception parsing RUIM record", exc);
711c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } finally {
712c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // Count up record load responses even if they are fails
713c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (isRecordLoadResponse) {
714c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                onRecordLoaded();
715c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
716c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
717c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
718c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
7190cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath    /**
7200cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath     * Returns an array of languages we have assets for.
7210cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath     *
7220cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath     * NOTE: This array will have duplicates. If this method will be caused
7230cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath     * frequently or in a tight loop, it can be rewritten for efficiency.
7240cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath     */
7250cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath    private static String[] getAssetLanguages(Context ctx) {
7260cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath        final String[] locales = ctx.getAssets().getLocales();
7270cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath        final String[] localeLangs = new String[locales.length];
7280cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath        for (int i = 0; i < locales.length; ++i) {
7290cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath            final String localeStr = locales[i];
7300cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath            final int separator = localeStr.indexOf('-');
7310cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath            if (separator < 0) {
7320cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath                localeLangs[i] = localeStr;
7330cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath            } else {
7340cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath                localeLangs[i] = localeStr.substring(0, separator);
7350cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath            }
7360cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath        }
7370cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath
7380cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath        return localeLangs;
7390cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath    }
7400cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath
741c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
742c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected void onRecordLoaded() {
743c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // One record loaded successfully or failed, In either case
744c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // we need to update the recordsToLoad count
74522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mRecordsToLoad -= 1;
74622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (DBG) log("onRecordLoaded " + mRecordsToLoad + " requested: " + mRecordsRequested);
747c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
74822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mRecordsToLoad == 0 && mRecordsRequested == true) {
749c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            onAllRecordsLoaded();
75022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        } else if (mRecordsToLoad < 0) {
751bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka            loge("recordsToLoad <0, programmer error suspected");
75222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mRecordsToLoad = 0;
753c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
754c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
755c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
756c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
757c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected void onAllRecordsLoaded() {
758bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        if (DBG) log("record load complete");
759bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka
760c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Further records that can be inserted are Operator/OEM dependent
761c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
762f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby        // FIXME: CSIM IMSI may not contain the MNC.
763f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby        if (false) {
764f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby            String operator = getRUIMOperatorNumeric();
765f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby            if (!TextUtils.isEmpty(operator)) {
766f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby                log("onAllRecordsLoaded set 'gsm.sim.operator.numeric' to operator='" +
767f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby                        operator + "'");
768a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                log("update icc_operator_numeric=" + operator);
769e70617d81dcd42350a737b11c25532e1d43df4ffLegler Wu                mTelephonyManager.setSimOperatorNumericForPhone(
770e70617d81dcd42350a737b11c25532e1d43df4ffLegler Wu                        mParentApp.getPhoneId(), operator);
771f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby            } else {
772f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby                log("onAllRecordsLoaded empty 'gsm.sim.operator.numeric' skipping");
773f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby            }
774c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
775f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby            if (!TextUtils.isEmpty(mImsi)) {
776a1421a82e8d4f711ba13a86d40889868ead492d4Amit Mahajan                log("onAllRecordsLoaded set mcc imsi=" + (VDBG ? ("=" + mImsi) : ""));
777e70617d81dcd42350a737b11c25532e1d43df4ffLegler Wu                mTelephonyManager.setSimCountryIsoForPhone(
778e70617d81dcd42350a737b11c25532e1d43df4ffLegler Wu                        mParentApp.getPhoneId(),
779e70617d81dcd42350a737b11c25532e1d43df4ffLegler Wu                        MccTable.countryCodeForMcc(
780e70617d81dcd42350a737b11c25532e1d43df4ffLegler Wu                        Integer.parseInt(mImsi.substring(0,3))));
781f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby            } else {
782f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby                log("onAllRecordsLoaded empty imsi skipping setting mcc");
783f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby            }
784c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
785e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
786c9a55d1e545ab7bc92e14c2ca1123ac71b18f7feAmit Mahajan        Resources resource = Resources.getSystem();
787c9a55d1e545ab7bc92e14c2ca1123ac71b18f7feAmit Mahajan        if (resource.getBoolean(com.android.internal.R.bool.config_use_sim_language_file)) {
788c9a55d1e545ab7bc92e14c2ca1123ac71b18f7feAmit Mahajan            setSimLanguage(mEFli, mEFpl);
789c9a55d1e545ab7bc92e14c2ca1123ac71b18f7feAmit Mahajan        }
790c9a55d1e545ab7bc92e14c2ca1123ac71b18f7feAmit Mahajan
791b7881d6e7e4e79491376bedf151c3412dfdc4121Wink Saville        mRecordsLoadedRegistrants.notifyRegistrants(
792c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            new AsyncResult(null, null, null));
7935866914ae9798adebcb84cd710bca660b797bff0Amit Mahajan
794062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal        // TODO: The below is hacky since the SubscriptionController may not be ready at this time.
7955866914ae9798adebcb84cd710bca660b797bff0Amit Mahajan        if (!TextUtils.isEmpty(mMdn)) {
796062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal            int phoneId = mParentApp.getUiccCard().getPhoneId();
797062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal            int[] subIds = SubscriptionController.getInstance().getSubId(phoneId);
798062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal            if (subIds != null) {
799062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal                SubscriptionManager.from(mContext).setDisplayNumber(mMdn, subIds[0]);
800062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal            } else {
801062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal                log("Cannot call setDisplayNumber: invalid subId");
802062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal            }
8035866914ae9798adebcb84cd710bca660b797bff0Amit Mahajan        }
804c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
805c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
806c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
807c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void onReady() {
808c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        fetchRuimRecords();
809c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
810c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        mCi.getCDMASubscription(obtainMessage(EVENT_GET_CDMA_SUBSCRIPTION_DONE));
811c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
812c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
813c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
814c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void fetchRuimRecords() {
81522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mRecordsRequested = true;
816c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
81722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (DBG) log("fetchRuimRecords " + mRecordsToLoad);
818c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
819e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mCi.getIMSIForApp(mParentApp.getAid(), obtainMessage(EVENT_GET_IMSI_DONE));
82022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mRecordsToLoad++;
821c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
822c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        mFh.loadEFTransparent(EF_ICCID,
823c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                obtainMessage(EVENT_GET_ICCID_DONE));
82422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mRecordsToLoad++;
825c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
826c9a55d1e545ab7bc92e14c2ca1123ac71b18f7feAmit Mahajan        mFh.loadEFTransparent(EF_PL,
827c9a55d1e545ab7bc92e14c2ca1123ac71b18f7feAmit Mahajan                obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfPlLoaded()));
828c9a55d1e545ab7bc92e14c2ca1123ac71b18f7feAmit Mahajan        mRecordsToLoad++;
829e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
830c9a55d1e545ab7bc92e14c2ca1123ac71b18f7feAmit Mahajan        mFh.loadEFTransparent(EF_CSIM_LI,
831c9a55d1e545ab7bc92e14c2ca1123ac71b18f7feAmit Mahajan                obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimLiLoaded()));
832c9a55d1e545ab7bc92e14c2ca1123ac71b18f7feAmit Mahajan        mRecordsToLoad++;
833e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
834e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mFh.loadEFTransparent(EF_CSIM_SPN,
835e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimSpnLoaded()));
83622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mRecordsToLoad++;
837e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
838e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mFh.loadEFLinearFixed(EF_CSIM_MDN, 1,
839e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimMdnLoaded()));
84022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mRecordsToLoad++;
841e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
842e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mFh.loadEFTransparent(EF_CSIM_IMSIM,
843e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimImsimLoaded()));
84422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mRecordsToLoad++;
845e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
846e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mFh.loadEFLinearFixedAll(EF_CSIM_CDMAHOME,
847e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimCdmaHomeLoaded()));
84822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mRecordsToLoad++;
849e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
850e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // Entire PRL could be huge. We are only interested in
851e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // the first 4 bytes of the record.
852e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mFh.loadEFTransparent(EF_CSIM_EPRL, 4,
853e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimEprlLoaded()));
85422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mRecordsToLoad++;
855e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
8562351b17aba5350004fc76707f3b3d2859ce773c8xinhe        mFh.loadEFTransparent(EF_CSIM_MIPUPP,
8572351b17aba5350004fc76707f3b3d2859ce773c8xinhe                obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimMipUppLoaded()));
8582351b17aba5350004fc76707f3b3d2859ce773c8xinhe        mRecordsToLoad++;
8592351b17aba5350004fc76707f3b3d2859ce773c8xinhe
86022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (DBG) log("fetchRuimRecords " + mRecordsToLoad + " requested: " + mRecordsRequested);
861c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Further records that can be inserted are Operator/OEM dependent
862c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
863c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
864c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
865c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * {@inheritDoc}
866c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
867c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * No Display rule for RUIMs yet.
868c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
869c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
870c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public int getDisplayRule(String plmn) {
871c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // TODO together with spn
872c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return 0;
873c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
874c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
875c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
876e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public boolean isProvisioned() {
877e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // If UICC card has CSIM app, look for MDN and MIN field
878e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // to determine if the SIM is provisioned.  Otherwise,
879e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // consider the SIM is provisioned. (for case of ordinal
880e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // USIM only UICC.)
881e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // If PROPERTY_TEST_CSIM is defined, bypess provision check
882e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // and consider the SIM is provisioned.
883e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (SystemProperties.getBoolean(PROPERTY_TEST_CSIM, false)) {
884e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return true;
885e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
886e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
887e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (mParentApp == null) {
888e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return false;
889e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
890e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
891e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (mParentApp.getType() == AppType.APPTYPE_CSIM &&
892e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            ((mMdn == null) || (mMin == null))) {
893e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return false;
894e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
895e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        return true;
896e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
897e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
898e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    @Override
899c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void setVoiceMessageWaiting(int line, int countWaiting) {
90026a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa        // Will be used in future to store voice mail count in UIM
90126a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa        // C.S0023-D_v1.0 does not have a file id in UIM for MWI
90226a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa        log("RuimRecords:setVoiceMessageWaiting - NOP for CDMA");
90326a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa    }
904c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
90526a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa    @Override
90626a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa    public int getVoiceMessageCount() {
90726a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa        // Will be used in future to retrieve voice mail count for UIM
90826a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa        // C.S0023-D_v1.0 does not have a file id in UIM for MWI
90926a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa        log("RuimRecords:getVoiceMessageCount - NOP for CDMA");
91026a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa        return 0;
911c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
912c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
913c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void handleRuimRefresh(IccRefreshResponse refreshResponse) {
914c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (refreshResponse == null) {
915c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (DBG) log("handleRuimRefresh received without input");
916c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return;
917c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
918c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
919c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (refreshResponse.aid != null &&
920e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                !refreshResponse.aid.equals(mParentApp.getAid())) {
921c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // This is for different app. Ignore.
922c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return;
923c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
924c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
925c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        switch (refreshResponse.refreshResult) {
926c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case IccRefreshResponse.REFRESH_RESULT_FILE_UPDATE:
927c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (DBG) log("handleRuimRefresh with SIM_REFRESH_FILE_UPDATED");
92822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mAdnCache.reset();
929c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                fetchRuimRecords();
930c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
931c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case IccRefreshResponse.REFRESH_RESULT_INIT:
932c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (DBG) log("handleRuimRefresh with SIM_REFRESH_INIT");
933c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // need to reload all files (that we care about)
93464bfd98578babdd437f1a83d2d5e1fc92c76e729Alex Yakavenka                onIccRefreshInit();
935c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
936c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case IccRefreshResponse.REFRESH_RESULT_RESET:
93762648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal                // Refresh reset is handled by the UiccCard object.
938c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (DBG) log("handleRuimRefresh with SIM_REFRESH_RESET");
939c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
940c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            default:
941c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // unknown refresh operation
942c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (DBG) log("handleRuimRefresh with unknown operation");
943c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
944c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
945c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
946c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
947e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public String getMdn() {
948e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        return mMdn;
949e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
950e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
951e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public String getMin() {
952e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        return mMin;
953e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
954e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
955e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public String getSid() {
956e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        return mHomeSystemId;
957e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
958e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
959e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public String getNid() {
960e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        return mHomeNetworkId;
961e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
962e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
963e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public boolean getCsimSpnDisplayCondition() {
964e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        return mCsimSpnDisplayCondition;
965e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
966c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
967c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected void log(String s) {
96899c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Saville        Rlog.d(LOG_TAG, "[RuimRecords] " + s);
969c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
970c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
971c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
972c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected void loge(String s) {
97399c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Saville        Rlog.e(LOG_TAG, "[RuimRecords] " + s);
974c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
97505ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka
97605ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka    @Override
97705ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
97805ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println("RuimRecords: " + this);
97905ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" extends:");
98005ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        super.dump(fd, pw, args);
98122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        pw.println(" mOtaCommited=" + mOtaCommited);
98205ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mMyMobileNumber=" + mMyMobileNumber);
98305ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mMin2Min1=" + mMin2Min1);
98405ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mPrlVersion=" + mPrlVersion);
98505ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mEFpl[]=" + Arrays.toString(mEFpl));
98605ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mEFli[]=" + Arrays.toString(mEFli));
98705ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mCsimSpnDisplayCondition=" + mCsimSpnDisplayCondition);
98805ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mMdn=" + mMdn);
98905ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mMin=" + mMin);
99005ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mHomeSystemId=" + mHomeSystemId);
99105ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mHomeNetworkId=" + mHomeNetworkId);
99205ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.flush();
99305ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka    }
994c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville}
995