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