1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.internal.telephony.uicc;
18 
19 import static android.telephony.SmsManager.STATUS_ON_ICC_READ;
20 import static android.telephony.SmsManager.STATUS_ON_ICC_UNREAD;
21 
22 import android.compat.annotation.UnsupportedAppUsage;
23 import android.content.Context;
24 import android.content.res.Resources;
25 import android.os.AsyncResult;
26 import android.os.Build;
27 import android.os.Message;
28 import android.os.PersistableBundle;
29 import android.telephony.CarrierConfigManager;
30 import android.telephony.PhoneNumberUtils;
31 import android.telephony.SmsMessage;
32 import android.telephony.SubscriptionInfo;
33 import android.text.TextUtils;
34 import android.util.Pair;
35 
36 import com.android.internal.telephony.CommandsInterface;
37 import com.android.internal.telephony.MccTable;
38 import com.android.internal.telephony.SmsConstants;
39 import com.android.internal.telephony.SubscriptionController;
40 import com.android.internal.telephony.gsm.SimTlv;
41 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
42 import com.android.telephony.Rlog;
43 
44 import java.io.FileDescriptor;
45 import java.io.PrintWriter;
46 import java.util.ArrayList;
47 import java.util.Arrays;
48 import java.util.List;
49 
50 /**
51  * {@hide}
52  */
53 public class SIMRecords extends IccRecords {
54     protected static final String LOG_TAG = "SIMRecords";
55 
56     private static final boolean CRASH_RIL = false;
57 
58     private static final boolean VDBG = false;
59 
60     // ***** Instance Variables
61 
62     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
63     VoiceMailConstants mVmConfig;
64 
65     // ***** Cached SIM State; cleared on channel close
66 
67     private int mCallForwardingStatus;
68 
69     /**
70      * States only used by getSpnFsm FSM
71      */
72     private GetSpnFsmState mSpnState;
73 
74     /** CPHS service information (See CPHS 4.2 B.3.1.1)
75      *  It will be set in onSimReady if reading GET_CPHS_INFO successfully
76      *  mCphsInfo[0] is CPHS Phase
77      *  mCphsInfo[1] and mCphsInfo[2] is CPHS Service Table
78      */
79     private byte[] mCphsInfo = null;
80     boolean mCspPlmnEnabled = true;
81 
82     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
83     byte[] mEfMWIS = null;
84     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
85     byte[] mEfCPHS_MWI =null;
86     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
87     byte[] mEfCff = null;
88     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
89     byte[] mEfCfis = null;
90 
91     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
92     byte[] mEfLi = null;
93     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
94     byte[] mEfPl = null;
95 
96     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
97     UsimServiceTable mUsimServiceTable;
98 
99     @Override
toString()100     public String toString() {
101         return "SimRecords: " + super.toString()
102                 + " mVmConfig" + mVmConfig
103                 + " callForwardingEnabled=" + mCallForwardingStatus
104                 + " spnState=" + mSpnState
105                 + " mCphsInfo=" + mCphsInfo
106                 + " mCspPlmnEnabled=" + mCspPlmnEnabled
107                 + " efMWIS=" + mEfMWIS
108                 + " efCPHS_MWI=" + mEfCPHS_MWI
109                 + " mEfCff=" + mEfCff
110                 + " mEfCfis=" + mEfCfis
111                 + " getOperatorNumeric=" + getOperatorNumeric();
112     }
113 
114     // ***** Constants
115 
116     // From TS 51.011 EF[SPDI] section
117     static final int TAG_SPDI = 0xA3;
118     static final int TAG_SPDI_PLMN_LIST = 0x80;
119 
120     // Full Name IEI from TS 24.008
121     static final int TAG_FULL_NETWORK_NAME = 0x43;
122 
123     // Short Name IEI from TS 24.008
124     static final int TAG_SHORT_NETWORK_NAME = 0x45;
125 
126     // PLMN Additional Information tag from from TS 24.008
127     static final int TAG_PLMN_ADDITIONAL_INFORMATION = 0x80;
128 
129     // active CFF from CPHS 4.2 B.4.5
130     static final int CFF_UNCONDITIONAL_ACTIVE = 0x0a;
131     static final int CFF_UNCONDITIONAL_DEACTIVE = 0x05;
132     static final int CFF_LINE1_MASK = 0x0f;
133     static final int CFF_LINE1_RESET = 0xf0;
134 
135     // CPHS Service Table (See CPHS 4.2 B.3.1)
136     private static final int CPHS_SST_MBN_MASK = 0x30;
137     private static final int CPHS_SST_MBN_ENABLED = 0x30;
138 
139     // EF_CFIS related constants
140     // Spec reference TS 51.011 section 10.3.46.
141     private static final int CFIS_BCD_NUMBER_LENGTH_OFFSET = 2;
142     private static final int CFIS_TON_NPI_OFFSET = 3;
143     private static final int CFIS_ADN_CAPABILITY_ID_OFFSET = 14;
144     private static final int CFIS_ADN_EXTENSION_ID_OFFSET = 15;
145 
146     // 3GPP specification constants
147     // Spec reference TS 31.102 section 4.2.16
148     private static final int FPLMN_BYTE_SIZE = 3;
149 
150     // ***** Event Constants
151     private static final int SIM_RECORD_EVENT_BASE = 0x00;
152     private static final int EVENT_GET_IMSI_DONE = 3 + SIM_RECORD_EVENT_BASE;
153     private static final int EVENT_GET_ICCID_DONE = 4 + SIM_RECORD_EVENT_BASE;
154     private static final int EVENT_GET_MBI_DONE = 5 + SIM_RECORD_EVENT_BASE;
155     private static final int EVENT_GET_MBDN_DONE = 6 + SIM_RECORD_EVENT_BASE;
156     private static final int EVENT_GET_MWIS_DONE = 7 + SIM_RECORD_EVENT_BASE;
157     private static final int EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE = 8 + SIM_RECORD_EVENT_BASE;
158     private static final int EVENT_GET_AD_DONE = 9 + SIM_RECORD_EVENT_BASE; // Admin data on SIM
159     private static final int EVENT_GET_MSISDN_DONE = 10 + SIM_RECORD_EVENT_BASE;
160     private static final int EVENT_GET_CPHS_MAILBOX_DONE = 11 + SIM_RECORD_EVENT_BASE;
161     private static final int EVENT_GET_SPN_DONE = 12 + SIM_RECORD_EVENT_BASE;
162     private static final int EVENT_GET_SPDI_DONE = 13 + SIM_RECORD_EVENT_BASE;
163     private static final int EVENT_UPDATE_DONE = 14 + SIM_RECORD_EVENT_BASE;
164     protected static final int EVENT_GET_PNN_DONE = 15 + SIM_RECORD_EVENT_BASE;
165     protected static final int EVENT_GET_OPL_DONE = 16 + SIM_RECORD_EVENT_BASE;
166     private static final int EVENT_GET_SST_DONE = 17 + SIM_RECORD_EVENT_BASE;
167     private static final int EVENT_GET_ALL_SMS_DONE = 18 + SIM_RECORD_EVENT_BASE;
168     private static final int EVENT_MARK_SMS_READ_DONE = 19 + SIM_RECORD_EVENT_BASE;
169     private static final int EVENT_SET_MBDN_DONE = 20 + SIM_RECORD_EVENT_BASE;
170     private static final int EVENT_SMS_ON_SIM = 21 + SIM_RECORD_EVENT_BASE;
171     private static final int EVENT_GET_SMS_DONE = 22 + SIM_RECORD_EVENT_BASE;
172     private static final int EVENT_GET_CFF_DONE = 24 + SIM_RECORD_EVENT_BASE;
173     private static final int EVENT_SET_CPHS_MAILBOX_DONE = 25 + SIM_RECORD_EVENT_BASE;
174     private static final int EVENT_GET_INFO_CPHS_DONE = 26 + SIM_RECORD_EVENT_BASE;
175     private static final int EVENT_SET_MSISDN_DONE = 30 + SIM_RECORD_EVENT_BASE;
176     private static final int EVENT_GET_CFIS_DONE = 32 + SIM_RECORD_EVENT_BASE;
177     private static final int EVENT_GET_CSP_CPHS_DONE = 33 + SIM_RECORD_EVENT_BASE;
178     private static final int EVENT_GET_GID1_DONE = 34 + SIM_RECORD_EVENT_BASE;
179     private static final int EVENT_GET_GID2_DONE = 36 + SIM_RECORD_EVENT_BASE;
180     private static final int EVENT_GET_PLMN_W_ACT_DONE = 37 + SIM_RECORD_EVENT_BASE;
181     private static final int EVENT_GET_OPLMN_W_ACT_DONE = 38 + SIM_RECORD_EVENT_BASE;
182     private static final int EVENT_GET_HPLMN_W_ACT_DONE = 39 + SIM_RECORD_EVENT_BASE;
183     private static final int EVENT_GET_EHPLMN_DONE = 40 + SIM_RECORD_EVENT_BASE;
184     private static final int EVENT_GET_FPLMN_DONE = 41 + SIM_RECORD_EVENT_BASE;
185     private static final int EVENT_GET_FPLMN_SIZE_DONE = 42 + SIM_RECORD_EVENT_BASE;
186     private static final int EVENT_SET_FPLMN_DONE = 43 + SIM_RECORD_EVENT_BASE;
187     // ***** Constructor
188 
SIMRecords(UiccCardApplication app, Context c, CommandsInterface ci)189     public SIMRecords(UiccCardApplication app, Context c, CommandsInterface ci) {
190         super(app, c, ci);
191 
192         mAdnCache = new AdnRecordCache(mFh);
193 
194         mVmConfig = new VoiceMailConstants();
195 
196         mRecordsRequested = false;  // No load request is made till SIM ready
197         mLockedRecordsReqReason = LOCKED_RECORDS_REQ_REASON_NONE;
198 
199         // recordsToLoad is set to 0 because no requests are made yet
200         mRecordsToLoad = 0;
201 
202         mCi.setOnSmsOnSim(this, EVENT_SMS_ON_SIM, null);
203 
204         // Start off by setting empty state
205         resetRecords();
206         if (DBG) log("SIMRecords X ctor this=" + this);
207     }
208 
209     @Override
dispose()210     public void dispose() {
211         if (DBG) log("Disposing SIMRecords this=" + this);
212         //Unregister for all events
213         mCi.unSetOnSmsOnSim(this);
214         resetRecords();
215         super.dispose();
216     }
217 
218     @Override
finalize()219     protected void finalize() {
220         if (DBG) log("finalized");
221     }
222 
resetRecords()223     protected void resetRecords() {
224         mImsi = null;
225         mMsisdn = null;
226         mVoiceMailNum = null;
227         mMncLength = UNINITIALIZED;
228         log("setting0 mMncLength" + mMncLength);
229         mIccId = null;
230         mFullIccId = null;
231         mCarrierNameDisplayCondition = DEFAULT_CARRIER_NAME_DISPLAY_CONDITION;
232         mEfMWIS = null;
233         mEfCPHS_MWI = null;
234         mSpdi = null;
235         mPnnHomeName = null;
236         mPnns = null;
237         mOpl = null;
238         mGid1 = null;
239         mGid2 = null;
240         mPlmnActRecords = null;
241         mOplmnActRecords = null;
242         mHplmnActRecords = null;
243         mFplmns = null;
244         mEhplmns = null;
245 
246         mAdnCache.reset();
247 
248         log("SIMRecords: onRadioOffOrNotAvailable set 'gsm.sim.operator.numeric' to operator=null");
249         log("update icc_operator_numeric=" + null);
250         mTelephonyManager.setSimOperatorNumericForPhone(mParentApp.getPhoneId(), "");
251         mTelephonyManager.setSimOperatorNameForPhone(mParentApp.getPhoneId(), "");
252         mTelephonyManager.setSimCountryIsoForPhone(mParentApp.getPhoneId(), "");
253 
254         // recordsRequested is set to false indicating that the SIM
255         // read requests made so far are not valid. This is set to
256         // true only when fresh set of read requests are made.
257         mRecordsRequested = false;
258         mLockedRecordsReqReason = LOCKED_RECORDS_REQ_REASON_NONE;
259         mLoaded.set(false);
260     }
261 
262     //***** Public Methods
263 
264     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
265     @Override
getMsisdnNumber()266     public String getMsisdnNumber() {
267         return mMsisdn;
268     }
269 
270     @Override
getUsimServiceTable()271     public UsimServiceTable getUsimServiceTable() {
272         return mUsimServiceTable;
273     }
274 
275     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getExtFromEf(int ef)276     private int getExtFromEf(int ef) {
277         int ext;
278         switch (ef) {
279             case EF_MSISDN:
280                 /* For USIM apps use EXT5. (TS 31.102 Section 4.2.37) */
281                 if (mParentApp.getType() == AppType.APPTYPE_USIM) {
282                     ext = EF_EXT5;
283                 } else {
284                     ext = EF_EXT1;
285                 }
286                 break;
287             default:
288                 ext = EF_EXT1;
289         }
290         return ext;
291     }
292 
293     /**
294      * Set subscriber number to SIM record
295      *
296      * The subscriber number is stored in EF_MSISDN (TS 51.011)
297      *
298      * When the operation is complete, onComplete will be sent to its handler
299      *
300      * @param alphaTag alpha-tagging of the dailing nubmer (up to 10 characters)
301      * @param number dialing number (up to 20 digits)
302      *        if the number starts with '+', then set to international TOA
303      * @param onComplete
304      *        onComplete.obj will be an AsyncResult
305      *        ((AsyncResult)onComplete.obj).exception == null on success
306      *        ((AsyncResult)onComplete.obj).exception != null on fail
307      */
308     @Override
setMsisdnNumber(String alphaTag, String number, Message onComplete)309     public void setMsisdnNumber(String alphaTag, String number,
310             Message onComplete) {
311 
312         // If the SIM card is locked by PIN, we will set EF_MSISDN fail.
313         // In that case, msisdn and msisdnTag should not be update.
314         mNewMsisdn = number;
315         mNewMsisdnTag = alphaTag;
316 
317         if(DBG) log("Set MSISDN: " + mNewMsisdnTag + " " + /*mNewMsisdn*/
318                 Rlog.pii(LOG_TAG, mNewMsisdn));
319 
320         AdnRecord adn = new AdnRecord(mNewMsisdnTag, mNewMsisdn);
321 
322         new AdnRecordLoader(mFh).updateEF(adn, EF_MSISDN, getExtFromEf(EF_MSISDN), 1, null,
323                 obtainMessage(EVENT_SET_MSISDN_DONE, onComplete));
324     }
325 
326     @Override
getMsisdnAlphaTag()327     public String getMsisdnAlphaTag() {
328         return mMsisdnTag;
329     }
330 
331     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
332     @Override
getVoiceMailNumber()333     public String getVoiceMailNumber() {
334         return mVoiceMailNum;
335     }
336 
337     /**
338      * Set voice mail number to SIM record
339      *
340      * The voice mail number can be stored either in EF_MBDN (TS 51.011) or
341      * EF_MAILBOX_CPHS (CPHS 4.2)
342      *
343      * If EF_MBDN is available, store the voice mail number to EF_MBDN
344      *
345      * If EF_MAILBOX_CPHS is enabled, store the voice mail number to EF_CHPS
346      *
347      * So the voice mail number will be stored in both EFs if both are available
348      *
349      * Return error only if both EF_MBDN and EF_MAILBOX_CPHS fail.
350      *
351      * When the operation is complete, onComplete will be sent to its handler
352      *
353      * @param alphaTag alpha-tagging of the dailing nubmer (upto 10 characters)
354      * @param voiceNumber dailing nubmer (upto 20 digits)
355      *        if the number is start with '+', then set to international TOA
356      * @param onComplete
357      *        onComplete.obj will be an AsyncResult
358      *        ((AsyncResult)onComplete.obj).exception == null on success
359      *        ((AsyncResult)onComplete.obj).exception != null on fail
360      */
361     @Override
setVoiceMailNumber(String alphaTag, String voiceNumber, Message onComplete)362     public void setVoiceMailNumber(String alphaTag, String voiceNumber,
363             Message onComplete) {
364         if (mDestroyed.get()) {
365             return;
366         }
367 
368         if (mIsVoiceMailFixed) {
369             AsyncResult.forMessage((onComplete)).exception =
370                     new IccVmFixedException("Voicemail number is fixed by operator");
371             onComplete.sendToTarget();
372             return;
373         }
374 
375         mNewVoiceMailNum = voiceNumber;
376         mNewVoiceMailTag = alphaTag;
377 
378         AdnRecord adn = new AdnRecord(mNewVoiceMailTag, mNewVoiceMailNum);
379 
380         if (mMailboxIndex != 0 && mMailboxIndex != 0xff) {
381 
382             new AdnRecordLoader(mFh).updateEF(adn, EF_MBDN, EF_EXT6,
383                     mMailboxIndex, null,
384                     obtainMessage(EVENT_SET_MBDN_DONE, onComplete));
385 
386         } else if (isCphsMailboxEnabled()) {
387 
388             new AdnRecordLoader(mFh).updateEF(adn, EF_MAILBOX_CPHS,
389                     EF_EXT1, 1, null,
390                     obtainMessage(EVENT_SET_CPHS_MAILBOX_DONE, onComplete));
391 
392         } else {
393             AsyncResult.forMessage((onComplete)).exception =
394                     new IccVmNotSupportedException("Update SIM voice mailbox error");
395             onComplete.sendToTarget();
396         }
397     }
398 
399     @Override
getVoiceMailAlphaTag()400     public String getVoiceMailAlphaTag()
401     {
402         return mVoiceMailTag;
403     }
404 
405     /**
406      * Sets the SIM voice message waiting indicator records
407      * @param line GSM Subscriber Profile Number, one-based. Only '1' is supported
408      * @param countWaiting The number of messages waiting, if known. Use
409      *                     -1 to indicate that an unknown number of
410      *                      messages are waiting
411      */
412     @Override
413     public void
setVoiceMessageWaiting(int line, int countWaiting)414     setVoiceMessageWaiting(int line, int countWaiting) {
415         if (line != 1) {
416             // only profile 1 is supported
417             return;
418         }
419 
420         try {
421             if (mEfMWIS != null) {
422                 // TS 51.011 10.3.45
423 
424                 // lsb of byte 0 is 'voicemail' status
425                 mEfMWIS[0] = (byte)((mEfMWIS[0] & 0xfe)
426                                     | (countWaiting == 0 ? 0 : 1));
427 
428                 // byte 1 is the number of voice messages waiting
429                 if (countWaiting < 0) {
430                     // The spec does not define what this should be
431                     // if we don't know the count
432                     mEfMWIS[1] = 0;
433                 } else {
434                     mEfMWIS[1] = (byte) countWaiting;
435                 }
436 
437                 mFh.updateEFLinearFixed(
438                     EF_MWIS, 1, mEfMWIS, null,
439                     obtainMessage (EVENT_UPDATE_DONE, EF_MWIS, 0));
440             }
441 
442             if (mEfCPHS_MWI != null) {
443                     // Refer CPHS4_2.WW6 B4.2.3
444                 mEfCPHS_MWI[0] = (byte)((mEfCPHS_MWI[0] & 0xf0)
445                             | (countWaiting == 0 ? 0x5 : 0xa));
446                 mFh.updateEFTransparent(
447                     EF_VOICE_MAIL_INDICATOR_CPHS, mEfCPHS_MWI,
448                     obtainMessage (EVENT_UPDATE_DONE, EF_VOICE_MAIL_INDICATOR_CPHS));
449             }
450         } catch (ArrayIndexOutOfBoundsException ex) {
451             logw("Error saving voice mail state to SIM. Probably malformed SIM record", ex);
452         }
453     }
454 
455     // Validate data is not null and not empty.
validEfCfis(byte[] data)456     private boolean validEfCfis(byte[] data) {
457         if (data != null) {
458             if (data[0] < 1 || data[0] > 4) {
459                 // The MSP (Multiple Subscriber Profile) byte should be between
460                 // 1 and 4 according to ETSI TS 131 102 v11.3.0 section 4.2.64.
461                 logw("MSP byte: " + data[0] + " is not between 1 and 4", null);
462             }
463             // empty EF_CFIS should be considered as call forward disabled
464             for (byte b : data) {
465                 if (b != (byte) 0xFF) {
466                     return true;
467                 }
468             }
469         }
470         return false;
471     }
472 
getVoiceMessageCount()473     public int getVoiceMessageCount() {
474         boolean voiceMailWaiting = false;
475         int countVoiceMessages = DEFAULT_VOICE_MESSAGE_COUNT;
476         if (mEfMWIS != null) {
477             // Use this data if the EF[MWIS] exists and
478             // has been loaded
479             // Refer TS 51.011 Section 10.3.45 for the content description
480             voiceMailWaiting = ((mEfMWIS[0] & 0x01) != 0);
481             countVoiceMessages = mEfMWIS[1] & 0xff;
482 
483             if (voiceMailWaiting && (countVoiceMessages == 0 || countVoiceMessages == 0xff)) {
484                 // Unknown count = -1
485                 countVoiceMessages = UNKNOWN_VOICE_MESSAGE_COUNT;
486             }
487             if (DBG) log(" VoiceMessageCount from SIM MWIS = " + countVoiceMessages);
488         } else if (mEfCPHS_MWI != null) {
489             // use voice mail count from CPHS
490             int indicator = (int) (mEfCPHS_MWI[0] & 0xf);
491 
492             // Refer CPHS4_2.WW6 B4.2.3
493             if (indicator == 0xA) {
494                 // Unknown count = -1
495                 countVoiceMessages = UNKNOWN_VOICE_MESSAGE_COUNT;
496             } else if (indicator == 0x5) {
497                 countVoiceMessages = 0;
498             }
499             if (DBG) log(" VoiceMessageCount from SIM CPHS = " + countVoiceMessages);
500         }
501         return countVoiceMessages;
502     }
503 
504     /**
505      * {@inheritDoc}
506      */
507     @Override
getVoiceCallForwardingFlag()508     public int getVoiceCallForwardingFlag() {
509         return mCallForwardingStatus;
510     }
511 
512     /**
513      * {@inheritDoc}
514      */
515     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
516     @Override
setVoiceCallForwardingFlag(int line, boolean enable, String dialNumber)517     public void setVoiceCallForwardingFlag(int line, boolean enable, String dialNumber) {
518 
519         if (line != 1) return; // only line 1 is supported
520 
521         mCallForwardingStatus = enable ? CALL_FORWARDING_STATUS_ENABLED :
522                 CALL_FORWARDING_STATUS_DISABLED;
523 
524         mRecordsEventsRegistrants.notifyResult(EVENT_CFI);
525 
526         try {
527             if (validEfCfis(mEfCfis)) {
528                 // lsb is of byte f1 is voice status
529                 if (enable) {
530                     mEfCfis[1] |= 1;
531                 } else {
532                     mEfCfis[1] &= 0xfe;
533                 }
534 
535                 log("setVoiceCallForwardingFlag: enable=" + enable
536                         + " mEfCfis=" + IccUtils.bytesToHexString(mEfCfis));
537 
538                 // Update dialNumber if not empty and CFU is enabled.
539                 // Spec reference for EF_CFIS contents, TS 51.011 section 10.3.46.
540                 if (enable && !TextUtils.isEmpty(dialNumber)) {
541                     logv("EF_CFIS: updating cf number, " + Rlog.pii(LOG_TAG, dialNumber));
542                     byte[] bcdNumber = PhoneNumberUtils.numberToCalledPartyBCD(
543                             dialNumber, PhoneNumberUtils.BCD_EXTENDED_TYPE_EF_ADN);
544 
545                     System.arraycopy(bcdNumber, 0, mEfCfis, CFIS_TON_NPI_OFFSET, bcdNumber.length);
546 
547                     mEfCfis[CFIS_BCD_NUMBER_LENGTH_OFFSET] = (byte) (bcdNumber.length);
548                     mEfCfis[CFIS_ADN_CAPABILITY_ID_OFFSET] = (byte) 0xFF;
549                     mEfCfis[CFIS_ADN_EXTENSION_ID_OFFSET] = (byte) 0xFF;
550                 }
551 
552                 mFh.updateEFLinearFixed(
553                         EF_CFIS, 1, mEfCfis, null,
554                         obtainMessage (EVENT_UPDATE_DONE, EF_CFIS));
555             } else {
556                 log("setVoiceCallForwardingFlag: ignoring enable=" + enable
557                         + " invalid mEfCfis=" + IccUtils.bytesToHexString(mEfCfis));
558             }
559 
560             if (mEfCff != null) {
561                 if (enable) {
562                     mEfCff[0] = (byte) ((mEfCff[0] & CFF_LINE1_RESET)
563                             | CFF_UNCONDITIONAL_ACTIVE);
564                 } else {
565                     mEfCff[0] = (byte) ((mEfCff[0] & CFF_LINE1_RESET)
566                             | CFF_UNCONDITIONAL_DEACTIVE);
567                 }
568 
569                 mFh.updateEFTransparent(
570                         EF_CFF_CPHS, mEfCff,
571                         obtainMessage (EVENT_UPDATE_DONE, EF_CFF_CPHS));
572             }
573         } catch (ArrayIndexOutOfBoundsException ex) {
574             logw("Error saving call forwarding flag to SIM. "
575                             + "Probably malformed SIM record", ex);
576 
577         }
578     }
579 
580     /**
581      * Called by STK Service when REFRESH is received.
582      * @param fileChanged indicates whether any files changed
583      * @param fileList if non-null, a list of EF files that changed
584      */
585     @Override
onRefresh(boolean fileChanged, int[] fileList)586     public void onRefresh(boolean fileChanged, int[] fileList) {
587         if (fileChanged) {
588             // A future optimization would be to inspect fileList and
589             // only reload those files that we care about.  For now,
590             // just re-fetch all SIM records that we cache.
591             fetchSimRecords();
592         }
593     }
594 
595     /**
596      * {@inheritDoc}
597      */
598     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
599     @Override
getOperatorNumeric()600     public String getOperatorNumeric() {
601         String imsi = getIMSI();
602         if (imsi == null) {
603             log("getOperatorNumeric: IMSI == null");
604             return null;
605         }
606         if (mMncLength == UNINITIALIZED || mMncLength == UNKNOWN) {
607             log("getSIMOperatorNumeric: bad mncLength");
608             return null;
609         }
610 
611         // Length = length of MCC + length of MNC
612         // length of mcc = 3 (TS 23.003 Section 2.2)
613         if (imsi.length() >= 3 + mMncLength) {
614             return imsi.substring(0, 3 + mMncLength);
615         } else {
616             return null;
617         }
618     }
619 
620     // ***** Overridden from Handler
621     @Override
handleMessage(Message msg)622     public void handleMessage(Message msg) {
623         AsyncResult ar;
624         AdnRecord adn;
625 
626         byte data[];
627 
628         boolean isRecordLoadResponse = false;
629 
630         if (mDestroyed.get()) {
631             loge("Received message " + msg + "[" + msg.what + "] " +
632                     " while being destroyed. Ignoring.");
633             return;
634         }
635 
636         try {
637             switch (msg.what) {
638                 /* IO events */
639                 case EVENT_GET_IMSI_DONE:
640                     isRecordLoadResponse = true;
641                     ar = (AsyncResult) msg.obj;
642 
643                     if (ar.exception != null) {
644                         loge("Exception querying IMSI, Exception:" + ar.exception);
645                         break;
646                     }
647 
648                     setImsi((String) ar.result);
649                     break;
650 
651                 case EVENT_GET_MBI_DONE:
652                     boolean isValidMbdn;
653                     isRecordLoadResponse = true;
654 
655                     ar = (AsyncResult) msg.obj;
656                     data = (byte[]) ar.result;
657 
658                     isValidMbdn = false;
659                     if (ar.exception == null) {
660                         // Refer TS 51.011 Section 10.3.44 for content details
661                         log("EF_MBI: " + IccUtils.bytesToHexString(data));
662 
663                         // Voice mail record number stored first
664                         mMailboxIndex = data[0] & 0xff;
665 
666                         // check if dailing numbe id valid
667                         if (mMailboxIndex != 0 && mMailboxIndex != 0xff) {
668                             log("Got valid mailbox number for MBDN");
669                             isValidMbdn = true;
670                         }
671                     }
672 
673                     // one more record to load
674                     mRecordsToLoad += 1;
675 
676                     if (isValidMbdn) {
677                         // Note: MBDN was not included in NUM_OF_SIM_RECORDS_LOADED
678                         new AdnRecordLoader(mFh).loadFromEF(EF_MBDN, EF_EXT6,
679                                 mMailboxIndex, obtainMessage(EVENT_GET_MBDN_DONE));
680                     } else {
681                         // If this EF not present, try mailbox as in CPHS standard
682                         // CPHS (CPHS4_2.WW6) is a european standard.
683                         new AdnRecordLoader(mFh).loadFromEF(EF_MAILBOX_CPHS,
684                                 EF_EXT1, 1,
685                                 obtainMessage(EVENT_GET_CPHS_MAILBOX_DONE));
686                     }
687 
688                     break;
689                 case EVENT_GET_CPHS_MAILBOX_DONE:
690                 case EVENT_GET_MBDN_DONE:
691                     //Resetting the voice mail number and voice mail tag to null
692                     //as these should be updated from the data read from EF_MBDN.
693                     //If they are not reset, incase of invalid data/exception these
694                     //variables are retaining their previous values and are
695                     //causing invalid voice mailbox info display to user.
696                     mVoiceMailNum = null;
697                     mVoiceMailTag = null;
698                     isRecordLoadResponse = true;
699 
700                     ar = (AsyncResult) msg.obj;
701 
702                     if (ar.exception != null) {
703 
704                         log("Invalid or missing EF"
705                                 + ((msg.what == EVENT_GET_CPHS_MAILBOX_DONE)
706                                     ? "[MAILBOX]" : "[MBDN]"));
707 
708                         // Bug #645770 fall back to CPHS
709                         // FIXME should use SST to decide
710 
711                         if (msg.what == EVENT_GET_MBDN_DONE) {
712                             //load CPHS on fail...
713                             // FIXME right now, only load line1's CPHS voice mail entry
714 
715                             mRecordsToLoad += 1;
716                             new AdnRecordLoader(mFh).loadFromEF(
717                                     EF_MAILBOX_CPHS, EF_EXT1, 1,
718                                     obtainMessage(EVENT_GET_CPHS_MAILBOX_DONE));
719                         }
720                         break;
721                     }
722 
723                     adn = (AdnRecord) ar.result;
724 
725                     log("VM: " + adn
726                             + ((msg.what == EVENT_GET_CPHS_MAILBOX_DONE)
727                                 ? " EF[MAILBOX]" : " EF[MBDN]"));
728 
729                     if (adn.isEmpty() && msg.what == EVENT_GET_MBDN_DONE) {
730                         // Bug #645770 fall back to CPHS
731                         // FIXME should use SST to decide
732                         // FIXME right now, only load line1's CPHS voice mail entry
733                         mRecordsToLoad += 1;
734                         new AdnRecordLoader(mFh).loadFromEF(
735                                 EF_MAILBOX_CPHS, EF_EXT1, 1,
736                                 obtainMessage(EVENT_GET_CPHS_MAILBOX_DONE));
737 
738                         break;
739                     }
740 
741                     mVoiceMailNum = adn.getNumber();
742                     mVoiceMailTag = adn.getAlphaTag();
743                     break;
744 
745                 case EVENT_GET_MSISDN_DONE:
746                     isRecordLoadResponse = true;
747 
748                     ar = (AsyncResult) msg.obj;
749 
750                     if (ar.exception != null) {
751                         log("Invalid or missing EF[MSISDN]");
752                         break;
753                     }
754 
755                     adn = (AdnRecord) ar.result;
756 
757                     mMsisdn = adn.getNumber();
758                     mMsisdnTag = adn.getAlphaTag();
759 
760                     log("MSISDN: " + /*mMsisdn*/ Rlog.pii(LOG_TAG, mMsisdn));
761                     break;
762 
763                 case EVENT_SET_MSISDN_DONE:
764                     isRecordLoadResponse = false;
765                     ar = (AsyncResult) msg.obj;
766 
767                     if (ar.exception == null) {
768                         mMsisdn = mNewMsisdn;
769                         mMsisdnTag = mNewMsisdnTag;
770                         log("Success to update EF[MSISDN]");
771                     }
772 
773                     if (ar.userObj != null) {
774                         AsyncResult.forMessage(((Message) ar.userObj)).exception = ar.exception;
775                         ((Message) ar.userObj).sendToTarget();
776                     }
777                     break;
778 
779                 case EVENT_GET_MWIS_DONE:
780                     isRecordLoadResponse = true;
781 
782                     ar = (AsyncResult) msg.obj;
783                     data = (byte[]) ar.result;
784 
785                     if (DBG) log("EF_MWIS : " + IccUtils.bytesToHexString(data));
786 
787                     if (ar.exception != null) {
788                         if (DBG) log("EVENT_GET_MWIS_DONE exception = " + ar.exception);
789                         break;
790                     }
791 
792                     if ((data[0] & 0xff) == 0xff) {
793                         if (DBG) log("SIMRecords: Uninitialized record MWIS");
794                         break;
795                     }
796 
797                     mEfMWIS = data;
798                     break;
799 
800                 case EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE:
801                     isRecordLoadResponse = true;
802 
803                     ar = (AsyncResult) msg.obj;
804                     data = (byte[]) ar.result;
805 
806                     if (DBG) log("EF_CPHS_MWI: " + IccUtils.bytesToHexString(data));
807 
808                     if (ar.exception != null) {
809                         if (DBG) {
810                             log("EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE exception = "
811                                     + ar.exception);
812                         }
813                         break;
814                     }
815 
816                     mEfCPHS_MWI = data;
817                     break;
818 
819                 case EVENT_GET_ICCID_DONE:
820                     isRecordLoadResponse = true;
821 
822                     ar = (AsyncResult) msg.obj;
823                     data = (byte[]) ar.result;
824 
825                     if (ar.exception != null) {
826                         break;
827                     }
828 
829                     mIccId = IccUtils.bcdToString(data, 0, data.length);
830                     mFullIccId = IccUtils.bchToString(data, 0, data.length);
831 
832                     log("iccid: " + SubscriptionInfo.givePrintableIccid(mFullIccId));
833                     break;
834 
835                 case EVENT_GET_AD_DONE:
836                     isRecordLoadResponse = true;
837                     mMncLength = UNKNOWN;
838                     try {
839                         if (!mCarrierTestOverride.isInTestMode()) {
840                             ar = (AsyncResult) msg.obj;
841                             data = (byte[]) ar.result;
842 
843                             if (ar.exception != null) {
844                                 break;
845                             }
846 
847                             log("EF_AD: " + IccUtils.bytesToHexString(data));
848 
849                             if (data.length < 3) {
850                                 log("Corrupt AD data on SIM");
851                                 break;
852                             }
853 
854                             if (data.length == 3) {
855                                 log("MNC length not present in EF_AD");
856                                 break;
857                             }
858 
859                             int len = data[3] & 0xf;
860                             if (len == 2 || len == 3) {
861                                 mMncLength = len;
862                             } else {
863                                 log("Received invalid or unset MNC Length=" + len);
864                             }
865                         }
866                     } finally {
867                         updateOperatorPlmn();
868                     }
869                     break;
870 
871                 case EVENT_GET_SPN_DONE:
872                     isRecordLoadResponse = true;
873                     ar = (AsyncResult) msg.obj;
874                     getSpnFsm(false, ar);
875                     break;
876 
877                 case EVENT_GET_CFF_DONE:
878                     isRecordLoadResponse = true;
879 
880                     ar = (AsyncResult) msg.obj;
881                     data = (byte[]) ar.result;
882 
883                     if (ar.exception != null) {
884                         mEfCff = null;
885                     } else {
886                         log("EF_CFF_CPHS: " + IccUtils.bytesToHexString(data));
887                         mEfCff = data;
888                     }
889 
890                     break;
891 
892                 case EVENT_GET_SPDI_DONE:
893                     isRecordLoadResponse = true;
894 
895                     ar = (AsyncResult) msg.obj;
896                     data = (byte[]) ar.result;
897 
898                     if (ar.exception != null) {
899                         break;
900                     }
901 
902                     parseEfSpdi(data);
903                     break;
904 
905                 case EVENT_UPDATE_DONE:
906                     ar = (AsyncResult) msg.obj;
907                     if (ar.exception != null) {
908                         logw("update failed. ", ar.exception);
909                     }
910                     break;
911 
912                 case EVENT_GET_PNN_DONE:
913                     isRecordLoadResponse = true;
914 
915                     ar = (AsyncResult) msg.obj;
916                     if (ar.exception != null) {
917                         break;
918                     }
919 
920                     parseEfPnn((ArrayList<byte[]>) ar.result);
921                     break;
922 
923                 case EVENT_GET_OPL_DONE:
924                     isRecordLoadResponse = true;
925 
926                     ar = (AsyncResult) msg.obj;
927                     if (ar.exception != null) {
928                         break;
929                     }
930 
931                     parseEfOpl((ArrayList<byte[]>) ar.result);
932                     break;
933 
934                 case EVENT_GET_ALL_SMS_DONE:
935                     isRecordLoadResponse = true;
936 
937                     ar = (AsyncResult) msg.obj;
938                     if (ar.exception != null) {
939                         break;
940                     }
941 
942                     handleSmses((ArrayList<byte[]>) ar.result);
943                     break;
944 
945                 case EVENT_MARK_SMS_READ_DONE:
946                     log("marked read: sms " + msg.arg1);
947                     break;
948 
949 
950                 case EVENT_SMS_ON_SIM:
951                     isRecordLoadResponse = false;
952 
953                     ar = (AsyncResult) msg.obj;
954 
955                     Integer index = (Integer) ar.result;
956 
957                     if (ar.exception != null || index == null) {
958                         loge("Error on SMS_ON_SIM with exp "
959                                 + ar.exception + " index " + index);
960                     } else {
961                         log("READ EF_SMS RECORD index=" + index);
962                         mFh.loadEFLinearFixed(EF_SMS, index, obtainMessage(EVENT_GET_SMS_DONE));
963                     }
964                     break;
965 
966                 case EVENT_GET_SMS_DONE:
967                     isRecordLoadResponse = false;
968                     ar = (AsyncResult) msg.obj;
969                     if (ar.exception == null) {
970                         handleSms((byte[]) ar.result);
971                     } else {
972                         loge("Error on GET_SMS with exp " + ar.exception);
973                     }
974                     break;
975                 case EVENT_GET_SST_DONE:
976                     isRecordLoadResponse = true;
977 
978                     ar = (AsyncResult) msg.obj;
979                     data = (byte[]) ar.result;
980 
981                     if (ar.exception != null) {
982                         break;
983                     }
984 
985                     mUsimServiceTable = new UsimServiceTable(data);
986                     if (DBG) log("SST: " + mUsimServiceTable);
987                     break;
988 
989                 case EVENT_GET_INFO_CPHS_DONE:
990                     isRecordLoadResponse = true;
991 
992                     ar = (AsyncResult) msg.obj;
993 
994                     if (ar.exception != null) {
995                         break;
996                     }
997 
998                     mCphsInfo = (byte[]) ar.result;
999 
1000                     if (DBG) log("iCPHS: " + IccUtils.bytesToHexString(mCphsInfo));
1001                     break;
1002 
1003                 case EVENT_SET_MBDN_DONE:
1004                     isRecordLoadResponse = false;
1005                     ar = (AsyncResult) msg.obj;
1006 
1007                     if (DBG) log("EVENT_SET_MBDN_DONE ex:" + ar.exception);
1008                     if (ar.exception == null) {
1009                         mVoiceMailNum = mNewVoiceMailNum;
1010                         mVoiceMailTag = mNewVoiceMailTag;
1011                     }
1012 
1013                     if (isCphsMailboxEnabled()) {
1014                         adn = new AdnRecord(mVoiceMailTag, mVoiceMailNum);
1015                         Message onCphsCompleted = (Message) ar.userObj;
1016 
1017                         /* write to cphs mailbox whenever it is available but
1018                         * we only need notify caller once if both updating are
1019                         * successful.
1020                         *
1021                         * so if set_mbdn successful, notify caller here and set
1022                         * onCphsCompleted to null
1023                         */
1024                         if (ar.exception == null && ar.userObj != null) {
1025                             AsyncResult.forMessage(((Message) ar.userObj)).exception = null;
1026                             ((Message) ar.userObj).sendToTarget();
1027 
1028                             if (DBG) log("Callback with MBDN successful.");
1029 
1030                             onCphsCompleted = null;
1031                         }
1032 
1033                         new AdnRecordLoader(mFh)
1034                                 .updateEF(adn, EF_MAILBOX_CPHS, EF_EXT1, 1, null,
1035                                 obtainMessage(EVENT_SET_CPHS_MAILBOX_DONE,
1036                                         onCphsCompleted));
1037                     } else {
1038                         if (ar.userObj != null) {
1039                             CarrierConfigManager configManager = (CarrierConfigManager)
1040                                     mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
1041                             if (ar.exception != null && configManager != null) {
1042                                 PersistableBundle b = configManager.getConfigForSubId(
1043                                         SubscriptionController.getInstance().getSubIdUsingPhoneId(
1044                                                 mParentApp.getPhoneId()));
1045                                 if (b != null && b.getBoolean(
1046                                         CarrierConfigManager.KEY_EDITABLE_VOICEMAIL_NUMBER_BOOL)) {
1047                                     // GsmCdmaPhone will store vm number on device
1048                                     // when IccVmNotSupportedException occurred
1049                                     AsyncResult.forMessage(((Message) ar.userObj)).exception =
1050                                             new IccVmNotSupportedException(
1051                                                     "Update SIM voice mailbox error");
1052                                 } else {
1053                                     AsyncResult.forMessage(((Message) ar.userObj))
1054                                             .exception = ar.exception;
1055                                 }
1056                             } else {
1057                                 AsyncResult.forMessage(((Message) ar.userObj))
1058                                     .exception = ar.exception;
1059                             }
1060                             ((Message) ar.userObj).sendToTarget();
1061                         }
1062                     }
1063                     break;
1064                 case EVENT_SET_CPHS_MAILBOX_DONE:
1065                     isRecordLoadResponse = false;
1066                     ar = (AsyncResult) msg.obj;
1067                     if (ar.exception == null) {
1068                         mVoiceMailNum = mNewVoiceMailNum;
1069                         mVoiceMailTag = mNewVoiceMailTag;
1070                     } else {
1071                         if (DBG) log("Set CPHS MailBox with exception: " + ar.exception);
1072                     }
1073                     if (ar.userObj != null) {
1074                         if (DBG) log("Callback with CPHS MB successful.");
1075                         AsyncResult.forMessage(((Message) ar.userObj)).exception
1076                                 = ar.exception;
1077                         ((Message) ar.userObj).sendToTarget();
1078                     }
1079                     break;
1080                 case EVENT_GET_CFIS_DONE:
1081                     isRecordLoadResponse = true;
1082 
1083                     ar = (AsyncResult) msg.obj;
1084                     data = (byte[]) ar.result;
1085 
1086                     if (ar.exception != null) {
1087                         mEfCfis = null;
1088                     } else {
1089                         log("EF_CFIS: " + IccUtils.bytesToHexString(data));
1090                         mEfCfis = data;
1091                     }
1092 
1093                     break;
1094 
1095                 case EVENT_GET_CSP_CPHS_DONE:
1096                     isRecordLoadResponse = true;
1097 
1098                     ar = (AsyncResult) msg.obj;
1099 
1100                     if (ar.exception != null) {
1101                         loge("Exception in fetching EF_CSP data " + ar.exception);
1102                         break;
1103                     }
1104 
1105                     data = (byte[]) ar.result;
1106 
1107                     log("EF_CSP: " + IccUtils.bytesToHexString(data));
1108                     handleEfCspData(data);
1109                     break;
1110 
1111                 case EVENT_GET_GID1_DONE:
1112                     isRecordLoadResponse = true;
1113 
1114                     ar = (AsyncResult) msg.obj;
1115                     data = (byte[]) ar.result;
1116 
1117                     if (ar.exception != null) {
1118                         loge("Exception in get GID1 " + ar.exception);
1119                         mGid1 = null;
1120                         break;
1121                     }
1122 
1123                     mGid1 = IccUtils.bytesToHexString(data);
1124 
1125                     log("GID1: " + mGid1);
1126 
1127                     break;
1128 
1129                 case EVENT_GET_GID2_DONE:
1130                     isRecordLoadResponse = true;
1131                     ar = (AsyncResult) msg.obj;
1132                     data = (byte[]) ar.result;
1133 
1134                     if (ar.exception != null) {
1135                         loge("Exception in get GID2 " + ar.exception);
1136                         mGid2 = null;
1137                         break;
1138                     }
1139 
1140                     mGid2 = IccUtils.bytesToHexString(data);
1141 
1142                     log("GID2: " + mGid2);
1143 
1144                     break;
1145 
1146                 case EVENT_GET_PLMN_W_ACT_DONE:
1147                     isRecordLoadResponse = true;
1148                     ar = (AsyncResult) msg.obj;
1149                     data = (byte[]) ar.result;
1150 
1151                     if (ar.exception != null || data == null) {
1152                         loge("Failed getting User PLMN with Access Tech Records: " + ar.exception);
1153                         break;
1154                     } else {
1155                         log("Received a PlmnActRecord, raw=" + IccUtils.bytesToHexString(data));
1156                         mPlmnActRecords = PlmnActRecord.getRecords(data);
1157                         if (VDBG) log("PlmnActRecords=" + Arrays.toString(mPlmnActRecords));
1158                     }
1159                     break;
1160 
1161                 case EVENT_GET_OPLMN_W_ACT_DONE:
1162                     isRecordLoadResponse = true;
1163                     ar = (AsyncResult) msg.obj;
1164                     data = (byte[]) ar.result;
1165 
1166                     if (ar.exception != null || data == null) {
1167                         loge("Failed getting Operator PLMN with Access Tech Records: "
1168                                 + ar.exception);
1169                         break;
1170                     } else {
1171                         log("Received a PlmnActRecord, raw=" + IccUtils.bytesToHexString(data));
1172                         mOplmnActRecords = PlmnActRecord.getRecords(data);
1173                         if (VDBG) log("OplmnActRecord[]=" + Arrays.toString(mOplmnActRecords));
1174                     }
1175                     break;
1176 
1177                 case EVENT_GET_HPLMN_W_ACT_DONE:
1178                     isRecordLoadResponse = true;
1179                     ar = (AsyncResult) msg.obj;
1180                     data = (byte[]) ar.result;
1181 
1182                     if (ar.exception != null || data == null) {
1183                         loge("Failed getting Home PLMN with Access Tech Records: " + ar.exception);
1184                         break;
1185                     } else {
1186                         log("Received a PlmnActRecord, raw=" + IccUtils.bytesToHexString(data));
1187                         mHplmnActRecords = PlmnActRecord.getRecords(data);
1188                         log("HplmnActRecord[]=" + Arrays.toString(mHplmnActRecords));
1189                     }
1190                     break;
1191 
1192                 case EVENT_GET_EHPLMN_DONE:
1193                     isRecordLoadResponse = true;
1194                     ar = (AsyncResult) msg.obj;
1195                     data = (byte[]) ar.result;
1196                     if (ar.exception != null || data == null) {
1197                         loge("Failed getting Equivalent Home PLMNs: " + ar.exception);
1198                         break;
1199                     } else {
1200                         mEhplmns = parseBcdPlmnList(data, "Equivalent Home");
1201                     }
1202                     break;
1203 
1204                 case EVENT_GET_FPLMN_DONE:
1205                     isRecordLoadResponse = true;
1206                     ar = (AsyncResult) msg.obj;
1207                     data = (byte[]) ar.result;
1208                     if (ar.exception != null || data == null) {
1209                         loge("Failed getting Forbidden PLMNs: " + ar.exception);
1210                     } else {
1211                         mFplmns = parseBcdPlmnList(data, "Forbidden");
1212                     }
1213                     if (msg.arg1 == HANDLER_ACTION_SEND_RESPONSE) {
1214                         if (VDBG) logv("getForbiddenPlmns(): send async response");
1215                         isRecordLoadResponse = false;
1216                         int key = msg.arg2;
1217                         Message response = retrievePendingTransaction(key).first;
1218                         if (response != null) {
1219                             if (ar.exception == null && data != null && mFplmns != null) {
1220                                 AsyncResult.forMessage(response, Arrays.copyOf(mFplmns,
1221                                         mFplmns.length), null);
1222                             } else {
1223                                 AsyncResult.forMessage(response, null, ar.exception);
1224                             }
1225                             response.sendToTarget();
1226                         } else {
1227                             loge("Failed to retrieve a response message for FPLMN");
1228                             break;
1229                         }
1230                     }
1231                     break;
1232 
1233                 case EVENT_GET_FPLMN_SIZE_DONE:
1234                     ar = (AsyncResult) msg.obj;
1235                     if (ar.exception != null) {
1236                         Message response = (Message) ar.userObj;
1237                         AsyncResult.forMessage(response).exception = ar.exception;
1238                         response.sendToTarget();
1239                         break;
1240                     }
1241                     int key = msg.arg2;
1242                     Pair<Message, Object> transaction = retrievePendingTransaction(key);
1243                     Message response = transaction.first;
1244                     List<String> fplmns = (List<String>) transaction.second;
1245                     int dataLength = (int) ar.result;
1246                     if (dataLength < 0 || dataLength % FPLMN_BYTE_SIZE != 0) {
1247                         loge("Failed to retrieve a correct fplmn size: " + dataLength);
1248                         AsyncResult.forMessage(response, -1, null);
1249                         response.sendToTarget();
1250                         break;
1251                     }
1252 
1253                     int maxWritebaleFplmns = dataLength / FPLMN_BYTE_SIZE;
1254                     List<String> fplmnsToWrite;
1255                     if (fplmns.size() <= maxWritebaleFplmns) {
1256                         fplmnsToWrite = fplmns;
1257                     } else {
1258                         fplmnsToWrite = fplmns.subList(0, maxWritebaleFplmns);
1259                     }
1260                     key = storePendingTransaction(response, fplmnsToWrite);
1261                     byte[] encodededFplmns = IccUtils.encodeFplmns(fplmns, dataLength);
1262                     mFh.updateEFTransparent(
1263                             EF_FPLMN,
1264                             encodededFplmns,
1265                             obtainMessage(
1266                                     EVENT_SET_FPLMN_DONE,
1267                                     msg.arg1,
1268                                     key));
1269                     break;
1270 
1271                 case EVENT_SET_FPLMN_DONE:
1272                     ar = (AsyncResult) msg.obj;
1273                     if (ar.exception != null) {
1274                         loge("Failed setting Forbidden PLMNs: " + ar.exception);
1275                     } else {
1276                         transaction = retrievePendingTransaction(msg.arg2);
1277                         response = transaction.first;
1278                         mFplmns = ((List<String>) transaction.second).toArray(new String[0]);
1279                         if (msg.arg1 == HANDLER_ACTION_SEND_RESPONSE) {
1280                             AsyncResult.forMessage(response, mFplmns.length, null);
1281                             response.sendToTarget();
1282                         }
1283                         log("Successfully setted fplmns " + ar.result);
1284                     }
1285                     break;
1286 
1287                 default:
1288                     super.handleMessage(msg);   // IccRecords handles generic record load responses
1289             }
1290         } catch (RuntimeException exc) {
1291             // I don't want these exceptions to be fatal
1292             logw("Exception parsing SIM record", exc);
1293         } finally {
1294             // Count up record load responses even if they are fails
1295             if (isRecordLoadResponse) {
1296                 onRecordLoaded();
1297             }
1298         }
1299     }
1300 
1301     private class EfPlLoaded implements IccRecordLoaded {
getEfName()1302         public String getEfName() {
1303             return "EF_PL";
1304         }
1305 
onRecordLoaded(AsyncResult ar)1306         public void onRecordLoaded(AsyncResult ar) {
1307             mEfPl = (byte[]) ar.result;
1308             if (DBG) log("EF_PL=" + IccUtils.bytesToHexString(mEfPl));
1309         }
1310     }
1311 
1312     private class EfUsimLiLoaded implements IccRecordLoaded {
getEfName()1313         public String getEfName() {
1314             return "EF_LI";
1315         }
1316 
onRecordLoaded(AsyncResult ar)1317         public void onRecordLoaded(AsyncResult ar) {
1318             mEfLi = (byte[]) ar.result;
1319             if (DBG) log("EF_LI=" + IccUtils.bytesToHexString(mEfLi));
1320         }
1321     }
1322 
1323     @Override
handleFileUpdate(int efid)1324     protected void handleFileUpdate(int efid) {
1325         switch(efid) {
1326             case EF_MBDN:
1327                 mRecordsToLoad++;
1328                 new AdnRecordLoader(mFh).loadFromEF(EF_MBDN, EF_EXT6,
1329                         mMailboxIndex, obtainMessage(EVENT_GET_MBDN_DONE));
1330                 break;
1331             case EF_MAILBOX_CPHS:
1332                 mRecordsToLoad++;
1333                 new AdnRecordLoader(mFh).loadFromEF(EF_MAILBOX_CPHS, EF_EXT1,
1334                         1, obtainMessage(EVENT_GET_CPHS_MAILBOX_DONE));
1335                 break;
1336             case EF_CSP_CPHS:
1337                 mRecordsToLoad++;
1338                 log("[CSP] SIM Refresh for EF_CSP_CPHS");
1339                 mFh.loadEFTransparent(EF_CSP_CPHS,
1340                         obtainMessage(EVENT_GET_CSP_CPHS_DONE));
1341                 break;
1342             case EF_FDN:
1343                 if (DBG) log("SIM Refresh called for EF_FDN");
1344                 mParentApp.queryFdn();
1345                 mAdnCache.reset();
1346                 break;
1347             case EF_MSISDN:
1348                 mRecordsToLoad++;
1349                 log("SIM Refresh called for EF_MSISDN");
1350                 new AdnRecordLoader(mFh).loadFromEF(EF_MSISDN, getExtFromEf(EF_MSISDN), 1,
1351                         obtainMessage(EVENT_GET_MSISDN_DONE));
1352                 break;
1353             case EF_CFIS:
1354             case EF_CFF_CPHS:
1355                 log("SIM Refresh called for EF_CFIS or EF_CFF_CPHS");
1356                 loadCallForwardingRecords();
1357                 break;
1358             default:
1359                 // For now, fetch all records if this is not a
1360                 // voicemail number.
1361                 // TODO: Handle other cases, instead of fetching all.
1362                 mLoaded.set(false);
1363                 mAdnCache.reset();
1364                 fetchSimRecords();
1365                 break;
1366         }
1367     }
1368 
1369     /**
1370      * Dispatch 3GPP format message to registrant ({@code GsmCdmaPhone}) to pass to the 3GPP SMS
1371      * dispatcher for delivery.
1372      */
dispatchGsmMessage(SmsMessage message)1373     private void dispatchGsmMessage(SmsMessage message) {
1374         mNewSmsRegistrants.notifyResult(message);
1375     }
1376 
handleSms(byte[] ba)1377     private void handleSms(byte[] ba) {
1378         if (DBG) log("handleSms status : " + ba[0]);
1379 
1380         // ba[0] is status byte. (see 3GPP TS 51.011 10.5.3)
1381         if ((ba[0] & 0x07) == STATUS_ON_ICC_UNREAD) {
1382             int n = ba.length;
1383 
1384             // Note: Data may include trailing FF's. That's OK; message
1385             // should still parse correctly.
1386             byte[] pdu = new byte[n - 1];
1387             System.arraycopy(ba, 1, pdu, 0, n - 1);
1388             SmsMessage message = SmsMessage.createFromPdu(pdu, SmsConstants.FORMAT_3GPP);
1389 
1390             dispatchGsmMessage(message);
1391         }
1392     }
1393 
handleSmses(ArrayList<byte[]> messages)1394     private void handleSmses(ArrayList<byte[]> messages) {
1395         int count = messages.size();
1396 
1397         for (int i = 0; i < count; i++) {
1398             byte[] ba = messages.get(i);
1399 
1400             if (DBG) log("handleSmses status " + i + ": " + ba[0]);
1401 
1402             // ba[0] is status byte. (see 3GPP TS 51.011 10.5.3)
1403             if ((ba[0] & 0x07) == STATUS_ON_ICC_UNREAD) {
1404                 int n = ba.length;
1405 
1406                 // Note: Data may include trailing FF's. That's OK; message
1407                 // should still parse correctly.
1408                 byte[] pdu = new byte[n - 1];
1409                 System.arraycopy(ba, 1, pdu, 0, n - 1);
1410                 SmsMessage message = SmsMessage.createFromPdu(pdu, SmsConstants.FORMAT_3GPP);
1411 
1412                 dispatchGsmMessage(message);
1413 
1414                 ba[0] = (byte) STATUS_ON_ICC_READ;
1415 
1416                 if (false) { // FIXME: writing seems to crash RdoServD
1417                     mFh.updateEFLinearFixed(EF_SMS,
1418                             i, ba, null, obtainMessage(EVENT_MARK_SMS_READ_DONE, i));
1419                 }
1420             }
1421         }
1422     }
1423 
1424     @Override
onRecordLoaded()1425     protected void onRecordLoaded() {
1426         // One record loaded successfully or failed, In either case
1427         // we need to update the recordsToLoad count
1428         mRecordsToLoad -= 1;
1429         if (DBG) log("onRecordLoaded " + mRecordsToLoad + " requested: " + mRecordsRequested);
1430 
1431         if (getRecordsLoaded()) {
1432             onAllRecordsLoaded();
1433         } else if (getLockedRecordsLoaded() || getNetworkLockedRecordsLoaded()) {
1434             onLockedAllRecordsLoaded();
1435         } else if (mRecordsToLoad < 0) {
1436             loge("recordsToLoad <0, programmer error suspected");
1437             mRecordsToLoad = 0;
1438         }
1439     }
1440 
setVoiceCallForwardingFlagFromSimRecords()1441     private void setVoiceCallForwardingFlagFromSimRecords() {
1442         if (validEfCfis(mEfCfis)) {
1443             // Refer TS 51.011 Section 10.3.46 for the content description
1444             mCallForwardingStatus = (mEfCfis[1] & 0x01);
1445             log("EF_CFIS: callForwardingEnabled=" + mCallForwardingStatus);
1446         } else if (mEfCff != null) {
1447             mCallForwardingStatus =
1448                     ((mEfCff[0] & CFF_LINE1_MASK) == CFF_UNCONDITIONAL_ACTIVE) ?
1449                             CALL_FORWARDING_STATUS_ENABLED : CALL_FORWARDING_STATUS_DISABLED;
1450             log("EF_CFF: callForwardingEnabled=" + mCallForwardingStatus);
1451         } else {
1452             mCallForwardingStatus = CALL_FORWARDING_STATUS_UNKNOWN;
1453             log("EF_CFIS and EF_CFF not valid. callForwardingEnabled=" + mCallForwardingStatus);
1454         }
1455     }
1456 
setSimLanguageFromEF()1457     private void setSimLanguageFromEF() {
1458         Resources resource = Resources.getSystem();
1459         if (resource.getBoolean(com.android.internal.R.bool.config_use_sim_language_file)) {
1460             setSimLanguage(mEfLi, mEfPl);
1461         } else {
1462             if (DBG) log ("Not using EF LI/EF PL");
1463         }
1464     }
1465 
onLockedAllRecordsLoaded()1466     private void onLockedAllRecordsLoaded() {
1467         setSimLanguageFromEF();
1468         setVoiceCallForwardingFlagFromSimRecords();
1469         if (mLockedRecordsReqReason == LOCKED_RECORDS_REQ_REASON_LOCKED) {
1470             mLockedRecordsLoadedRegistrants.notifyRegistrants(new AsyncResult(null, null, null));
1471         } else if (mLockedRecordsReqReason == LOCKED_RECORDS_REQ_REASON_NETWORK_LOCKED) {
1472             mNetworkLockedRecordsLoadedRegistrants.notifyRegistrants(
1473                     new AsyncResult(null, null, null));
1474         } else {
1475             loge("onLockedAllRecordsLoaded: unexpected mLockedRecordsReqReason "
1476                     + mLockedRecordsReqReason);
1477         }
1478     }
1479 
1480     @Override
onAllRecordsLoaded()1481     protected void onAllRecordsLoaded() {
1482         if (DBG) log("record load complete");
1483 
1484         setSimLanguageFromEF();
1485         setVoiceCallForwardingFlagFromSimRecords();
1486 
1487         // Some fields require more than one SIM record to set
1488 
1489         String operator = getOperatorNumeric();
1490         if (!TextUtils.isEmpty(operator)) {
1491             log("onAllRecordsLoaded set 'gsm.sim.operator.numeric' to operator='" +
1492                     operator + "'");
1493             mTelephonyManager.setSimOperatorNumericForPhone(
1494                     mParentApp.getPhoneId(), operator);
1495         } else {
1496             log("onAllRecordsLoaded empty 'gsm.sim.operator.numeric' skipping");
1497         }
1498 
1499         String imsi = getIMSI();
1500 
1501         if (!TextUtils.isEmpty(imsi) && imsi.length() >= 3) {
1502             log("onAllRecordsLoaded set mcc imsi" + (VDBG ? ("=" + imsi) : ""));
1503             mTelephonyManager.setSimCountryIsoForPhone(
1504                     mParentApp.getPhoneId(), MccTable.countryCodeForMcc(imsi.substring(0, 3)));
1505         } else {
1506             log("onAllRecordsLoaded empty imsi skipping setting mcc");
1507         }
1508 
1509         setVoiceMailByCountry(operator);
1510         mLoaded.set(true);
1511         mRecordsLoadedRegistrants.notifyRegistrants(new AsyncResult(null, null, null));
1512     }
1513 
1514     //***** Private methods
1515 
setVoiceMailByCountry(String spn)1516     private void setVoiceMailByCountry (String spn) {
1517         if (mVmConfig.containsCarrier(spn)) {
1518             mIsVoiceMailFixed = true;
1519             mVoiceMailNum = mVmConfig.getVoiceMailNumber(spn);
1520             mVoiceMailTag = mVmConfig.getVoiceMailTag(spn);
1521         }
1522     }
1523 
1524     /**
1525      * String[] of forbidden PLMNs will be sent to the Message's handler
1526      * in the result field of an AsyncResult in the response.obj.
1527      */
getForbiddenPlmns(Message response)1528     public void getForbiddenPlmns(Message response) {
1529         int key = storePendingTransaction(response);
1530         mFh.loadEFTransparent(EF_FPLMN, obtainMessage(
1531                     EVENT_GET_FPLMN_DONE, HANDLER_ACTION_SEND_RESPONSE, key));
1532     }
1533 
1534     /**
1535      * Set the forbidden PLMNs on the sim
1536      *
1537      * @param response Response to be send back.
1538      * @param fplmns List of fplmns to be written to SIM.
1539      */
setForbiddenPlmns(Message response, List<String> fplmns)1540     public void setForbiddenPlmns(Message response, List<String> fplmns) {
1541         int key = storePendingTransaction(response, fplmns);
1542         mFh.getEFTransparentRecordSize(
1543                 EF_FPLMN,
1544                 obtainMessage(EVENT_GET_FPLMN_SIZE_DONE, HANDLER_ACTION_SEND_RESPONSE, key));
1545     }
1546 
1547 
1548     @Override
onReady()1549     public void onReady() {
1550         fetchSimRecords();
1551     }
1552 
1553     @Override
onLocked()1554     protected void onLocked() {
1555         if (DBG) log("only fetch EF_LI, EF_PL and EF_ICCID in locked state");
1556         super.onLocked();
1557 
1558         loadEfLiAndEfPl();
1559 
1560         mFh.loadEFTransparent(EF_ICCID, obtainMessage(EVENT_GET_ICCID_DONE));
1561         mRecordsToLoad++;
1562     }
1563 
loadEfLiAndEfPl()1564     private void loadEfLiAndEfPl() {
1565         if (mParentApp.getType() == AppType.APPTYPE_USIM) {
1566             mFh.loadEFTransparent(EF_LI,
1567                     obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfUsimLiLoaded()));
1568             mRecordsToLoad++;
1569 
1570             mFh.loadEFTransparent(EF_PL,
1571                     obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfPlLoaded()));
1572             mRecordsToLoad++;
1573         }
1574     }
1575 
loadCallForwardingRecords()1576     private void loadCallForwardingRecords() {
1577         mRecordsRequested = true;
1578         mFh.loadEFLinearFixed(EF_CFIS, 1, obtainMessage(EVENT_GET_CFIS_DONE));
1579         mRecordsToLoad++;
1580         mFh.loadEFTransparent(EF_CFF_CPHS, obtainMessage(EVENT_GET_CFF_DONE));
1581         mRecordsToLoad++;
1582     }
1583 
1584     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
fetchSimRecords()1585     protected void fetchSimRecords() {
1586         mRecordsRequested = true;
1587 
1588         if (DBG) log("fetchSimRecords " + mRecordsToLoad);
1589 
1590         mCi.getIMSIForApp(mParentApp.getAid(), obtainMessage(EVENT_GET_IMSI_DONE));
1591         mRecordsToLoad++;
1592 
1593         mFh.loadEFTransparent(EF_ICCID, obtainMessage(EVENT_GET_ICCID_DONE));
1594         mRecordsToLoad++;
1595 
1596         // FIXME should examine EF[MSISDN]'s capability configuration
1597         // to determine which is the voice/data/fax line
1598         new AdnRecordLoader(mFh).loadFromEF(EF_MSISDN, getExtFromEf(EF_MSISDN), 1,
1599                     obtainMessage(EVENT_GET_MSISDN_DONE));
1600         mRecordsToLoad++;
1601 
1602         // Record number is subscriber profile
1603         mFh.loadEFLinearFixed(EF_MBI, 1, obtainMessage(EVENT_GET_MBI_DONE));
1604         mRecordsToLoad++;
1605 
1606         mFh.loadEFTransparent(EF_AD, obtainMessage(EVENT_GET_AD_DONE));
1607         mRecordsToLoad++;
1608 
1609         // Record number is subscriber profile
1610         mFh.loadEFLinearFixed(EF_MWIS, 1, obtainMessage(EVENT_GET_MWIS_DONE));
1611         mRecordsToLoad++;
1612 
1613 
1614         // Also load CPHS-style voice mail indicator, which stores
1615         // the same info as EF[MWIS]. If both exist, both are updated
1616         // but the EF[MWIS] data is preferred
1617         // Please note this must be loaded after EF[MWIS]
1618         mFh.loadEFTransparent(
1619                 EF_VOICE_MAIL_INDICATOR_CPHS,
1620                 obtainMessage(EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE));
1621         mRecordsToLoad++;
1622 
1623         // Same goes for Call Forward Status indicator: fetch both
1624         // EF[CFIS] and CPHS-EF, with EF[CFIS] preferred.
1625         loadCallForwardingRecords();
1626 
1627         getSpnFsm(true, null);
1628 
1629         mFh.loadEFTransparent(EF_SPDI, obtainMessage(EVENT_GET_SPDI_DONE));
1630         mRecordsToLoad++;
1631 
1632         mFh.loadEFLinearFixedAll(EF_PNN, obtainMessage(EVENT_GET_PNN_DONE));
1633         mRecordsToLoad++;
1634 
1635         mFh.loadEFLinearFixedAll(EF_OPL, obtainMessage(EVENT_GET_OPL_DONE));
1636         mRecordsToLoad++;
1637 
1638         mFh.loadEFTransparent(EF_SST, obtainMessage(EVENT_GET_SST_DONE));
1639         mRecordsToLoad++;
1640 
1641         mFh.loadEFTransparent(EF_INFO_CPHS, obtainMessage(EVENT_GET_INFO_CPHS_DONE));
1642         mRecordsToLoad++;
1643 
1644         mFh.loadEFTransparent(EF_CSP_CPHS,obtainMessage(EVENT_GET_CSP_CPHS_DONE));
1645         mRecordsToLoad++;
1646 
1647         mFh.loadEFTransparent(EF_GID1, obtainMessage(EVENT_GET_GID1_DONE));
1648         mRecordsToLoad++;
1649 
1650         mFh.loadEFTransparent(EF_GID2, obtainMessage(EVENT_GET_GID2_DONE));
1651         mRecordsToLoad++;
1652 
1653         mFh.loadEFTransparent(EF_PLMN_W_ACT, obtainMessage(EVENT_GET_PLMN_W_ACT_DONE));
1654         mRecordsToLoad++;
1655 
1656         mFh.loadEFTransparent(EF_OPLMN_W_ACT, obtainMessage(EVENT_GET_OPLMN_W_ACT_DONE));
1657         mRecordsToLoad++;
1658 
1659         mFh.loadEFTransparent(EF_HPLMN_W_ACT, obtainMessage(EVENT_GET_HPLMN_W_ACT_DONE));
1660         mRecordsToLoad++;
1661 
1662         mFh.loadEFTransparent(EF_EHPLMN, obtainMessage(EVENT_GET_EHPLMN_DONE));
1663         mRecordsToLoad++;
1664 
1665         mFh.loadEFTransparent(EF_FPLMN, obtainMessage(
1666                     EVENT_GET_FPLMN_DONE, HANDLER_ACTION_NONE, -1));
1667         mRecordsToLoad++;
1668 
1669         loadEfLiAndEfPl();
1670         mFh.getEFLinearRecordSize(EF_SMS, obtainMessage(EVENT_GET_SMS_RECORD_SIZE_DONE));
1671         mRecordsToLoad++;
1672 
1673         // XXX should seek instead of examining them all
1674         if (false) { // XXX
1675             mFh.loadEFLinearFixedAll(EF_SMS, obtainMessage(EVENT_GET_ALL_SMS_DONE));
1676             mRecordsToLoad++;
1677         }
1678 
1679         if (CRASH_RIL) {
1680             String sms = "0107912160130310f20404d0110041007030208054832b0120"
1681                          + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
1682                          + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
1683                          + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
1684                          + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
1685                          + "ffffffffffffffffffffffffffffff";
1686             byte[] ba = IccUtils.hexStringToBytes(sms);
1687 
1688             mFh.updateEFLinearFixed(EF_SMS, 1, ba, null,
1689                             obtainMessage(EVENT_MARK_SMS_READ_DONE, 1));
1690         }
1691         if (DBG) log("fetchSimRecords " + mRecordsToLoad + " requested: " + mRecordsRequested);
1692     }
1693 
1694     @Override
1695     @CarrierNameDisplayConditionBitmask
getCarrierNameDisplayCondition()1696     public int getCarrierNameDisplayCondition() {
1697         return mCarrierNameDisplayCondition;
1698     }
1699 
1700     /**
1701      * States of Get SPN Finite State Machine which only used by getSpnFsm()
1702      */
1703     @UnsupportedAppUsage(implicitMember =
1704             "values()[Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;")
1705     private enum GetSpnFsmState {
1706         IDLE,               // No initialized
1707         @UnsupportedAppUsage
1708         INIT,               // Start FSM
1709         @UnsupportedAppUsage
1710         READ_SPN_3GPP,      // Load EF_SPN firstly
1711         @UnsupportedAppUsage
1712         READ_SPN_CPHS,      // Load EF_SPN_CPHS secondly
1713         @UnsupportedAppUsage
1714         READ_SPN_SHORT_CPHS // Load EF_SPN_SHORT_CPHS last
1715     }
1716 
1717     /**
1718      * Finite State Machine to load Service Provider Name , which can be stored
1719      * in either EF_SPN (3GPP), EF_SPN_CPHS, or EF_SPN_SHORT_CPHS (CPHS4.2)
1720      *
1721      * After starting, FSM will search SPN EFs in order and stop after finding
1722      * the first valid SPN
1723      *
1724      * If the FSM gets restart while waiting for one of
1725      * SPN EFs results (i.e. a SIM refresh occurs after issuing
1726      * read EF_CPHS_SPN), it will re-initialize only after
1727      * receiving and discarding the unfinished SPN EF result.
1728      *
1729      * @param start set true only for initialize loading
1730      * @param ar the AsyncResult from loadEFTransparent
1731      *        ar.exception holds exception in error
1732      *        ar.result is byte[] for data in success
1733      */
1734     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getSpnFsm(boolean start, AsyncResult ar)1735     private void getSpnFsm(boolean start, AsyncResult ar) {
1736         byte[] data;
1737 
1738         if (start) {
1739             // Check previous state to see if there is outstanding
1740             // SPN read
1741             if (mSpnState == GetSpnFsmState.READ_SPN_3GPP
1742                     || mSpnState == GetSpnFsmState.READ_SPN_CPHS
1743                     || mSpnState == GetSpnFsmState.READ_SPN_SHORT_CPHS
1744                     || mSpnState == GetSpnFsmState.INIT) {
1745                 // Set INIT then return so the INIT code
1746                 // will run when the outstanding read done.
1747                 mSpnState = GetSpnFsmState.INIT;
1748                 return;
1749             } else {
1750                 mSpnState = GetSpnFsmState.INIT;
1751             }
1752         }
1753 
1754         switch(mSpnState){
1755             case INIT:
1756                 setServiceProviderName(null);
1757 
1758                 mFh.loadEFTransparent(EF_SPN,
1759                         obtainMessage(EVENT_GET_SPN_DONE));
1760                 mRecordsToLoad++;
1761 
1762                 mSpnState = GetSpnFsmState.READ_SPN_3GPP;
1763                 break;
1764             case READ_SPN_3GPP:
1765                 if (ar != null && ar.exception == null) {
1766                     data = (byte[]) ar.result;
1767 
1768                     // Reference: 3GPP TS 31.102 section 4.2.12 EF_SPN
1769                     // The first byte is display condition.
1770                     mCarrierNameDisplayCondition =
1771                             convertSpnDisplayConditionToBitmask(data[0] & 0xff);
1772 
1773                     setServiceProviderName(IccUtils.adnStringFieldToString(
1774                                 data, 1, data.length - 1));
1775                     // for card double-check and brand override
1776                     // we have to do this:
1777                     final String spn = getServiceProviderName();
1778 
1779                     if (spn == null || spn.length() == 0) {
1780                         mSpnState = GetSpnFsmState.READ_SPN_CPHS;
1781                     } else {
1782                         if (DBG) log("Load EF_SPN: " + spn
1783                                 + " carrierNameDisplayCondition: " + mCarrierNameDisplayCondition);
1784                         mTelephonyManager.setSimOperatorNameForPhone(
1785                                 mParentApp.getPhoneId(), spn);
1786 
1787                         mSpnState = GetSpnFsmState.IDLE;
1788                     }
1789                 } else {
1790                     mSpnState = GetSpnFsmState.READ_SPN_CPHS;
1791                 }
1792 
1793                 if (mSpnState == GetSpnFsmState.READ_SPN_CPHS) {
1794                     mFh.loadEFTransparent( EF_SPN_CPHS,
1795                             obtainMessage(EVENT_GET_SPN_DONE));
1796                     mRecordsToLoad++;
1797 
1798                     mCarrierNameDisplayCondition = DEFAULT_CARRIER_NAME_DISPLAY_CONDITION;
1799                 }
1800                 break;
1801             case READ_SPN_CPHS:
1802                 if (ar != null && ar.exception == null) {
1803                     data = (byte[]) ar.result;
1804 
1805                     setServiceProviderName(IccUtils.adnStringFieldToString(
1806                                 data, 0, data.length));
1807                     // for card double-check and brand override
1808                     // we have to do this:
1809                     final String spn = getServiceProviderName();
1810 
1811                     if (spn == null || spn.length() == 0) {
1812                         mSpnState = GetSpnFsmState.READ_SPN_SHORT_CPHS;
1813                     } else {
1814                         // Display CPHS Operator Name only when not roaming
1815                         mCarrierNameDisplayCondition = 0;
1816 
1817                         if (DBG) log("Load EF_SPN_CPHS: " + spn);
1818                         mTelephonyManager.setSimOperatorNameForPhone(
1819                                 mParentApp.getPhoneId(), spn);
1820 
1821                         mSpnState = GetSpnFsmState.IDLE;
1822                     }
1823                 } else {
1824                     mSpnState = GetSpnFsmState.READ_SPN_SHORT_CPHS;
1825                 }
1826 
1827                 if (mSpnState == GetSpnFsmState.READ_SPN_SHORT_CPHS) {
1828                     mFh.loadEFTransparent(
1829                             EF_SPN_SHORT_CPHS, obtainMessage(EVENT_GET_SPN_DONE));
1830                     mRecordsToLoad++;
1831                 }
1832                 break;
1833             case READ_SPN_SHORT_CPHS:
1834                 if (ar != null && ar.exception == null) {
1835                     data = (byte[]) ar.result;
1836 
1837                     setServiceProviderName(IccUtils.adnStringFieldToString(
1838                                 data, 0, data.length));
1839                     // for card double-check and brand override
1840                     // we have to do this:
1841                     final String spn = getServiceProviderName();
1842 
1843                     if (spn == null || spn.length() == 0) {
1844                         if (DBG) log("No SPN loaded in either CHPS or 3GPP");
1845                     } else {
1846                         // Display CPHS Operator Name only when not roaming
1847                         mCarrierNameDisplayCondition = 0;
1848 
1849                         if (DBG) log("Load EF_SPN_SHORT_CPHS: " + spn);
1850                         mTelephonyManager.setSimOperatorNameForPhone(
1851                                 mParentApp.getPhoneId(), spn);
1852                     }
1853                 } else {
1854                     setServiceProviderName(null);
1855                     if (DBG) log("No SPN loaded in either CHPS or 3GPP");
1856                 }
1857 
1858                 mSpnState = GetSpnFsmState.IDLE;
1859                 break;
1860             default:
1861                 mSpnState = GetSpnFsmState.IDLE;
1862         }
1863     }
1864 
1865     /**
1866      * Parse TS 51.011 EF[SPDI] record
1867      * This record contains the list of numeric network IDs that
1868      * are treated specially when determining SPN display
1869      */
parseEfSpdi(byte[] data)1870     private void parseEfSpdi(byte[] data) {
1871         SimTlv tlv = new SimTlv(data, 0, data.length);
1872 
1873         byte[] plmnEntries = null;
1874 
1875         for ( ; tlv.isValidObject() ; tlv.nextObject()) {
1876             // Skip SPDI tag, if existant
1877             if (tlv.getTag() == TAG_SPDI) {
1878               tlv = new SimTlv(tlv.getData(), 0, tlv.getData().length);
1879             }
1880             // There should only be one TAG_SPDI_PLMN_LIST
1881             if (tlv.getTag() == TAG_SPDI_PLMN_LIST) {
1882                 plmnEntries = tlv.getData();
1883                 break;
1884             }
1885         }
1886 
1887         if (plmnEntries == null) {
1888             return;
1889         }
1890 
1891         List<String> tmpSpdi = new ArrayList<>(plmnEntries.length / 3);
1892         for (int i = 0; i + 2 < plmnEntries.length; i += 3) {
1893             String plmnCode = IccUtils.bcdPlmnToString(plmnEntries, i);
1894             if (!TextUtils.isEmpty(plmnCode)) {
1895                 tmpSpdi.add(plmnCode);
1896             }
1897         }
1898         log("parseEfSpdi: " + tmpSpdi);
1899 
1900         mSpdi = tmpSpdi.toArray(new String[tmpSpdi.size()]);
1901     }
1902 
1903     /**
1904      * Parse EF PLMN Network Name (PNN) record from SIM
1905      * Reference: 3GPP TS 31.102 Section 4.2.58.
1906      */
parseEfPnn(ArrayList<byte[]> dataArray)1907     private void parseEfPnn(ArrayList<byte[]> dataArray) {
1908         if (dataArray == null) return;
1909 
1910         final int count = dataArray.size();
1911         List<PlmnNetworkName> tmpPnns = new ArrayList<>(count);
1912         for (int i = 0; i < count; i++) {
1913             byte[] data = dataArray.get(i);
1914             SimTlv tlv = new SimTlv(data, 0, data.length);
1915 
1916             String longName = null;
1917             String shortName = null;
1918             for (; tlv.isValidObject(); tlv.nextObject()) {
1919                 switch (tlv.getTag()) {
1920                     case TAG_FULL_NETWORK_NAME:
1921                         longName = IccUtils.networkNameToString(tlv.getData(), 0,
1922                                 tlv.getData().length);
1923                         break;
1924 
1925                     case TAG_SHORT_NETWORK_NAME:
1926                         shortName = IccUtils.networkNameToString(tlv.getData(), 0,
1927                                 tlv.getData().length);
1928                         break;
1929 
1930                     case TAG_PLMN_ADDITIONAL_INFORMATION:
1931                         // TODO(b/154300344): read PLMN Additional Information.
1932                         break;
1933                 }
1934             }
1935             // PNNs must maintain their original indices. They will be referred to by index in OPL.
1936             tmpPnns.add(new PlmnNetworkName(longName, shortName));
1937         }
1938         log("parseEfPnn: " + tmpPnns);
1939 
1940         mPnns = tmpPnns.toArray(new PlmnNetworkName[0]);
1941 
1942         // For compatiblility with legacy code.
1943         if (mPnns.length > 0) mPnnHomeName = mPnns[0].getName();
1944     }
1945 
1946     /**
1947      * Parse EF Operator PLMN List (OPL) record from SIM
1948      * Reference: 3GPP TS 31.102 Section 4.2.59.
1949      */
parseEfOpl(ArrayList<byte[]> dataArray)1950     private void parseEfOpl(ArrayList<byte[]> dataArray) {
1951         if (dataArray == null) return;
1952 
1953         final int count = dataArray.size();
1954         List<OperatorPlmnInfo> tmpOpl = new ArrayList<>(count);
1955         for (int i = 0; i < count; i++) {
1956             byte[] data = dataArray.get(i);
1957             // data.length is 8 as defined in 3GPP TS 31.102 Section 4.2.59.
1958             // Byte 0 to 2 are for PLMN.
1959             // Byte 3 and 4 are for lacTacStart.
1960             // Byte 5 and 6 are for lacTacEnd.
1961             // Byte 7 is for PNN Record Identifier.
1962             if (data.length != 8) {
1963                 loge("Invalid length for OPL record " + data);
1964                 continue;
1965             }
1966 
1967             // A BCD value of 'D' in any of the MCC and/or MNC digits shall be used to indicate
1968             // a "wild" value for that corresponding MCC/MNC digit.
1969             String plmn = IccUtils.bcdPlmnToString(data, 0);
1970             if (plmn.length() < PLMN_MIN_LENGTH) {
1971                 loge("Invalid length for decoded PLMN " + plmn);
1972                 continue;
1973             }
1974             int lacTacStart = IccUtils.bytesToInt(data, 3, 2);
1975             int lacTacEnd = IccUtils.bytesToInt(data, 5, 2);
1976             int pnnRecordId = IccUtils.bytesToInt(data, 7, 1);
1977 
1978             tmpOpl.add(new OperatorPlmnInfo(plmn, lacTacStart, lacTacEnd, pnnRecordId));
1979         }
1980         log("parseEfOpl: " + tmpOpl);
1981         mOpl = tmpOpl.toArray(new OperatorPlmnInfo[0]);
1982     }
1983 
1984     /**
1985      * convert a byte array of packed plmns to an array of strings
1986      */
parseBcdPlmnList(byte[] data, String description)1987     private String[] parseBcdPlmnList(byte[] data, String description) {
1988         final int packedBcdPlmnLenBytes = 3;
1989         log("Received " + description + " PLMNs, raw=" + IccUtils.bytesToHexString(data));
1990         if (data.length == 0 || (data.length % packedBcdPlmnLenBytes) != 0) {
1991             loge("Received invalid " + description + " PLMN list");
1992             return null;
1993         }
1994         int numPlmns = data.length / packedBcdPlmnLenBytes;
1995         int numValidPlmns = 0;
1996         String[] parsed = new String[numPlmns];
1997         for (int i = 0; i < numPlmns; i++) {
1998             parsed[numValidPlmns] = IccUtils.bcdPlmnToString(data, i * packedBcdPlmnLenBytes);
1999             // we count the valid (non empty) records and only increment if valid
2000             if (!TextUtils.isEmpty(parsed[numValidPlmns])) numValidPlmns++;
2001         }
2002         String[] ret = Arrays.copyOf(parsed, numValidPlmns);
2003         if (VDBG) logv(description + " PLMNs: " + Arrays.toString(ret));
2004         return ret;
2005     }
2006 
2007     /**
2008      * check to see if Mailbox Number is allocated and activated in CPHS SST
2009      */
2010     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
isCphsMailboxEnabled()2011     private boolean isCphsMailboxEnabled() {
2012         if (mCphsInfo == null)  return false;
2013         return ((mCphsInfo[1] & CPHS_SST_MBN_MASK) == CPHS_SST_MBN_ENABLED );
2014     }
2015 
2016     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2017     @Override
log(String s)2018     protected void log(String s) {
2019         if (mParentApp != null) {
2020             Rlog.d(LOG_TAG, "[SIMRecords-" + mParentApp.getPhoneId() + "] " + s);
2021         } else {
2022             Rlog.d(LOG_TAG, "[SIMRecords] " + s);
2023         }
2024     }
2025 
2026     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2027     @Override
loge(String s)2028     protected void loge(String s) {
2029         if (mParentApp != null) {
2030             Rlog.e(LOG_TAG, "[SIMRecords-" + mParentApp.getPhoneId() + "] " + s);
2031         } else {
2032             Rlog.e(LOG_TAG, "[SIMRecords] " + s);
2033         }
2034     }
2035 
logw(String s, Throwable tr)2036     protected void logw(String s, Throwable tr) {
2037         if (mParentApp != null) {
2038             Rlog.w(LOG_TAG, "[SIMRecords-" + mParentApp.getPhoneId() + "] " + s, tr);
2039         } else {
2040             Rlog.w(LOG_TAG, "[SIMRecords] " + s, tr);
2041         }
2042     }
2043 
2044     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
logv(String s)2045     protected void logv(String s) {
2046         if (mParentApp != null) {
2047             Rlog.v(LOG_TAG, "[SIMRecords-" + mParentApp.getPhoneId() + "] " + s);
2048         } else {
2049             Rlog.v(LOG_TAG, "[SIMRecords] " + s);
2050         }
2051     }
2052 
2053     /**
2054      * Return true if "Restriction of menu options for manual PLMN selection"
2055      * bit is set or EF_CSP data is unavailable, return false otherwise.
2056      */
2057     @Override
isCspPlmnEnabled()2058     public boolean isCspPlmnEnabled() {
2059         return mCspPlmnEnabled;
2060     }
2061 
2062     /**
2063      * Parse EF_CSP data and check if
2064      * "Restriction of menu options for manual PLMN selection" is
2065      * Enabled/Disabled
2066      *
2067      * @param data EF_CSP hex data.
2068      */
handleEfCspData(byte[] data)2069     private void handleEfCspData(byte[] data) {
2070         // As per spec CPHS4_2.WW6, CPHS B.4.7.1, EF_CSP contains CPHS defined
2071         // 18 bytes (i.e 9 service groups info) and additional data specific to
2072         // operator. The valueAddedServicesGroup is not part of standard
2073         // services. This is operator specific and can be programmed any where.
2074         // Normally this is programmed as 10th service after the standard
2075         // services.
2076         int usedCspGroups = data.length / 2;
2077         // This is the "Service Group Number" of "Value Added Services Group".
2078         byte valueAddedServicesGroup = (byte)0xC0;
2079 
2080         mCspPlmnEnabled = true;
2081         for (int i = 0; i < usedCspGroups; i++) {
2082              if (data[2 * i] == valueAddedServicesGroup) {
2083                  log("[CSP] found ValueAddedServicesGroup, value " + data[(2 * i) + 1]);
2084                  if ((data[(2 * i) + 1] & 0x80) == 0x80) {
2085                      // Bit 8 is for
2086                      // "Restriction of menu options for manual PLMN selection".
2087                      // Operator Selection menu should be enabled.
2088                      mCspPlmnEnabled = true;
2089                  } else {
2090                      mCspPlmnEnabled = false;
2091                      // Operator Selection menu should be disabled.
2092                      // Operator Selection Mode should be set to Automatic.
2093                      log("[CSP] Set Automatic Network Selection");
2094                      mNetworkSelectionModeAutomaticRegistrants.notifyRegistrants();
2095                  }
2096                  return;
2097              }
2098         }
2099 
2100         log("[CSP] Value Added Service Group (0xC0), not found!");
2101     }
2102 
2103     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)2104     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2105         pw.println("SIMRecords: " + this);
2106         pw.println(" extends:");
2107         super.dump(fd, pw, args);
2108         pw.println(" mVmConfig=" + mVmConfig);
2109         pw.println(" mCallForwardingStatus=" + mCallForwardingStatus);
2110         pw.println(" mSpnState=" + mSpnState);
2111         pw.println(" mCphsInfo=" + mCphsInfo);
2112         pw.println(" mCspPlmnEnabled=" + mCspPlmnEnabled);
2113         pw.println(" mEfMWIS[]=" + Arrays.toString(mEfMWIS));
2114         pw.println(" mEfCPHS_MWI[]=" + Arrays.toString(mEfCPHS_MWI));
2115         pw.println(" mEfCff[]=" + Arrays.toString(mEfCff));
2116         pw.println(" mEfCfis[]=" + Arrays.toString(mEfCfis));
2117         pw.println(" mCarrierNameDisplayCondition=" + mCarrierNameDisplayCondition);
2118         pw.println(" mSpdi[]=" + mSpdi);
2119         pw.println(" mUsimServiceTable=" + mUsimServiceTable);
2120         pw.println(" mGid1=" + mGid1);
2121         if (mCarrierTestOverride.isInTestMode()) {
2122             pw.println(" mFakeGid1=" + mCarrierTestOverride.getFakeGid1());
2123         }
2124         pw.println(" mGid2=" + mGid2);
2125         if (mCarrierTestOverride.isInTestMode()) {
2126             pw.println(" mFakeGid2=" + mCarrierTestOverride.getFakeGid2());
2127         }
2128         pw.println(" mPnnHomeName=" + mPnnHomeName);
2129         if (mCarrierTestOverride.isInTestMode()) {
2130             pw.println(" mFakePnnHomeName=" + mCarrierTestOverride.getFakePnnHomeName());
2131         }
2132         pw.println(" mPlmnActRecords[]=" + Arrays.toString(mPlmnActRecords));
2133         pw.println(" mOplmnActRecords[]=" + Arrays.toString(mOplmnActRecords));
2134         pw.println(" mHplmnActRecords[]=" + Arrays.toString(mHplmnActRecords));
2135         pw.println(" mFplmns[]=" + Arrays.toString(mFplmns));
2136         pw.println(" mEhplmns[]=" + Arrays.toString(mEhplmns));
2137         pw.flush();
2138     }
2139 }
2140