RuimRecords.java revision 2351b17aba5350004fc76707f3b3d2859ce773c8
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.Message;
34c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.os.SystemProperties;
35a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.TelephonyManager;
3699c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Savilleimport android.telephony.Rlog;
37e9070e6d48d1389987650fa2c3e1f90aab860684Wink Savilleimport android.text.TextUtils;
382351b17aba5350004fc76707f3b3d2859ce773c8xinheimport android.util.Log;
39c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
40c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.CommandsInterface;
41e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenkaimport com.android.internal.telephony.GsmAlphabet;
42c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.MccTable;
43c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
44e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenkaimport com.android.internal.telephony.cdma.sms.UserData;
45d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
462351b17aba5350004fc76707f3b3d2859ce773c8xinheimport com.android.internal.util.BitwiseInputStream;
47c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
48c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/**
49c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * {@hide}
50c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */
51c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savillepublic final class RuimRecords extends IccRecords {
52cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    static final String LOG_TAG = "RuimRecords";
53c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
5422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville    private boolean  mOtaCommited=false;
55c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
56c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // ***** Instance Variables
57c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
58c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private String mMyMobileNumber;
59c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private String mMin2Min1;
60c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
61c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private String mPrlVersion;
62e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    // From CSIM application
63e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private byte[] mEFpl = null;
64e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private byte[] mEFli = null;
65e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    boolean mCsimSpnDisplayCondition = false;
66e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private String mMdn;
67e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private String mMin;
68e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private String mHomeSystemId;
69e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private String mHomeNetworkId;
702351b17aba5350004fc76707f3b3d2859ce773c8xinhe    private String mNai;
71c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
72f92cb4bd5519427a0db673709d94683a8baf203aWink Saville    @Override
73f92cb4bd5519427a0db673709d94683a8baf203aWink Saville    public String toString() {
74f92cb4bd5519427a0db673709d94683a8baf203aWink Saville        return "RuimRecords: " + super.toString()
7522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                + " m_ota_commited" + mOtaCommited
76f92cb4bd5519427a0db673709d94683a8baf203aWink Saville                + " mMyMobileNumber=" + "xxxx"
77f92cb4bd5519427a0db673709d94683a8baf203aWink Saville                + " mMin2Min1=" + mMin2Min1
78f92cb4bd5519427a0db673709d94683a8baf203aWink Saville                + " mPrlVersion=" + mPrlVersion
79f92cb4bd5519427a0db673709d94683a8baf203aWink Saville                + " mEFpl=" + mEFpl
80f92cb4bd5519427a0db673709d94683a8baf203aWink Saville                + " mEFli=" + mEFli
81f92cb4bd5519427a0db673709d94683a8baf203aWink Saville                + " mCsimSpnDisplayCondition=" + mCsimSpnDisplayCondition
82f92cb4bd5519427a0db673709d94683a8baf203aWink Saville                + " mMdn=" + mMdn
83f92cb4bd5519427a0db673709d94683a8baf203aWink Saville                + " mMin=" + mMin
84f92cb4bd5519427a0db673709d94683a8baf203aWink Saville                + " mHomeSystemId=" + mHomeSystemId
85f92cb4bd5519427a0db673709d94683a8baf203aWink Saville                + " mHomeNetworkId=" + mHomeNetworkId;
86f92cb4bd5519427a0db673709d94683a8baf203aWink Saville    }
87f92cb4bd5519427a0db673709d94683a8baf203aWink Saville
88c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // ***** Event Constants
89c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_GET_IMSI_DONE = 3;
90c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_GET_DEVICE_IDENTITY_DONE = 4;
91c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_GET_ICCID_DONE = 5;
92c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_GET_CDMA_SUBSCRIPTION_DONE = 10;
93c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_UPDATE_DONE = 14;
94c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_GET_SST_DONE = 17;
95c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_GET_ALL_SMS_DONE = 18;
96c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_MARK_SMS_READ_DONE = 19;
97c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
98c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_SMS_ON_RUIM = 21;
99c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_GET_SMS_DONE = 22;
100c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
101c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final int EVENT_RUIM_REFRESH = 31;
102c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
103e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public RuimRecords(UiccCardApplication app, Context c, CommandsInterface ci) {
104e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        super(app, c, ci);
105c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
10622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mAdnCache = new AdnRecordCache(mFh);
107c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
10822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mRecordsRequested = false;  // No load request is made till SIM ready
109c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
110c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // recordsToLoad is set to 0 because no requests are made yet
11122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mRecordsToLoad = 0;
112c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
113c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // NOTE the EVENT_SMS_ON_RUIM is not registered
114c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        mCi.registerForIccRefresh(this, EVENT_RUIM_REFRESH, null);
115c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
116c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Start off by setting empty state
117e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        resetRecords();
118c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
119e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mParentApp.registerForReady(this, EVENT_APP_READY, null);
120f92cb4bd5519427a0db673709d94683a8baf203aWink Saville        if (DBG) log("RuimRecords X ctor this=" + this);
121c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
122c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
123c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
124c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void dispose() {
125c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (DBG) log("Disposing RuimRecords " + this);
126c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        //Unregister for all events
127c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        mCi.unregisterForIccRefresh(this);
128e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mParentApp.unregisterForReady(this);
129e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        resetRecords();
130c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        super.dispose();
131c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
132c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
133c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
134c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected void finalize() {
135c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if(DBG) log("RuimRecords finalized");
136c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
137c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
138e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    protected void resetRecords() {
13922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mCountVoiceMessages = 0;
14022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mMncLength = UNINITIALIZED;
141a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        log("setting0 mMncLength" + mMncLength);
142b7881d6e7e4e79491376bedf151c3412dfdc4121Wink Saville        mIccId = null;
143c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
14422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mAdnCache.reset();
145c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
146c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Don't clean up PROPERTY_ICC_OPERATOR_ISO_COUNTRY and
147c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // PROPERTY_ICC_OPERATOR_NUMERIC here. Since not all CDMA
148c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // devices have RUIM, these properties should keep the original
149c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // values, e.g. build time settings, when there is no RUIM but
150c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // set new values when RUIM is available and loaded.
151c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
152c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // recordsRequested is set to false indicating that the SIM
153c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // read requests made so far are not valid. This is set to
154c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // true only when fresh set of read requests are made.
15522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mRecordsRequested = false;
156c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
157c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
158e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    @Override
159e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public String getIMSI() {
160e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        return mImsi;
161e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
162e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
163c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public String getMdnNumber() {
164c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return mMyMobileNumber;
165c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
166c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
167c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public String getCdmaMin() {
168c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         return mMin2Min1;
169c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
170c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
171c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Returns null if RUIM is not yet ready */
172c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public String getPrlVersion() {
173c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return mPrlVersion;
174c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
175c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
176c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
1772351b17aba5350004fc76707f3b3d2859ce773c8xinhe    /** Returns null if RUIM is not yet ready */
1782351b17aba5350004fc76707f3b3d2859ce773c8xinhe    public String getNAI() {
1792351b17aba5350004fc76707f3b3d2859ce773c8xinhe        return mNai;
1802351b17aba5350004fc76707f3b3d2859ce773c8xinhe    }
1812351b17aba5350004fc76707f3b3d2859ce773c8xinhe
1822351b17aba5350004fc76707f3b3d2859ce773c8xinhe    @Override
183c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void setVoiceMailNumber(String alphaTag, String voiceNumber, Message onComplete){
184c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // In CDMA this is Operator/OEM dependent
185c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        AsyncResult.forMessage((onComplete)).exception =
186c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                new IccException("setVoiceMailNumber not implemented");
187c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        onComplete.sendToTarget();
188c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        loge("method setVoiceMailNumber is not implemented");
189c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
190c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
191c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
192c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Called by CCAT Service when REFRESH is received.
193c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param fileChanged indicates whether any files changed
194c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param fileList if non-null, a list of EF files that changed
195c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
196c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
197c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void onRefresh(boolean fileChanged, int[] fileList) {
198c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (fileChanged) {
199c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // A future optimization would be to inspect fileList and
200c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // only reload those files that we care about.  For now,
201c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // just re-fetch all RUIM records that we cache.
202c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            fetchRuimRecords();
203c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
204c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
205c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
206e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private int adjstMinDigits (int digits) {
207e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // Per C.S0005 section 2.3.1.
208e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        digits += 111;
209e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        digits = (digits % 10 == 0)?(digits - 10):digits;
210e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        digits = ((digits / 10) % 10 == 0)?(digits - 100):digits;
211e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        digits = ((digits / 100) % 10 == 0)?(digits - 1000):digits;
212e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        return digits;
213e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
214e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
215c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
216c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Returns the 5 or 6 digit MCC/MNC of the operator that
217c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  provided the RUIM card. Returns null of RUIM is not yet ready
218c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
219c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public String getRUIMOperatorNumeric() {
220c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (mImsi == null) {
221c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return null;
222c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
223c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
22422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mMncLength != UNINITIALIZED && mMncLength != UNKNOWN) {
225c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // Length = length of MCC + length of MNC
226c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // length of mcc = 3 (3GPP2 C.S0005 - Section 2.3)
22722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            return mImsi.substring(0, 3 + mMncLength);
228c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
229c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
230c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Guess the MNC length based on the MCC if we don't
231c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // have a valid value in ef[ad]
232c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
233c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        int mcc = Integer.parseInt(mImsi.substring(0,3));
234c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return mImsi.substring(0, 3 + MccTable.smallestDigitsMccForMnc(mcc));
235c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
236c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
237e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    // Refer to ETSI TS 102.221
238e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private class EfPlLoaded implements IccRecordLoaded {
239cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        @Override
240e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public String getEfName() {
241e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return "EF_PL";
242e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
243e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
244cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        @Override
245e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public void onRecordLoaded(AsyncResult ar) {
246e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mEFpl = (byte[]) ar.result;
247e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (DBG) log("EF_PL=" + IccUtils.bytesToHexString(mEFpl));
248e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
249e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
250e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
251e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    // Refer to C.S0065 5.2.26
252e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private class EfCsimLiLoaded implements IccRecordLoaded {
253cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        @Override
254e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public String getEfName() {
255e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return "EF_CSIM_LI";
256e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
257e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
258cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        @Override
259e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public void onRecordLoaded(AsyncResult ar) {
260e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mEFli = (byte[]) ar.result;
261e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            // convert csim efli data to iso 639 format
262e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            for (int i = 0; i < mEFli.length; i+=2) {
263e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                switch(mEFli[i+1]) {
264e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case 0x01: mEFli[i] = 'e'; mEFli[i+1] = 'n';break;
265e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case 0x02: mEFli[i] = 'f'; mEFli[i+1] = 'r';break;
266e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case 0x03: mEFli[i] = 'e'; mEFli[i+1] = 's';break;
267e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case 0x04: mEFli[i] = 'j'; mEFli[i+1] = 'a';break;
268e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case 0x05: mEFli[i] = 'k'; mEFli[i+1] = 'o';break;
269e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case 0x06: mEFli[i] = 'z'; mEFli[i+1] = 'h';break;
270e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case 0x07: mEFli[i] = 'h'; mEFli[i+1] = 'e';break;
271e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                default: mEFli[i] = ' '; mEFli[i+1] = ' ';
272e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                }
273e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
274e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
275e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (DBG) log("EF_LI=" + IccUtils.bytesToHexString(mEFli));
276e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
277e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
278e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
279e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    // Refer to C.S0065 5.2.32
280e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private class EfCsimSpnLoaded implements IccRecordLoaded {
281cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        @Override
282e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public String getEfName() {
283e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return "EF_CSIM_SPN";
284e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
285e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
286cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        @Override
287e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public void onRecordLoaded(AsyncResult ar) {
288e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            byte[] data = (byte[]) ar.result;
289e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (DBG) log("CSIM_SPN=" +
290e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                         IccUtils.bytesToHexString(data));
291e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
292e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            // C.S0065 for EF_SPN decoding
293e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mCsimSpnDisplayCondition = ((0x01 & data[0]) != 0);
294e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
295e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            int encoding = data[1];
296e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            int language = data[2];
297e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            byte[] spnData = new byte[32];
298e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            int len = ((data.length - 3) < 32) ? (data.length - 3) : 32;
299e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            System.arraycopy(data, 3, spnData, 0, len);
300e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
301e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            int numBytes;
302e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            for (numBytes = 0; numBytes < spnData.length; numBytes++) {
303e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if ((spnData[numBytes] & 0xFF) == 0xFF) break;
304e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
305e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
306e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (numBytes == 0) {
307b93bb3538c55f173f94a4ee7510d9d1521d8f731Shishir Agrawal                setServiceProviderName("");
308e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                return;
309e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
310e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            try {
311e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                switch (encoding) {
312e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case UserData.ENCODING_OCTET:
313e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case UserData.ENCODING_LATIN:
314b93bb3538c55f173f94a4ee7510d9d1521d8f731Shishir Agrawal                    setServiceProviderName(new String(spnData, 0, numBytes, "ISO-8859-1"));
315e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    break;
316e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case UserData.ENCODING_IA5:
317e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case UserData.ENCODING_GSM_7BIT_ALPHABET:
318b93bb3538c55f173f94a4ee7510d9d1521d8f731Shishir Agrawal                    setServiceProviderName(
319b93bb3538c55f173f94a4ee7510d9d1521d8f731Shishir Agrawal                            GsmAlphabet.gsm7BitPackedToString(spnData, 0, (numBytes*8)/7));
320e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    break;
32160e3a52dad667a094af0c269176ee30da739ee84Sandeep Gutta                case UserData.ENCODING_7BIT_ASCII:
322b5d27d8e567ef835e961548b144cdad95d2361deJing Zhao                    String spn = new String(spnData, 0, numBytes, "US-ASCII");
323b5d27d8e567ef835e961548b144cdad95d2361deJing Zhao                    // To address issues with incorrect encoding scheme
324b5d27d8e567ef835e961548b144cdad95d2361deJing Zhao                    // programmed in some commercial CSIM cards, the decoded
325b5d27d8e567ef835e961548b144cdad95d2361deJing Zhao                    // SPN is checked to have characters in printable ASCII
326b5d27d8e567ef835e961548b144cdad95d2361deJing Zhao                    // range. If not, they are decoded with
327b5d27d8e567ef835e961548b144cdad95d2361deJing Zhao                    // ENCODING_GSM_7BIT_ALPHABET scheme.
328b5d27d8e567ef835e961548b144cdad95d2361deJing Zhao                    if (TextUtils.isPrintableAsciiOnly(spn)) {
329b5d27d8e567ef835e961548b144cdad95d2361deJing Zhao                        setServiceProviderName(spn);
330b5d27d8e567ef835e961548b144cdad95d2361deJing Zhao                    } else {
331b5d27d8e567ef835e961548b144cdad95d2361deJing Zhao                        if (DBG) log("Some corruption in SPN decoding = " + spn);
332b5d27d8e567ef835e961548b144cdad95d2361deJing Zhao                        if (DBG) log("Using ENCODING_GSM_7BIT_ALPHABET scheme...");
333b5d27d8e567ef835e961548b144cdad95d2361deJing Zhao                        setServiceProviderName(
334b5d27d8e567ef835e961548b144cdad95d2361deJing Zhao                                GsmAlphabet.gsm7BitPackedToString(spnData, 0, (numBytes * 8) / 7));
335b5d27d8e567ef835e961548b144cdad95d2361deJing Zhao                    }
33660e3a52dad667a094af0c269176ee30da739ee84Sandeep Gutta                break;
337e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                case UserData.ENCODING_UNICODE_16:
338b93bb3538c55f173f94a4ee7510d9d1521d8f731Shishir Agrawal                    setServiceProviderName(new String(spnData, 0, numBytes, "utf-16"));
339e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    break;
340e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                default:
341e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    log("SPN encoding not supported");
342e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                }
343e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            } catch(Exception e) {
344e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                log("spn decode error: " + e);
345e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
346b93bb3538c55f173f94a4ee7510d9d1521d8f731Shishir Agrawal            if (DBG) log("spn=" + getServiceProviderName());
347e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (DBG) log("spnCondition=" + mCsimSpnDisplayCondition);
348b93bb3538c55f173f94a4ee7510d9d1521d8f731Shishir Agrawal            SystemProperties.set(PROPERTY_ICC_OPERATOR_ALPHA, getServiceProviderName());
349e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
350e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
351e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
352e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private class EfCsimMdnLoaded implements IccRecordLoaded {
353cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        @Override
354e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public String getEfName() {
355e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return "EF_CSIM_MDN";
356e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
357e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
358cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        @Override
359e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public void onRecordLoaded(AsyncResult ar) {
360e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            byte[] data = (byte[]) ar.result;
361e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (DBG) log("CSIM_MDN=" + IccUtils.bytesToHexString(data));
362e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            // Refer to C.S0065 5.2.35
363e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            int mdnDigitsNum = 0x0F & data[0];
364e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mMdn = IccUtils.cdmaBcdToString(data, 1, mdnDigitsNum);
365e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (DBG) log("CSIM MDN=" + mMdn);
366e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
367e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
368e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
369e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private class EfCsimImsimLoaded implements IccRecordLoaded {
370cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        @Override
371e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public String getEfName() {
372e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return "EF_CSIM_IMSIM";
373e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
374e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
375cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        @Override
376e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public void onRecordLoaded(AsyncResult ar) {
377e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            byte[] data = (byte[]) ar.result;
378e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (DBG) log("CSIM_IMSIM=" + IccUtils.bytesToHexString(data));
379e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            // C.S0065 section 5.2.2 for IMSI_M encoding
380e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            // C.S0005 section 2.3.1 for MIN encoding in IMSI_M.
381e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            boolean provisioned = ((data[7] & 0x80) == 0x80);
382e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
383e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (provisioned) {
384e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                int first3digits = ((0x03 & data[2]) << 8) + (0xFF & data[1]);
385e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                int second3digits = (((0xFF & data[5]) << 8) | (0xFF & data[4])) >> 6;
386e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                int digit7 = 0x0F & (data[4] >> 2);
387e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if (digit7 > 0x09) digit7 = 0;
388e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                int last3digits = ((0x03 & data[4]) << 8) | (0xFF & data[3]);
389e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                first3digits = adjstMinDigits(first3digits);
390e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                second3digits = adjstMinDigits(second3digits);
391e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                last3digits = adjstMinDigits(last3digits);
392e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
393e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                StringBuilder builder = new StringBuilder();
394e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                builder.append(String.format(Locale.US, "%03d", first3digits));
395e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                builder.append(String.format(Locale.US, "%03d", second3digits));
396e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                builder.append(String.format(Locale.US, "%d", digit7));
397e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                builder.append(String.format(Locale.US, "%03d", last3digits));
398e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                mMin = builder.toString();
399e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if (DBG) log("min present=" + mMin);
400e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            } else {
401e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if (DBG) log("min not present");
402e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
403e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
404e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
405e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
406e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private class EfCsimCdmaHomeLoaded implements IccRecordLoaded {
407cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        @Override
408e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public String getEfName() {
409e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return "EF_CSIM_CDMAHOME";
410e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
411e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
412cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        @Override
413e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public void onRecordLoaded(AsyncResult ar) {
414e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            // Per C.S0065 section 5.2.8
415e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            ArrayList<byte[]> dataList = (ArrayList<byte[]>) ar.result;
416e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (DBG) log("CSIM_CDMAHOME data size=" + dataList.size());
417e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (dataList.isEmpty()) {
418e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                return;
419e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
420e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            StringBuilder sidBuf = new StringBuilder();
421e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            StringBuilder nidBuf = new StringBuilder();
422e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
423e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            for (byte[] data : dataList) {
424e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if (data.length == 5) {
425e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    int sid = ((data[1] & 0xFF) << 8) | (data[0] & 0xFF);
426e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    int nid = ((data[3] & 0xFF) << 8) | (data[2] & 0xFF);
427e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    sidBuf.append(sid).append(',');
428e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    nidBuf.append(nid).append(',');
429e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                }
430e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
431e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            // remove trailing ","
432e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            sidBuf.setLength(sidBuf.length()-1);
433e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            nidBuf.setLength(nidBuf.length()-1);
434e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
435e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mHomeSystemId = sidBuf.toString();
436e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mHomeNetworkId = nidBuf.toString();
437e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
438e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
439e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
440e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private class EfCsimEprlLoaded implements IccRecordLoaded {
441cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        @Override
442e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public String getEfName() {
443e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return "EF_CSIM_EPRL";
444e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
445cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        @Override
446e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        public void onRecordLoaded(AsyncResult ar) {
447e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            onGetCSimEprlDone(ar);
448e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
449e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
450e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
451e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private void onGetCSimEprlDone(AsyncResult ar) {
452e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // C.S0065 section 5.2.57 for EFeprl encoding
453e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // C.S0016 section 3.5.5 for PRL format.
454e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        byte[] data = (byte[]) ar.result;
455e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (DBG) log("CSIM_EPRL=" + IccUtils.bytesToHexString(data));
456e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
457e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // Only need the first 4 bytes of record
458e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (data.length > 3) {
459e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            int prlId = ((data[2] & 0xFF) << 8) | (data[3] & 0xFF);
460e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            mPrlVersion = Integer.toString(prlId);
461e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
462e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (DBG) log("CSIM PRL version=" + mPrlVersion);
463e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
464e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
4652351b17aba5350004fc76707f3b3d2859ce773c8xinhe    private class EfCsimMipUppLoaded implements IccRecordLoaded {
4662351b17aba5350004fc76707f3b3d2859ce773c8xinhe        @Override
4672351b17aba5350004fc76707f3b3d2859ce773c8xinhe        public String getEfName() {
4682351b17aba5350004fc76707f3b3d2859ce773c8xinhe            return "EF_CSIM_MIPUPP";
4692351b17aba5350004fc76707f3b3d2859ce773c8xinhe        }
4702351b17aba5350004fc76707f3b3d2859ce773c8xinhe
4712351b17aba5350004fc76707f3b3d2859ce773c8xinhe        boolean checkLengthLegal(int length, int expectLength) {
4722351b17aba5350004fc76707f3b3d2859ce773c8xinhe            if(length < expectLength) {
4732351b17aba5350004fc76707f3b3d2859ce773c8xinhe                Log.e(LOG_TAG, "CSIM MIPUPP format error, length = " + length  +
4742351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        "expected length at least =" + expectLength);
4752351b17aba5350004fc76707f3b3d2859ce773c8xinhe                return false;
4762351b17aba5350004fc76707f3b3d2859ce773c8xinhe            } else {
4772351b17aba5350004fc76707f3b3d2859ce773c8xinhe                return true;
4782351b17aba5350004fc76707f3b3d2859ce773c8xinhe            }
4792351b17aba5350004fc76707f3b3d2859ce773c8xinhe        }
4802351b17aba5350004fc76707f3b3d2859ce773c8xinhe
4812351b17aba5350004fc76707f3b3d2859ce773c8xinhe        @Override
4822351b17aba5350004fc76707f3b3d2859ce773c8xinhe        public void onRecordLoaded(AsyncResult ar) {
4832351b17aba5350004fc76707f3b3d2859ce773c8xinhe            // 3GPP2 C.S0065 section 5.2.24
4842351b17aba5350004fc76707f3b3d2859ce773c8xinhe            byte[] data = (byte[]) ar.result;
4852351b17aba5350004fc76707f3b3d2859ce773c8xinhe
4862351b17aba5350004fc76707f3b3d2859ce773c8xinhe            if(data.length < 1) {
4872351b17aba5350004fc76707f3b3d2859ce773c8xinhe                Log.e(LOG_TAG,"MIPUPP read error");
4882351b17aba5350004fc76707f3b3d2859ce773c8xinhe                return;
4892351b17aba5350004fc76707f3b3d2859ce773c8xinhe            }
4902351b17aba5350004fc76707f3b3d2859ce773c8xinhe
4912351b17aba5350004fc76707f3b3d2859ce773c8xinhe            BitwiseInputStream bitStream = new BitwiseInputStream(data);
4922351b17aba5350004fc76707f3b3d2859ce773c8xinhe            try {
4932351b17aba5350004fc76707f3b3d2859ce773c8xinhe                int  mipUppLength = bitStream.read(8);
4942351b17aba5350004fc76707f3b3d2859ce773c8xinhe                //transfer length from byte to bit
4952351b17aba5350004fc76707f3b3d2859ce773c8xinhe                mipUppLength = (mipUppLength << 3);
4962351b17aba5350004fc76707f3b3d2859ce773c8xinhe
4972351b17aba5350004fc76707f3b3d2859ce773c8xinhe                if (!checkLengthLegal(mipUppLength, 1)) {
4982351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    return;
4992351b17aba5350004fc76707f3b3d2859ce773c8xinhe                }
5002351b17aba5350004fc76707f3b3d2859ce773c8xinhe                //parse the MIPUPP body 3GPP2 C.S0016-C 3.5.8.6
5012351b17aba5350004fc76707f3b3d2859ce773c8xinhe                int retryInfoInclude = bitStream.read(1);
5022351b17aba5350004fc76707f3b3d2859ce773c8xinhe                mipUppLength--;
5032351b17aba5350004fc76707f3b3d2859ce773c8xinhe
5042351b17aba5350004fc76707f3b3d2859ce773c8xinhe                if(retryInfoInclude == 1) {
5052351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    if (!checkLengthLegal(mipUppLength, 11)) {
5062351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        return;
5072351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    }
5082351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    bitStream.skip(11); //not used now
5092351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    //transfer length from byte to bit
5102351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    mipUppLength -= 11;
5112351b17aba5350004fc76707f3b3d2859ce773c8xinhe                }
5122351b17aba5350004fc76707f3b3d2859ce773c8xinhe
5132351b17aba5350004fc76707f3b3d2859ce773c8xinhe                if (!checkLengthLegal(mipUppLength, 4)) {
5142351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    return;
5152351b17aba5350004fc76707f3b3d2859ce773c8xinhe                }
5162351b17aba5350004fc76707f3b3d2859ce773c8xinhe                int numNai = bitStream.read(4);
5172351b17aba5350004fc76707f3b3d2859ce773c8xinhe                mipUppLength -= 4;
5182351b17aba5350004fc76707f3b3d2859ce773c8xinhe
5192351b17aba5350004fc76707f3b3d2859ce773c8xinhe                //start parse NAI body
5202351b17aba5350004fc76707f3b3d2859ce773c8xinhe                for(int index = 0; index < numNai; index++) {
5212351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    if (!checkLengthLegal(mipUppLength, 4)) {
5222351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        return;
5232351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    }
5242351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    int naiEntryIndex = bitStream.read(4);
5252351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    mipUppLength -= 4;
5262351b17aba5350004fc76707f3b3d2859ce773c8xinhe
5272351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    if (!checkLengthLegal(mipUppLength, 8)) {
5282351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        return;
5292351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    }
5302351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    int naiLength = bitStream.read(8);
5312351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    mipUppLength -= 8;
5322351b17aba5350004fc76707f3b3d2859ce773c8xinhe
5332351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    if(naiEntryIndex == 0) {
5342351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        //we find the one!
5352351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        if (!checkLengthLegal(mipUppLength, naiLength << 3)) {
5362351b17aba5350004fc76707f3b3d2859ce773c8xinhe                            return;
5372351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        }
5382351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        char naiCharArray[] = new char[naiLength];
5392351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        for(int index1 = 0; index1 < naiLength; index1++) {
5402351b17aba5350004fc76707f3b3d2859ce773c8xinhe                            naiCharArray[index1] = (char)(bitStream.read(8) & 0xFF);
5412351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        }
5422351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        mNai =  new String(naiCharArray);
5432351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        return; //need not parsing further
5442351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    } else {
5452351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        //ignore this NAI body
5462351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        if (!checkLengthLegal(mipUppLength, (naiLength << 3) + 102)) {
5472351b17aba5350004fc76707f3b3d2859ce773c8xinhe                            return;
5482351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        }
5492351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        bitStream.skip((naiLength << 3) + 101);//not used
5502351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        int mnAaaSpiIndicator = bitStream.read(1);
5512351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        mipUppLength -= ((naiLength << 3) + 102);
5522351b17aba5350004fc76707f3b3d2859ce773c8xinhe
5532351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        if(mnAaaSpiIndicator == 1) {
5542351b17aba5350004fc76707f3b3d2859ce773c8xinhe                            if (!checkLengthLegal(mipUppLength, 32)) {
5552351b17aba5350004fc76707f3b3d2859ce773c8xinhe                                return;
5562351b17aba5350004fc76707f3b3d2859ce773c8xinhe                            }
5572351b17aba5350004fc76707f3b3d2859ce773c8xinhe                            bitStream.skip(32); //not used
5582351b17aba5350004fc76707f3b3d2859ce773c8xinhe                            mipUppLength -= 32;
5592351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        }
5602351b17aba5350004fc76707f3b3d2859ce773c8xinhe
5612351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        //MN-HA_AUTH_ALGORITHM
5622351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        if (!checkLengthLegal(mipUppLength, 5)) {
5632351b17aba5350004fc76707f3b3d2859ce773c8xinhe                            return;
5642351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        }
5652351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        bitStream.skip(4);
5662351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        mipUppLength -= 4;
5672351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        int mnHaSpiIndicator = bitStream.read(1);
5682351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        mipUppLength--;
5692351b17aba5350004fc76707f3b3d2859ce773c8xinhe
5702351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        if(mnHaSpiIndicator == 1) {
5712351b17aba5350004fc76707f3b3d2859ce773c8xinhe                            if (!checkLengthLegal(mipUppLength, 32)) {
5722351b17aba5350004fc76707f3b3d2859ce773c8xinhe                                return;
5732351b17aba5350004fc76707f3b3d2859ce773c8xinhe                            }
5742351b17aba5350004fc76707f3b3d2859ce773c8xinhe                            bitStream.skip(32);
5752351b17aba5350004fc76707f3b3d2859ce773c8xinhe                            mipUppLength -= 32;
5762351b17aba5350004fc76707f3b3d2859ce773c8xinhe                        }
5772351b17aba5350004fc76707f3b3d2859ce773c8xinhe                    }
5782351b17aba5350004fc76707f3b3d2859ce773c8xinhe                }
5792351b17aba5350004fc76707f3b3d2859ce773c8xinhe            } catch(Exception e) {
5802351b17aba5350004fc76707f3b3d2859ce773c8xinhe              Log.e(LOG_TAG,"MIPUPP read Exception error!");
5812351b17aba5350004fc76707f3b3d2859ce773c8xinhe                return;
5822351b17aba5350004fc76707f3b3d2859ce773c8xinhe            }
5832351b17aba5350004fc76707f3b3d2859ce773c8xinhe        }
5842351b17aba5350004fc76707f3b3d2859ce773c8xinhe    }
5852351b17aba5350004fc76707f3b3d2859ce773c8xinhe
586c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
587c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void handleMessage(Message msg) {
588c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        AsyncResult ar;
589c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
590c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        byte data[];
591c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
592c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        boolean isRecordLoadResponse = false;
593c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
594bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        if (mDestroyed.get()) {
595c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            loge("Received message " + msg +
596c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    "[" + msg.what + "] while being destroyed. Ignoring.");
597c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return;
598c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
599c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
600c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        try { switch (msg.what) {
601e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            case EVENT_APP_READY:
602e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                onReady();
603e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                break;
604c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
605c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_GET_DEVICE_IDENTITY_DONE:
606c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                log("Event EVENT_GET_DEVICE_IDENTITY_DONE Received");
607c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
608c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
609c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            /* IO events */
610c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_GET_IMSI_DONE:
611c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                isRecordLoadResponse = true;
612c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
613c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult)msg.obj;
614c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (ar.exception != null) {
615c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    loge("Exception querying IMSI, Exception:" + ar.exception);
616c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    break;
617c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
618c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
619c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                mImsi = (String) ar.result;
620c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
621c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // IMSI (MCC+MNC+MSIN) is at least 6 digits, but not more
622c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // than 15 (and usually 15).
623c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (mImsi != null && (mImsi.length() < 6 || mImsi.length() > 15)) {
624c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    loge("invalid IMSI " + mImsi);
625c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    mImsi = null;
626c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
627c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
628f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby                // FIXME: CSIM IMSI may not contain the MNC.
629f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby                if (false) {
630f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby                    log("IMSI: " + mImsi.substring(0, 6) + "xxxxxxxxx");
631f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby
632f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby                    String operatorNumeric = getRUIMOperatorNumeric();
633f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby                    if (operatorNumeric != null) {
634f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby                        if (operatorNumeric.length() <= 6) {
635a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                            log("update mccmnc=" + operatorNumeric);
636f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby                            MccTable.updateMccMncConfiguration(mContext, operatorNumeric, false);
637f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby                        }
638c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
639a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                } else {
640a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    String operatorNumeric = getRUIMOperatorNumeric();
641a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    log("NO update mccmnc=" + operatorNumeric);
642c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
643f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby
644c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
645c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
646c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_GET_CDMA_SUBSCRIPTION_DONE:
647c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult)msg.obj;
648c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                String localTemp[] = (String[])ar.result;
649c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (ar.exception != null) {
650c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    break;
651c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
652c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
653c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                mMyMobileNumber = localTemp[0];
654c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                mMin2Min1 = localTemp[3];
655c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                mPrlVersion = localTemp[4];
656c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
657c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                log("MDN: " + mMyMobileNumber + " MIN: " + mMin2Min1);
658c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
659c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
660c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
661c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_GET_ICCID_DONE:
662c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                isRecordLoadResponse = true;
663c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
664c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult)msg.obj;
665c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                data = (byte[])ar.result;
666c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
667c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (ar.exception != null) {
668c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    break;
669c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
670c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
671b7881d6e7e4e79491376bedf151c3412dfdc4121Wink Saville                mIccId = IccUtils.bcdToString(data, 0, data.length);
672c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
673b7881d6e7e4e79491376bedf151c3412dfdc4121Wink Saville                log("iccid: " + mIccId);
674c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
675c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
676c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
677c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_UPDATE_DONE:
678c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult)msg.obj;
679c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (ar.exception != null) {
68099c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Saville                    Rlog.i(LOG_TAG, "RuimRecords update failed", ar.exception);
681c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
682c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
683c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
684c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_GET_ALL_SMS_DONE:
685c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_MARK_SMS_READ_DONE:
686c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_SMS_ON_RUIM:
687c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_GET_SMS_DONE:
68899c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Saville                Rlog.w(LOG_TAG, "Event not supported: " + msg.what);
689c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
690c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
691c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // TODO: probably EF_CST should be read instead
692c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_GET_SST_DONE:
693c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                log("Event EVENT_GET_SST_DONE Received");
694c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            break;
695c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
696c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case EVENT_RUIM_REFRESH:
697c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                isRecordLoadResponse = false;
698c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ar = (AsyncResult)msg.obj;
699c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (ar.exception == null) {
700c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    handleRuimRefresh((IccRefreshResponse)ar.result);
701c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
702c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
703c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
704e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            default:
705e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                super.handleMessage(msg);   // IccRecords handles generic record load responses
706e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
707c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }}catch (RuntimeException exc) {
708c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // I don't want these exceptions to be fatal
70999c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Saville            Rlog.w(LOG_TAG, "Exception parsing RUIM record", exc);
710c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } finally {
711c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // Count up record load responses even if they are fails
712c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (isRecordLoadResponse) {
713c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                onRecordLoaded();
714c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
715c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
716c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
717c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
7180cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath    /**
7190cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath     * Returns an array of languages we have assets for.
7200cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath     *
7210cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath     * NOTE: This array will have duplicates. If this method will be caused
7220cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath     * frequently or in a tight loop, it can be rewritten for efficiency.
7230cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath     */
7240cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath    private static String[] getAssetLanguages(Context ctx) {
7250cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath        final String[] locales = ctx.getAssets().getLocales();
7260cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath        final String[] localeLangs = new String[locales.length];
7270cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath        for (int i = 0; i < locales.length; ++i) {
7280cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath            final String localeStr = locales[i];
7290cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath            final int separator = localeStr.indexOf('-');
7300cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath            if (separator < 0) {
7310cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath                localeLangs[i] = localeStr;
7320cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath            } else {
7330cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath                localeLangs[i] = localeStr.substring(0, separator);
7340cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath            }
7350cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath        }
7360cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath
7370cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath        return localeLangs;
7380cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath    }
7390cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath
740e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private String findBestLanguage(byte[] languages) {
7410cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath        final String[] assetLanguages = getAssetLanguages(mContext);
742e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
7430cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath        if ((languages == null) || (assetLanguages == null)) return null;
744e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
745e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // Each 2-bytes consists of one language
746e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        for (int i = 0; (i + 1) < languages.length; i += 2) {
7470cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath            final String lang;
748e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            try {
7490cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath                lang = new String(languages, i, 2, "ISO-8859-1");
750e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            } catch(java.io.UnsupportedEncodingException e) {
7510cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath                log("Failed to parse SIM language records");
7520cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath                continue;
7530cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath            }
7540cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath
7550cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath            for (int j = 0; j < assetLanguages.length; j++) {
7560cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath                if (assetLanguages[j].equals(lang)) {
7570cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath                    return lang;
7580cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath                }
759e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
760e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
7610cdae27a3afaf241764dc3a03bfff6ed012656dbNarayan Kamath
762e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // no match found. return null
763e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        return null;
764e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
765e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
766e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private void setLocaleFromCsim() {
767e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        String prefLang = null;
768e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // check EFli then EFpl
769e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        prefLang = findBestLanguage(mEFli);
770e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
771e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (prefLang == null) {
772e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            prefLang = findBestLanguage(mEFpl);
773e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
774e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
775e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (prefLang != null) {
776e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            // check country code from SIM
777e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            String imsi = getIMSI();
778e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            String country = null;
779e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (imsi != null) {
780e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                country = MccTable.countryCodeForMcc(
781e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                                    Integer.parseInt(imsi.substring(0,3)));
782e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
783e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            log("Setting locale to " + prefLang + "_" + country);
784e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            MccTable.setSystemLocale(mContext, prefLang, country);
785e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        } else {
786e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            log ("No suitable CSIM selected locale");
787e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
788e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
789e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
790c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
791c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected void onRecordLoaded() {
792c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // One record loaded successfully or failed, In either case
793c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // we need to update the recordsToLoad count
79422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mRecordsToLoad -= 1;
79522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (DBG) log("onRecordLoaded " + mRecordsToLoad + " requested: " + mRecordsRequested);
796c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
79722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (mRecordsToLoad == 0 && mRecordsRequested == true) {
798c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            onAllRecordsLoaded();
79922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        } else if (mRecordsToLoad < 0) {
800bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka            loge("recordsToLoad <0, programmer error suspected");
80122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            mRecordsToLoad = 0;
802c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
803c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
804c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
805c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
806c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected void onAllRecordsLoaded() {
807bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka        if (DBG) log("record load complete");
808bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka
809c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Further records that can be inserted are Operator/OEM dependent
810c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
811f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby        // FIXME: CSIM IMSI may not contain the MNC.
812f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby        if (false) {
813f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby            String operator = getRUIMOperatorNumeric();
814f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby            if (!TextUtils.isEmpty(operator)) {
815f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby                log("onAllRecordsLoaded set 'gsm.sim.operator.numeric' to operator='" +
816f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby                        operator + "'");
817a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                log("update icc_operator_numeric=" + operator);
818f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby                SystemProperties.set(PROPERTY_ICC_OPERATOR_NUMERIC, operator);
819f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby            } else {
820f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby                log("onAllRecordsLoaded empty 'gsm.sim.operator.numeric' skipping");
821f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby            }
822c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
823f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby            if (!TextUtils.isEmpty(mImsi)) {
824f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby                log("onAllRecordsLoaded set mcc imsi=" + mImsi);
825f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby                SystemProperties.set(PROPERTY_ICC_OPERATOR_ISO_COUNTRY,
826f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby                        MccTable.countryCodeForMcc(Integer.parseInt(mImsi.substring(0,3))));
827f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby            } else {
828f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby                log("onAllRecordsLoaded empty imsi skipping setting mcc");
829f93def879c5225379e1542eedf50bfd6aca17779Jake Hamby            }
830c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
831e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
832e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        setLocaleFromCsim();
833b7881d6e7e4e79491376bedf151c3412dfdc4121Wink Saville        mRecordsLoadedRegistrants.notifyRegistrants(
834c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            new AsyncResult(null, null, null));
835c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
836c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
837c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
838c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void onReady() {
839c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        fetchRuimRecords();
840c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
841c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        mCi.getCDMASubscription(obtainMessage(EVENT_GET_CDMA_SUBSCRIPTION_DONE));
842c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
843c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
844c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
845c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void fetchRuimRecords() {
84622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mRecordsRequested = true;
847c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
84822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (DBG) log("fetchRuimRecords " + mRecordsToLoad);
849c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
850e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mCi.getIMSIForApp(mParentApp.getAid(), obtainMessage(EVENT_GET_IMSI_DONE));
85122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mRecordsToLoad++;
852c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
853c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        mFh.loadEFTransparent(EF_ICCID,
854c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                obtainMessage(EVENT_GET_ICCID_DONE));
85522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mRecordsToLoad++;
856c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
857e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mFh.loadEFTransparent(EF_PL,
858e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfPlLoaded()));
85922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mRecordsToLoad++;
860e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
861e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mFh.loadEFTransparent(EF_CSIM_LI,
862e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimLiLoaded()));
86322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mRecordsToLoad++;
864e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
865e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mFh.loadEFTransparent(EF_CSIM_SPN,
866e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimSpnLoaded()));
86722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mRecordsToLoad++;
868e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
869e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mFh.loadEFLinearFixed(EF_CSIM_MDN, 1,
870e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimMdnLoaded()));
87122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mRecordsToLoad++;
872e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
873e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mFh.loadEFTransparent(EF_CSIM_IMSIM,
874e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimImsimLoaded()));
87522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mRecordsToLoad++;
876e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
877e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mFh.loadEFLinearFixedAll(EF_CSIM_CDMAHOME,
878e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimCdmaHomeLoaded()));
87922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mRecordsToLoad++;
880e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
881e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // Entire PRL could be huge. We are only interested in
882e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // the first 4 bytes of the record.
883e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mFh.loadEFTransparent(EF_CSIM_EPRL, 4,
884e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimEprlLoaded()));
88522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mRecordsToLoad++;
886e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
8872351b17aba5350004fc76707f3b3d2859ce773c8xinhe        mFh.loadEFTransparent(EF_CSIM_MIPUPP,
8882351b17aba5350004fc76707f3b3d2859ce773c8xinhe                obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimMipUppLoaded()));
8892351b17aba5350004fc76707f3b3d2859ce773c8xinhe        mRecordsToLoad++;
8902351b17aba5350004fc76707f3b3d2859ce773c8xinhe
89122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        if (DBG) log("fetchRuimRecords " + mRecordsToLoad + " requested: " + mRecordsRequested);
892c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Further records that can be inserted are Operator/OEM dependent
893c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
894c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
895c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
896c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * {@inheritDoc}
897c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
898c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * No Display rule for RUIMs yet.
899c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
900c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
901c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public int getDisplayRule(String plmn) {
902c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // TODO together with spn
903c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return 0;
904c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
905c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
906c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
907e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public boolean isProvisioned() {
908e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // If UICC card has CSIM app, look for MDN and MIN field
909e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // to determine if the SIM is provisioned.  Otherwise,
910e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // consider the SIM is provisioned. (for case of ordinal
911e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // USIM only UICC.)
912e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // If PROPERTY_TEST_CSIM is defined, bypess provision check
913e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        // and consider the SIM is provisioned.
914e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (SystemProperties.getBoolean(PROPERTY_TEST_CSIM, false)) {
915e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return true;
916e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
917e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
918e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (mParentApp == null) {
919e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return false;
920e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
921e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
922e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (mParentApp.getType() == AppType.APPTYPE_CSIM &&
923e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            ((mMdn == null) || (mMin == null))) {
924e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            return false;
925e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
926e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        return true;
927e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
928e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
929e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    @Override
930c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void setVoiceMessageWaiting(int line, int countWaiting) {
931c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (line != 1) {
932c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // only profile 1 is supported
933c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return;
934c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
935c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
936c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // range check
937c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (countWaiting < 0) {
938c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            countWaiting = -1;
939c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (countWaiting > 0xff) {
940c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // C.S0015-B v2, 4.5.12
941c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // range: 0-99
942c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            countWaiting = 0xff;
943c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
94422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mCountVoiceMessages = countWaiting;
945c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
946c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        mRecordsEventsRegistrants.notifyResult(EVENT_MWI);
947c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
948c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
949c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private void handleRuimRefresh(IccRefreshResponse refreshResponse) {
950c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (refreshResponse == null) {
951c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (DBG) log("handleRuimRefresh received without input");
952c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return;
953c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
954c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
955c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (refreshResponse.aid != null &&
956e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                !refreshResponse.aid.equals(mParentApp.getAid())) {
957c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // This is for different app. Ignore.
958c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return;
959c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
960c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
961c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        switch (refreshResponse.refreshResult) {
962c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case IccRefreshResponse.REFRESH_RESULT_FILE_UPDATE:
963c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (DBG) log("handleRuimRefresh with SIM_REFRESH_FILE_UPDATED");
96422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mAdnCache.reset();
965c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                fetchRuimRecords();
966c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
967c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case IccRefreshResponse.REFRESH_RESULT_INIT:
968c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (DBG) log("handleRuimRefresh with SIM_REFRESH_INIT");
969c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // need to reload all files (that we care about)
97064bfd98578babdd437f1a83d2d5e1fc92c76e729Alex Yakavenka                onIccRefreshInit();
971c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
972c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            case IccRefreshResponse.REFRESH_RESULT_RESET:
973c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (DBG) log("handleRuimRefresh with SIM_REFRESH_RESET");
974c3e37a01b74d28ebf10572bb0811c8a01916d941Shishir Agrawal                if (requirePowerOffOnSimRefreshReset()) {
975c3e37a01b74d28ebf10572bb0811c8a01916d941Shishir Agrawal                    mCi.setRadioPower(false, null);
976c3e37a01b74d28ebf10572bb0811c8a01916d941Shishir Agrawal                    /* Note: no need to call setRadioPower(true).  Assuming the desired
977c3e37a01b74d28ebf10572bb0811c8a01916d941Shishir Agrawal                    * radio power state is still ON (as tracked by ServiceStateTracker),
978c3e37a01b74d28ebf10572bb0811c8a01916d941Shishir Agrawal                    * ServiceStateTracker will call setRadioPower when it receives the
979c3e37a01b74d28ebf10572bb0811c8a01916d941Shishir Agrawal                    * RADIO_STATE_CHANGED notification for the power off.  And if the
980c3e37a01b74d28ebf10572bb0811c8a01916d941Shishir Agrawal                    * desired power state has changed in the interim, we don't want to
981c3e37a01b74d28ebf10572bb0811c8a01916d941Shishir Agrawal                    * override it with an unconditional power on.
982c3e37a01b74d28ebf10572bb0811c8a01916d941Shishir Agrawal                    */
983c3e37a01b74d28ebf10572bb0811c8a01916d941Shishir Agrawal                }
984c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
985c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            default:
986c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // unknown refresh operation
987c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (DBG) log("handleRuimRefresh with unknown operation");
988c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                break;
989c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
990c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
991c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
992e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public String getMdn() {
993e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        return mMdn;
994e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
995e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
996e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public String getMin() {
997e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        return mMin;
998e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
999e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
1000e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public String getSid() {
1001e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        return mHomeSystemId;
1002e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
1003e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
1004e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public String getNid() {
1005e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        return mHomeNetworkId;
1006e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
1007e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
1008e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public boolean getCsimSpnDisplayCondition() {
1009e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        return mCsimSpnDisplayCondition;
1010e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    }
1011c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
1012c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected void log(String s) {
101399c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Saville        Rlog.d(LOG_TAG, "[RuimRecords] " + s);
1014c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
1015c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
1016c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
1017c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected void loge(String s) {
101899c2e1d6749cfad2a8ca94a47857d8c3bfc09454Wink Saville        Rlog.e(LOG_TAG, "[RuimRecords] " + s);
1019c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
102005ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka
102105ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka    @Override
102205ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
102305ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println("RuimRecords: " + this);
102405ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" extends:");
102505ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        super.dump(fd, pw, args);
102622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        pw.println(" mOtaCommited=" + mOtaCommited);
102705ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mMyMobileNumber=" + mMyMobileNumber);
102805ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mMin2Min1=" + mMin2Min1);
102905ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mPrlVersion=" + mPrlVersion);
103005ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mEFpl[]=" + Arrays.toString(mEFpl));
103105ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mEFli[]=" + Arrays.toString(mEFli));
103205ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mCsimSpnDisplayCondition=" + mCsimSpnDisplayCondition);
103305ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mMdn=" + mMdn);
103405ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mMin=" + mMin);
103505ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mHomeSystemId=" + mHomeSystemId);
103605ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.println(" mHomeNetworkId=" + mHomeNetworkId);
103705ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka        pw.flush();
103805ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka    }
1039c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville}
1040