Loading src/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java +6 −7 Original line number Diff line number Diff line Loading @@ -166,6 +166,10 @@ public class IccPhoneBookInterfaceManager { return new AdnRecord(oldTag, oldPhoneNumber, oldEmailArray, oldAnrArray); } private AdnRecord generateAdnRecordWithNewTagByContentValues(ContentValues values) { return generateAdnRecordWithNewTagByContentValues(0, 0, values); } private AdnRecord generateAdnRecordWithNewTagByContentValues( int efId, int recordNumber, ContentValues values) { if (values == null) { Loading Loading @@ -215,14 +219,12 @@ public class IccPhoneBookInterfaceManager { synchronized (updateRequest) { Message response = mBaseHandler.obtainMessage(EVENT_UPDATE_DONE, updateRequest); AdnRecord oldAdn = generateAdnRecordWithOldTagByContentValues(values); AdnRecord newAdn = generateAdnRecordWithNewTagByContentValues(values); if (usesPbCache(efid)) { AdnRecord newAdn = generateAdnRecordWithNewTagByContentValues(IccConstants.EF_ADN, 0, values); mSimPbRecordCache.updateSimPbAdnBySearch(oldAdn, newAdn, response); waitForResult(updateRequest); return (boolean) updateRequest.mResult; } else { AdnRecord newAdn = generateAdnRecordWithNewTagByContentValues(efid, 0, values); if (mAdnCache != null) { mAdnCache.updateAdnBySearch(efid, oldAdn, newAdn, pin2, response); waitForResult(updateRequest); Loading Loading @@ -270,15 +272,12 @@ public class IccPhoneBookInterfaceManager { Request updateRequest = new Request(); synchronized (updateRequest) { Message response = mBaseHandler.obtainMessage(EVENT_UPDATE_DONE, updateRequest); AdnRecord newAdn = generateAdnRecordWithNewTagByContentValues(efid, index, values); if (usesPbCache(efid)) { AdnRecord newAdn = generateAdnRecordWithNewTagByContentValues(IccConstants.EF_ADN, index, values); mSimPbRecordCache.updateSimPbAdnByRecordId(index, newAdn, response); waitForResult(updateRequest); return (boolean) updateRequest.mResult; } else { AdnRecord newAdn = generateAdnRecordWithNewTagByContentValues(efid, index, values); if (mAdnCache != null) { mAdnCache.updateAdnByIndex(efid, newAdn, index, pin2, response); waitForResult(updateRequest); Loading src/java/com/android/internal/telephony/RILUtils.java +41 −6 Original line number Diff line number Diff line Loading @@ -4370,10 +4370,21 @@ public class RILUtils { */ public static android.hardware.radio.V1_6.PhonebookRecordInfo convertToHalPhonebookRecordInfo( SimPhonebookRecord record) { if(record != null) { return record.toPhonebookRecordInfo(); android.hardware.radio.V1_6.PhonebookRecordInfo pbRecordInfo = new android.hardware.radio.V1_6.PhonebookRecordInfo(); pbRecordInfo.recordId = record.getRecordIndex(); pbRecordInfo.name = convertNullToEmptyString(record.getAlphaTag()); pbRecordInfo.number = convertNullToEmptyString( convertToHalPhonebookRecordInfoNumber(record.getNumber())); if (record.getEmails() != null) { pbRecordInfo.emails = primitiveArrayToArrayList(record.getEmails()); } return null; if (record.getAdditionalNumbers() != null) { for (String addNum : record.getAdditionalNumbers()) { pbRecordInfo.additionalNumbers.add(convertToHalPhonebookRecordInfoNumber(addNum)); } } return pbRecordInfo; } /** Loading @@ -4383,10 +4394,34 @@ public class RILUtils { */ public static android.hardware.radio.sim.PhonebookRecordInfo convertToHalPhonebookRecordInfoAidl(SimPhonebookRecord record) { if(record != null) { return record.toPhonebookRecordInfoAidl(); android.hardware.radio.sim.PhonebookRecordInfo pbRecordInfo = new android.hardware.radio.sim.PhonebookRecordInfo(); pbRecordInfo.recordId = record.getRecordIndex(); pbRecordInfo.name = convertNullToEmptyString(record.getAlphaTag()); pbRecordInfo.number = convertNullToEmptyString( convertToHalPhonebookRecordInfoNumber(record.getNumber())); pbRecordInfo.emails = record.getEmails(); if (record.getAdditionalNumbers() != null) { String[] additionalNumbers = new String[record.getAdditionalNumbers().length]; for (int i = 0; i < additionalNumbers.length; i++) { additionalNumbers[i] = convertToHalPhonebookRecordInfoNumber(record.getAdditionalNumbers()[i]); } return null; pbRecordInfo.additionalNumbers = additionalNumbers; } return pbRecordInfo; } /** * Convert the GSM pause/wild/wait character to the phone number in the SIM PhonebookRecordInfo * number format * @param input GSM pause/wild/wait character * @return The converted PhonebookRecordInfo number */ private static String convertToHalPhonebookRecordInfoNumber(String input) { return input == null ? null : input.replace(PhoneNumberUtils.WAIT, 'e') .replace(PhoneNumberUtils.PAUSE, 'T') .replace(PhoneNumberUtils.WILD, '?'); } /** Loading src/java/com/android/internal/telephony/uicc/SimPhonebookRecord.java +17 −99 Original line number Diff line number Diff line Loading @@ -16,14 +16,12 @@ package com.android.internal.telephony.uicc; import android.hardware.radio.V1_6.PhonebookRecordInfo; import android.telephony.PhoneNumberUtils; import android.text.TextUtils; import com.android.internal.telephony.util.ArrayUtils; import java.util.Arrays; import java.util.ArrayList; /** * Represents a Phonebook entry from the SIM. Loading @@ -32,16 +30,15 @@ import java.util.ArrayList; */ public class SimPhonebookRecord { // Instance variables private int mRecordId = 0; private int mRecordIndex = 0; private String mAlphaTag; private String mNumber; private String[] mEmails; private String[] mAdditionalNumbers; // Instance methods public SimPhonebookRecord (int recordId, String alphaTag, String number, public SimPhonebookRecord (int recordIndex, String alphaTag, String number, String[] emails, String[] adNumbers) { mRecordId = recordId; mRecordIndex = recordIndex; mAlphaTag = alphaTag; mNumber = convertRecordFormatToNumber(number); mEmails = emails; Loading @@ -53,58 +50,8 @@ public class SimPhonebookRecord { } } public SimPhonebookRecord(PhonebookRecordInfo recInfo) { if (recInfo != null) { mRecordId = recInfo.recordId; mAlphaTag = recInfo.name; mNumber = recInfo.number; mEmails = recInfo.emails == null ? null : recInfo.emails.toArray(new String[recInfo.emails.size()]); mAdditionalNumbers = recInfo.additionalNumbers == null ? null : recInfo.additionalNumbers.toArray( new String[recInfo.additionalNumbers.size()]); } } public SimPhonebookRecord() {} public PhonebookRecordInfo toPhonebookRecordInfo() { PhonebookRecordInfo pbRecordInfo = new PhonebookRecordInfo(); pbRecordInfo.recordId = mRecordId; pbRecordInfo.name = convertNullToEmptyString(mAlphaTag); pbRecordInfo.number = convertNullToEmptyString(convertNumberToRecordFormat(mNumber)); if (mEmails != null) { pbRecordInfo.emails = new ArrayList<>(Arrays.asList(mEmails)); } if (mAdditionalNumbers != null) { for (String addNum : mAdditionalNumbers) { pbRecordInfo.additionalNumbers.add(convertNumberToRecordFormat(addNum)); } } return pbRecordInfo; } public android.hardware.radio.sim.PhonebookRecordInfo toPhonebookRecordInfoAidl() { android.hardware.radio.sim.PhonebookRecordInfo pbRecordInfo = new android.hardware.radio.sim.PhonebookRecordInfo(); pbRecordInfo.recordId = mRecordId; pbRecordInfo.name = convertNullToEmptyString(mAlphaTag); pbRecordInfo.number = convertNullToEmptyString(convertNumberToRecordFormat(mNumber)); if (mEmails != null) { pbRecordInfo.emails = mEmails; } if (mAdditionalNumbers != null) { String[] additionalNumbers = new String[mAdditionalNumbers.length]; for (int i = 0; i < additionalNumbers.length; i++) { additionalNumbers[i] = convertNumberToRecordFormat(mAdditionalNumbers[i]); } pbRecordInfo.additionalNumbers = additionalNumbers; } return pbRecordInfo; } public int getRecordId() { return mRecordId; public int getRecordIndex() { return mRecordIndex; } public String getAlphaTag() { Loading @@ -123,35 +70,15 @@ public class SimPhonebookRecord { return mAdditionalNumbers; } /** Convert null to an empty String */ private String convertNullToEmptyString(String str) { return str != null ? str : ""; } /** * Convert the SIM PhonebookRecordInfo number to the GSM pause/wild/wait number * @param input the SIM PhonebookRecordInfo number * @return The converted GSM pause/wild/wait number * convert phone number in the SIM phonebook record format to GSM pause/wild/wait character */ private String convertRecordFormatToNumber(String input) { private static String convertRecordFormatToNumber(String input) { return input == null ? null : input.replace( 'e', PhoneNumberUtils.WAIT ) .replace( 'T', PhoneNumberUtils.PAUSE ) .replace( '?', PhoneNumberUtils.WILD ); } /** * Convert the GSM pause/wild/wait characters to the phone number in the SIM PhonebookRecordInfo * number format * @param input GSM pause/wild/wait character * @return The converted PhonebookRecordInfo number */ private String convertNumberToRecordFormat(String input) { return input == null ? null : input.replace(PhoneNumberUtils.WAIT, 'e') .replace(PhoneNumberUtils.PAUSE, 'T') .replace(PhoneNumberUtils.WILD, '?'); } public boolean isEmpty() { return TextUtils.isEmpty(mAlphaTag) && TextUtils.isEmpty(mNumber) Loading @@ -162,8 +89,8 @@ public class SimPhonebookRecord { @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("SimPhoneBookRecord{").append("ID =") .append(mRecordId).append(", name = ") sb.append("SimPhoneBookRecord{").append("index =") .append(mRecordIndex).append(", name = ") .append(mAlphaTag == null ? "null" : mAlphaTag) .append(", number = ").append(mNumber == null ? "null" : mNumber) .append(", email count = ").append(mEmails == null ? 0 : mEmails.length) Loading @@ -176,28 +103,19 @@ public class SimPhonebookRecord { } public final static class Builder { private int mRecordId = 0; private int mRecordIndex = 0; private String mAlphaTag = null; private String mNumber = null; private String[] mEmails; private String[] mAdditionalNumbers; public SimPhonebookRecord build() { SimPhonebookRecord record = new SimPhonebookRecord(); record.mAlphaTag = mAlphaTag; record.mRecordId = mRecordId; record.mNumber = mNumber; if (mEmails != null) { record.mEmails = mEmails; } if (mAdditionalNumbers != null) { record.mAdditionalNumbers = mAdditionalNumbers; } return record; return new SimPhonebookRecord(mRecordIndex, mAlphaTag, mNumber, mEmails, mAdditionalNumbers); } public Builder setRecordId(int recordId) { mRecordId = recordId; public Builder setRecordIndex(int index) { mRecordIndex = index; return this; } Loading src/java/com/android/internal/telephony/uicc/SimPhonebookRecordCache.java +97 −97 Original line number Diff line number Diff line Loading @@ -29,16 +29,13 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.RadioInterfaceCapabilityController; import com.android.internal.telephony.uicc.AdnCapacity; import com.android.internal.telephony.uicc.IccConstants; import java.util.ArrayList; import java.util.Collections; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.ConcurrentSkipListMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.stream.Collectors; Loading @@ -59,9 +56,6 @@ public class SimPhonebookRecordCache extends Handler { // Instance Variables private String LOG_TAG = "SimPhonebookRecordCache"; private static final boolean DBG = true; @VisibleForTesting static final boolean ENABLE_INFLATE_WITH_EMPTY_RECORDS = true; // Event Constants private static final int EVENT_PHONEBOOK_CHANGED = 1; private static final int EVENT_PHONEBOOK_RECORDS_RECEIVED = 2; Loading @@ -73,7 +67,6 @@ public class SimPhonebookRecordCache extends Handler { private static final int MAX_RETRY_COUNT = 3; private static final int RETRY_INTERVAL = 3000; // 3S private static final int INVALID_RECORD_ID = -1; // member variables private final CommandsInterface mCi; Loading @@ -83,9 +76,9 @@ public class SimPhonebookRecordCache extends Handler { // Presenting ADN capacity, including ADN, EMAIL ANR, and so on. private AtomicReference<AdnCapacity> mAdnCapacity = new AtomicReference<AdnCapacity>(null); private Object mReadLock = new Object(); private final ConcurrentSkipListMap<Integer, AdnRecord> mSimPbRecords = new ConcurrentSkipListMap<Integer, AdnRecord>(); private final List<UpdateRequest> mUpdateRequests = private List<AdnRecord> mSimPbRecords = Collections.synchronizedList(new ArrayList<AdnRecord>()); private List<UpdateRequest> mUpdateRequests = Collections.synchronizedList(new ArrayList<UpdateRequest>()); // If true, clear the records in the cache and re-query from modem private AtomicBoolean mIsCacheInvalidated = new AtomicBoolean(false); Loading Loading @@ -155,9 +148,7 @@ public class SimPhonebookRecordCache extends Handler { synchronized (mReadLock) { for (Message response : mAdnLoadingWaiters){ if (response != null) { List<AdnRecord> result = new ArrayList<AdnRecord>(mSimPbRecords.values()); AsyncResult.forMessage(response, result, null); AsyncResult.forMessage(response).result = mSimPbRecords; response.sendToTarget(); } } Loading Loading @@ -248,14 +239,7 @@ public class SimPhonebookRecordCache extends Handler { @VisibleForTesting public List<AdnRecord> getAdnRecords() { return mSimPbRecords.values().stream().collect(Collectors.toList()); } @VisibleForTesting public void clear() { if (!ENABLE_INFLATE_WITH_EMPTY_RECORDS) { mSimPbRecords.clear(); } return mSimPbRecords; } private void notifyAdnLoadingWaiters() { Loading @@ -270,50 +254,68 @@ public class SimPhonebookRecordCache extends Handler { sendErrorResponse(response, "There is an invalid new Adn for update"); return; } boolean found = mSimPbRecords.containsKey(recordId); boolean found = false; int index = 0; for (Iterator<AdnRecord> it = mSimPbRecords.iterator(); it.hasNext();) { AdnRecord oldAdn = it.next(); ++index; if (oldAdn.getRecId() == recordId) { found = true; break; } } if (!found) { sendErrorResponse(response, "There is an invalid old Adn for update"); return; } updateSimPhonebookByNewAdn(recordId, newAdn, response); updateSimPhonebookByNewAdn(index, newAdn, response); } public void updateSimPbAdnBySearch(AdnRecord oldAdn, AdnRecord newAdn, Message response) { int index = -1; if ((oldAdn == null || oldAdn.isEmpty()) && !newAdn.isEmpty()) { // Add contact index = 0; } else { int count = 1; // Delete or update contact for (Iterator<AdnRecord> it = mSimPbRecords.iterator(); it.hasNext();) { if (oldAdn.isEqual(it.next())) { index = count; break; } count++; } } if (index == -1) { sendErrorResponse(response, "SIM Phonebook record don't exist for " + oldAdn); return; } if (newAdn == null) { sendErrorResponse(response, "There is an invalid new Adn for update"); return; } int recordId = INVALID_RECORD_ID; // The ID isn't specified by caller if (oldAdn != null && !oldAdn.isEmpty()) { for(AdnRecord adn : mSimPbRecords.values()) { if (oldAdn.isEqual(adn)) { recordId = adn.getRecId(); break; } } } if (recordId == INVALID_RECORD_ID && mAdnCapacity.get() != null && mAdnCapacity.get().isSimFull()) { if (index == 0 && mAdnCapacity.get() != null && mAdnCapacity.get().isSimFull()) { sendErrorResponse(response, "SIM Phonebook record is full"); return; } updateSimPhonebookByNewAdn(recordId, newAdn, response); updateSimPhonebookByNewAdn(index, newAdn, response); } private void updateSimPhonebookByNewAdn(int recordId, AdnRecord newAdn, Message response) { logd("update sim contact for record ID = " + recordId); final int updatingRecordId = recordId == INVALID_RECORD_ID ? 0 : recordId; private void updateSimPhonebookByNewAdn(int index, AdnRecord newAdn, Message response) { int recordIndex = (index == 0) ? newAdn.getRecId() : mSimPbRecords.get(index - 1).getRecId(); SimPhonebookRecord updateAdn = new SimPhonebookRecord.Builder() .setRecordId(updatingRecordId) .setRecordIndex(recordIndex) .setAlphaTag(newAdn.getAlphaTag()) .setNumber(newAdn.getNumber()) .setEmails(newAdn.getEmails()) .setAdditionalNumbers(newAdn.getAdditionalNumbers()) .build(); UpdateRequest updateRequest = new UpdateRequest(recordId, newAdn, updateAdn, response); UpdateRequest updateRequest = new UpdateRequest(index, newAdn, updateAdn, response); mUpdateRequests.add(updateRequest); final boolean isCapacityInvalid = isAdnCapacityInvalid(); if (isCapacityInvalid) { Loading Loading @@ -438,9 +440,8 @@ public class SimPhonebookRecordCache extends Handler { } mAdnCapacity.set(newCapacity); if (oldCapacity == null && newCapacity != null) { inflateWithEmptyRecords(newCapacity); if (!newCapacity.isSimEmpty()){ mIsCacheInvalidated.set(true); invalidateSimPbCache(); fillCacheWithoutWaiting(); } else { notifyAdnLoadingWaiters(); Loading @@ -460,18 +461,6 @@ public class SimPhonebookRecordCache extends Handler { } } private void inflateWithEmptyRecords(AdnCapacity capacity) { if (ENABLE_INFLATE_WITH_EMPTY_RECORDS) { logd("inflateWithEmptyRecords"); if (capacity != null && mSimPbRecords.isEmpty()) { for (int i = 1; i <= capacity.getMaxAdnCount(); i++) { mSimPbRecords.putIfAbsent(i, new AdnRecord(IccConstants.EF_ADN, i, null, null, null, null)); } } } } private void handlePhonebookRecordReceived(ReceivedPhonebookRecords records) { if (records != null) { if (records.isOk()) { Loading Loading @@ -505,20 +494,41 @@ public class SimPhonebookRecordCache extends Handler { UpdateRequest updateRequest = (UpdateRequest)ar.userObj; mIsUpdateDone = true; if (ar.exception == null) { int myRecordId = updateRequest.myRecordId; int index = updateRequest.index; AdnRecord adn = updateRequest.adnRecord; int recordId = ((int[]) (ar.result))[0]; logd("my record ID = " + myRecordId + " new record ID = " + recordId); if (myRecordId == INVALID_RECORD_ID || myRecordId == recordId) { if (!adn.isEmpty()) { addOrChangeSimPbRecord(adn, recordId); int recordIndex = ((int[]) (ar.result))[0]; if (index == 0) { // add contact addSimPbRecord(adn, recordIndex); } else if (adn.isEmpty()){ // delete contact AdnRecord deletedRecord = mSimPbRecords.get(index - 1); int adnRecordIndex = deletedRecord.getRecId(); logd("Record number for deleted ADN is " + adnRecordIndex); if(recordIndex == adnRecordIndex) { deleteSimPbRecord(index); } else { deleteSimPbRecord(recordId); e = new RuntimeException( "The index for deleted ADN record did not match"); } } else { e = new RuntimeException("The record ID for update doesn't match"); // Change contact if (mSimPbRecords.size() > index - 1) { AdnRecord oldRecord = mSimPbRecords.get(index - 1); int adnRecordIndex = oldRecord.getRecId(); logd("Record number for changed ADN is " + adnRecordIndex); if(recordIndex == adnRecordIndex) { updateSimPbRecord(adn, recordIndex, index); } else { e = new RuntimeException( "The index for changed ADN record did not match"); } } else { e = new RuntimeException( "The index for changed ADN record is out of the border"); } } } else { e = new RuntimeException("Update adn record failed", ar.exception); } Loading Loading @@ -554,15 +564,14 @@ public class SimPhonebookRecordCache extends Handler { private void populateAdnRecords(List<SimPhonebookRecord> records) { if (records != null) { Map<Integer, AdnRecord> newRecords = records.stream().map(record -> {return new AdnRecord(IccConstants.EF_ADN, record.getRecordId(), List<AdnRecord> newRecords = records.stream().map(record -> {return new AdnRecord(0, // PBR or ADN record.getRecordIndex(), record.getAlphaTag(), record.getNumber(), record.getEmails(), record.getAdditionalNumbers());}) .collect(Collectors.toMap(AdnRecord::getRecId, adn -> adn)); mSimPbRecords.putAll(newRecords); record.getAdditionalNumbers());}).collect(Collectors.toList()); mSimPbRecords.addAll(newRecords); } } Loading @@ -575,39 +584,30 @@ public class SimPhonebookRecordCache extends Handler { sendMessageDelayed(message, RETRY_INTERVAL); } private void addOrChangeSimPbRecord(AdnRecord record, int recordId) { logd("Record number for the added or changed ADN is " + recordId); record.setRecId(recordId); if (ENABLE_INFLATE_WITH_EMPTY_RECORDS) { mSimPbRecords.replace(recordId, record); } else { mSimPbRecords.put(recordId, record); } private void addSimPbRecord(AdnRecord addedRecord, int recordIndex) { logd("Record number for the added ADN is " + recordIndex); addedRecord.setRecId(recordIndex); mSimPbRecords.add(addedRecord); } private void deleteSimPbRecord(int recordId) { logd("Record number for the deleted ADN is " + recordId); if (ENABLE_INFLATE_WITH_EMPTY_RECORDS) { mSimPbRecords.replace(recordId, new AdnRecord(IccConstants.EF_ADN, recordId, null, null, null, null)); } else { if (mSimPbRecords.containsKey(recordId)) { mSimPbRecords.remove(recordId); } private void deleteSimPbRecord(int index) { logd("Record number for the deleted ADN is " + index); mSimPbRecords.remove(index - 1); } private void updateSimPbRecord(AdnRecord newRecord, int recordIndex, int index) { logd("Record number for the updated ADN is " + recordIndex); newRecord.setRecId(recordIndex); mSimPbRecords.set(index - 1, newRecord); } private void invalidateSimPbCache() { logd("invalidateSimPbCache"); mIsCacheInvalidated.set(true); if (ENABLE_INFLATE_WITH_EMPTY_RECORDS) { mSimPbRecords.replaceAll((k, v) -> new AdnRecord(IccConstants.EF_ADN, k, null, null, null, null)); } else { mSimPbRecords.clear(); } } private void logd(String msg) { if (DBG) { Loading @@ -622,14 +622,14 @@ public class SimPhonebookRecordCache extends Handler { } private final static class UpdateRequest { private int myRecordId; private int index; private Message response; private AdnRecord adnRecord; private SimPhonebookRecord phonebookRecord; UpdateRequest(int recordId, AdnRecord record, SimPhonebookRecord phonebookRecord, UpdateRequest(int index, AdnRecord record, SimPhonebookRecord phonebookRecord, Message response) { this.myRecordId = recordId; this.index = index; this.adnRecord = record; this.phonebookRecord = phonebookRecord; this.response = response; Loading tests/telephonytests/src/com/android/internal/telephony/SimulatedCommands.java +1 −8 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
src/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java +6 −7 Original line number Diff line number Diff line Loading @@ -166,6 +166,10 @@ public class IccPhoneBookInterfaceManager { return new AdnRecord(oldTag, oldPhoneNumber, oldEmailArray, oldAnrArray); } private AdnRecord generateAdnRecordWithNewTagByContentValues(ContentValues values) { return generateAdnRecordWithNewTagByContentValues(0, 0, values); } private AdnRecord generateAdnRecordWithNewTagByContentValues( int efId, int recordNumber, ContentValues values) { if (values == null) { Loading Loading @@ -215,14 +219,12 @@ public class IccPhoneBookInterfaceManager { synchronized (updateRequest) { Message response = mBaseHandler.obtainMessage(EVENT_UPDATE_DONE, updateRequest); AdnRecord oldAdn = generateAdnRecordWithOldTagByContentValues(values); AdnRecord newAdn = generateAdnRecordWithNewTagByContentValues(values); if (usesPbCache(efid)) { AdnRecord newAdn = generateAdnRecordWithNewTagByContentValues(IccConstants.EF_ADN, 0, values); mSimPbRecordCache.updateSimPbAdnBySearch(oldAdn, newAdn, response); waitForResult(updateRequest); return (boolean) updateRequest.mResult; } else { AdnRecord newAdn = generateAdnRecordWithNewTagByContentValues(efid, 0, values); if (mAdnCache != null) { mAdnCache.updateAdnBySearch(efid, oldAdn, newAdn, pin2, response); waitForResult(updateRequest); Loading Loading @@ -270,15 +272,12 @@ public class IccPhoneBookInterfaceManager { Request updateRequest = new Request(); synchronized (updateRequest) { Message response = mBaseHandler.obtainMessage(EVENT_UPDATE_DONE, updateRequest); AdnRecord newAdn = generateAdnRecordWithNewTagByContentValues(efid, index, values); if (usesPbCache(efid)) { AdnRecord newAdn = generateAdnRecordWithNewTagByContentValues(IccConstants.EF_ADN, index, values); mSimPbRecordCache.updateSimPbAdnByRecordId(index, newAdn, response); waitForResult(updateRequest); return (boolean) updateRequest.mResult; } else { AdnRecord newAdn = generateAdnRecordWithNewTagByContentValues(efid, index, values); if (mAdnCache != null) { mAdnCache.updateAdnByIndex(efid, newAdn, index, pin2, response); waitForResult(updateRequest); Loading
src/java/com/android/internal/telephony/RILUtils.java +41 −6 Original line number Diff line number Diff line Loading @@ -4370,10 +4370,21 @@ public class RILUtils { */ public static android.hardware.radio.V1_6.PhonebookRecordInfo convertToHalPhonebookRecordInfo( SimPhonebookRecord record) { if(record != null) { return record.toPhonebookRecordInfo(); android.hardware.radio.V1_6.PhonebookRecordInfo pbRecordInfo = new android.hardware.radio.V1_6.PhonebookRecordInfo(); pbRecordInfo.recordId = record.getRecordIndex(); pbRecordInfo.name = convertNullToEmptyString(record.getAlphaTag()); pbRecordInfo.number = convertNullToEmptyString( convertToHalPhonebookRecordInfoNumber(record.getNumber())); if (record.getEmails() != null) { pbRecordInfo.emails = primitiveArrayToArrayList(record.getEmails()); } return null; if (record.getAdditionalNumbers() != null) { for (String addNum : record.getAdditionalNumbers()) { pbRecordInfo.additionalNumbers.add(convertToHalPhonebookRecordInfoNumber(addNum)); } } return pbRecordInfo; } /** Loading @@ -4383,10 +4394,34 @@ public class RILUtils { */ public static android.hardware.radio.sim.PhonebookRecordInfo convertToHalPhonebookRecordInfoAidl(SimPhonebookRecord record) { if(record != null) { return record.toPhonebookRecordInfoAidl(); android.hardware.radio.sim.PhonebookRecordInfo pbRecordInfo = new android.hardware.radio.sim.PhonebookRecordInfo(); pbRecordInfo.recordId = record.getRecordIndex(); pbRecordInfo.name = convertNullToEmptyString(record.getAlphaTag()); pbRecordInfo.number = convertNullToEmptyString( convertToHalPhonebookRecordInfoNumber(record.getNumber())); pbRecordInfo.emails = record.getEmails(); if (record.getAdditionalNumbers() != null) { String[] additionalNumbers = new String[record.getAdditionalNumbers().length]; for (int i = 0; i < additionalNumbers.length; i++) { additionalNumbers[i] = convertToHalPhonebookRecordInfoNumber(record.getAdditionalNumbers()[i]); } return null; pbRecordInfo.additionalNumbers = additionalNumbers; } return pbRecordInfo; } /** * Convert the GSM pause/wild/wait character to the phone number in the SIM PhonebookRecordInfo * number format * @param input GSM pause/wild/wait character * @return The converted PhonebookRecordInfo number */ private static String convertToHalPhonebookRecordInfoNumber(String input) { return input == null ? null : input.replace(PhoneNumberUtils.WAIT, 'e') .replace(PhoneNumberUtils.PAUSE, 'T') .replace(PhoneNumberUtils.WILD, '?'); } /** Loading
src/java/com/android/internal/telephony/uicc/SimPhonebookRecord.java +17 −99 Original line number Diff line number Diff line Loading @@ -16,14 +16,12 @@ package com.android.internal.telephony.uicc; import android.hardware.radio.V1_6.PhonebookRecordInfo; import android.telephony.PhoneNumberUtils; import android.text.TextUtils; import com.android.internal.telephony.util.ArrayUtils; import java.util.Arrays; import java.util.ArrayList; /** * Represents a Phonebook entry from the SIM. Loading @@ -32,16 +30,15 @@ import java.util.ArrayList; */ public class SimPhonebookRecord { // Instance variables private int mRecordId = 0; private int mRecordIndex = 0; private String mAlphaTag; private String mNumber; private String[] mEmails; private String[] mAdditionalNumbers; // Instance methods public SimPhonebookRecord (int recordId, String alphaTag, String number, public SimPhonebookRecord (int recordIndex, String alphaTag, String number, String[] emails, String[] adNumbers) { mRecordId = recordId; mRecordIndex = recordIndex; mAlphaTag = alphaTag; mNumber = convertRecordFormatToNumber(number); mEmails = emails; Loading @@ -53,58 +50,8 @@ public class SimPhonebookRecord { } } public SimPhonebookRecord(PhonebookRecordInfo recInfo) { if (recInfo != null) { mRecordId = recInfo.recordId; mAlphaTag = recInfo.name; mNumber = recInfo.number; mEmails = recInfo.emails == null ? null : recInfo.emails.toArray(new String[recInfo.emails.size()]); mAdditionalNumbers = recInfo.additionalNumbers == null ? null : recInfo.additionalNumbers.toArray( new String[recInfo.additionalNumbers.size()]); } } public SimPhonebookRecord() {} public PhonebookRecordInfo toPhonebookRecordInfo() { PhonebookRecordInfo pbRecordInfo = new PhonebookRecordInfo(); pbRecordInfo.recordId = mRecordId; pbRecordInfo.name = convertNullToEmptyString(mAlphaTag); pbRecordInfo.number = convertNullToEmptyString(convertNumberToRecordFormat(mNumber)); if (mEmails != null) { pbRecordInfo.emails = new ArrayList<>(Arrays.asList(mEmails)); } if (mAdditionalNumbers != null) { for (String addNum : mAdditionalNumbers) { pbRecordInfo.additionalNumbers.add(convertNumberToRecordFormat(addNum)); } } return pbRecordInfo; } public android.hardware.radio.sim.PhonebookRecordInfo toPhonebookRecordInfoAidl() { android.hardware.radio.sim.PhonebookRecordInfo pbRecordInfo = new android.hardware.radio.sim.PhonebookRecordInfo(); pbRecordInfo.recordId = mRecordId; pbRecordInfo.name = convertNullToEmptyString(mAlphaTag); pbRecordInfo.number = convertNullToEmptyString(convertNumberToRecordFormat(mNumber)); if (mEmails != null) { pbRecordInfo.emails = mEmails; } if (mAdditionalNumbers != null) { String[] additionalNumbers = new String[mAdditionalNumbers.length]; for (int i = 0; i < additionalNumbers.length; i++) { additionalNumbers[i] = convertNumberToRecordFormat(mAdditionalNumbers[i]); } pbRecordInfo.additionalNumbers = additionalNumbers; } return pbRecordInfo; } public int getRecordId() { return mRecordId; public int getRecordIndex() { return mRecordIndex; } public String getAlphaTag() { Loading @@ -123,35 +70,15 @@ public class SimPhonebookRecord { return mAdditionalNumbers; } /** Convert null to an empty String */ private String convertNullToEmptyString(String str) { return str != null ? str : ""; } /** * Convert the SIM PhonebookRecordInfo number to the GSM pause/wild/wait number * @param input the SIM PhonebookRecordInfo number * @return The converted GSM pause/wild/wait number * convert phone number in the SIM phonebook record format to GSM pause/wild/wait character */ private String convertRecordFormatToNumber(String input) { private static String convertRecordFormatToNumber(String input) { return input == null ? null : input.replace( 'e', PhoneNumberUtils.WAIT ) .replace( 'T', PhoneNumberUtils.PAUSE ) .replace( '?', PhoneNumberUtils.WILD ); } /** * Convert the GSM pause/wild/wait characters to the phone number in the SIM PhonebookRecordInfo * number format * @param input GSM pause/wild/wait character * @return The converted PhonebookRecordInfo number */ private String convertNumberToRecordFormat(String input) { return input == null ? null : input.replace(PhoneNumberUtils.WAIT, 'e') .replace(PhoneNumberUtils.PAUSE, 'T') .replace(PhoneNumberUtils.WILD, '?'); } public boolean isEmpty() { return TextUtils.isEmpty(mAlphaTag) && TextUtils.isEmpty(mNumber) Loading @@ -162,8 +89,8 @@ public class SimPhonebookRecord { @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("SimPhoneBookRecord{").append("ID =") .append(mRecordId).append(", name = ") sb.append("SimPhoneBookRecord{").append("index =") .append(mRecordIndex).append(", name = ") .append(mAlphaTag == null ? "null" : mAlphaTag) .append(", number = ").append(mNumber == null ? "null" : mNumber) .append(", email count = ").append(mEmails == null ? 0 : mEmails.length) Loading @@ -176,28 +103,19 @@ public class SimPhonebookRecord { } public final static class Builder { private int mRecordId = 0; private int mRecordIndex = 0; private String mAlphaTag = null; private String mNumber = null; private String[] mEmails; private String[] mAdditionalNumbers; public SimPhonebookRecord build() { SimPhonebookRecord record = new SimPhonebookRecord(); record.mAlphaTag = mAlphaTag; record.mRecordId = mRecordId; record.mNumber = mNumber; if (mEmails != null) { record.mEmails = mEmails; } if (mAdditionalNumbers != null) { record.mAdditionalNumbers = mAdditionalNumbers; } return record; return new SimPhonebookRecord(mRecordIndex, mAlphaTag, mNumber, mEmails, mAdditionalNumbers); } public Builder setRecordId(int recordId) { mRecordId = recordId; public Builder setRecordIndex(int index) { mRecordIndex = index; return this; } Loading
src/java/com/android/internal/telephony/uicc/SimPhonebookRecordCache.java +97 −97 Original line number Diff line number Diff line Loading @@ -29,16 +29,13 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.RadioInterfaceCapabilityController; import com.android.internal.telephony.uicc.AdnCapacity; import com.android.internal.telephony.uicc.IccConstants; import java.util.ArrayList; import java.util.Collections; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.ConcurrentSkipListMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.stream.Collectors; Loading @@ -59,9 +56,6 @@ public class SimPhonebookRecordCache extends Handler { // Instance Variables private String LOG_TAG = "SimPhonebookRecordCache"; private static final boolean DBG = true; @VisibleForTesting static final boolean ENABLE_INFLATE_WITH_EMPTY_RECORDS = true; // Event Constants private static final int EVENT_PHONEBOOK_CHANGED = 1; private static final int EVENT_PHONEBOOK_RECORDS_RECEIVED = 2; Loading @@ -73,7 +67,6 @@ public class SimPhonebookRecordCache extends Handler { private static final int MAX_RETRY_COUNT = 3; private static final int RETRY_INTERVAL = 3000; // 3S private static final int INVALID_RECORD_ID = -1; // member variables private final CommandsInterface mCi; Loading @@ -83,9 +76,9 @@ public class SimPhonebookRecordCache extends Handler { // Presenting ADN capacity, including ADN, EMAIL ANR, and so on. private AtomicReference<AdnCapacity> mAdnCapacity = new AtomicReference<AdnCapacity>(null); private Object mReadLock = new Object(); private final ConcurrentSkipListMap<Integer, AdnRecord> mSimPbRecords = new ConcurrentSkipListMap<Integer, AdnRecord>(); private final List<UpdateRequest> mUpdateRequests = private List<AdnRecord> mSimPbRecords = Collections.synchronizedList(new ArrayList<AdnRecord>()); private List<UpdateRequest> mUpdateRequests = Collections.synchronizedList(new ArrayList<UpdateRequest>()); // If true, clear the records in the cache and re-query from modem private AtomicBoolean mIsCacheInvalidated = new AtomicBoolean(false); Loading Loading @@ -155,9 +148,7 @@ public class SimPhonebookRecordCache extends Handler { synchronized (mReadLock) { for (Message response : mAdnLoadingWaiters){ if (response != null) { List<AdnRecord> result = new ArrayList<AdnRecord>(mSimPbRecords.values()); AsyncResult.forMessage(response, result, null); AsyncResult.forMessage(response).result = mSimPbRecords; response.sendToTarget(); } } Loading Loading @@ -248,14 +239,7 @@ public class SimPhonebookRecordCache extends Handler { @VisibleForTesting public List<AdnRecord> getAdnRecords() { return mSimPbRecords.values().stream().collect(Collectors.toList()); } @VisibleForTesting public void clear() { if (!ENABLE_INFLATE_WITH_EMPTY_RECORDS) { mSimPbRecords.clear(); } return mSimPbRecords; } private void notifyAdnLoadingWaiters() { Loading @@ -270,50 +254,68 @@ public class SimPhonebookRecordCache extends Handler { sendErrorResponse(response, "There is an invalid new Adn for update"); return; } boolean found = mSimPbRecords.containsKey(recordId); boolean found = false; int index = 0; for (Iterator<AdnRecord> it = mSimPbRecords.iterator(); it.hasNext();) { AdnRecord oldAdn = it.next(); ++index; if (oldAdn.getRecId() == recordId) { found = true; break; } } if (!found) { sendErrorResponse(response, "There is an invalid old Adn for update"); return; } updateSimPhonebookByNewAdn(recordId, newAdn, response); updateSimPhonebookByNewAdn(index, newAdn, response); } public void updateSimPbAdnBySearch(AdnRecord oldAdn, AdnRecord newAdn, Message response) { int index = -1; if ((oldAdn == null || oldAdn.isEmpty()) && !newAdn.isEmpty()) { // Add contact index = 0; } else { int count = 1; // Delete or update contact for (Iterator<AdnRecord> it = mSimPbRecords.iterator(); it.hasNext();) { if (oldAdn.isEqual(it.next())) { index = count; break; } count++; } } if (index == -1) { sendErrorResponse(response, "SIM Phonebook record don't exist for " + oldAdn); return; } if (newAdn == null) { sendErrorResponse(response, "There is an invalid new Adn for update"); return; } int recordId = INVALID_RECORD_ID; // The ID isn't specified by caller if (oldAdn != null && !oldAdn.isEmpty()) { for(AdnRecord adn : mSimPbRecords.values()) { if (oldAdn.isEqual(adn)) { recordId = adn.getRecId(); break; } } } if (recordId == INVALID_RECORD_ID && mAdnCapacity.get() != null && mAdnCapacity.get().isSimFull()) { if (index == 0 && mAdnCapacity.get() != null && mAdnCapacity.get().isSimFull()) { sendErrorResponse(response, "SIM Phonebook record is full"); return; } updateSimPhonebookByNewAdn(recordId, newAdn, response); updateSimPhonebookByNewAdn(index, newAdn, response); } private void updateSimPhonebookByNewAdn(int recordId, AdnRecord newAdn, Message response) { logd("update sim contact for record ID = " + recordId); final int updatingRecordId = recordId == INVALID_RECORD_ID ? 0 : recordId; private void updateSimPhonebookByNewAdn(int index, AdnRecord newAdn, Message response) { int recordIndex = (index == 0) ? newAdn.getRecId() : mSimPbRecords.get(index - 1).getRecId(); SimPhonebookRecord updateAdn = new SimPhonebookRecord.Builder() .setRecordId(updatingRecordId) .setRecordIndex(recordIndex) .setAlphaTag(newAdn.getAlphaTag()) .setNumber(newAdn.getNumber()) .setEmails(newAdn.getEmails()) .setAdditionalNumbers(newAdn.getAdditionalNumbers()) .build(); UpdateRequest updateRequest = new UpdateRequest(recordId, newAdn, updateAdn, response); UpdateRequest updateRequest = new UpdateRequest(index, newAdn, updateAdn, response); mUpdateRequests.add(updateRequest); final boolean isCapacityInvalid = isAdnCapacityInvalid(); if (isCapacityInvalid) { Loading Loading @@ -438,9 +440,8 @@ public class SimPhonebookRecordCache extends Handler { } mAdnCapacity.set(newCapacity); if (oldCapacity == null && newCapacity != null) { inflateWithEmptyRecords(newCapacity); if (!newCapacity.isSimEmpty()){ mIsCacheInvalidated.set(true); invalidateSimPbCache(); fillCacheWithoutWaiting(); } else { notifyAdnLoadingWaiters(); Loading @@ -460,18 +461,6 @@ public class SimPhonebookRecordCache extends Handler { } } private void inflateWithEmptyRecords(AdnCapacity capacity) { if (ENABLE_INFLATE_WITH_EMPTY_RECORDS) { logd("inflateWithEmptyRecords"); if (capacity != null && mSimPbRecords.isEmpty()) { for (int i = 1; i <= capacity.getMaxAdnCount(); i++) { mSimPbRecords.putIfAbsent(i, new AdnRecord(IccConstants.EF_ADN, i, null, null, null, null)); } } } } private void handlePhonebookRecordReceived(ReceivedPhonebookRecords records) { if (records != null) { if (records.isOk()) { Loading Loading @@ -505,20 +494,41 @@ public class SimPhonebookRecordCache extends Handler { UpdateRequest updateRequest = (UpdateRequest)ar.userObj; mIsUpdateDone = true; if (ar.exception == null) { int myRecordId = updateRequest.myRecordId; int index = updateRequest.index; AdnRecord adn = updateRequest.adnRecord; int recordId = ((int[]) (ar.result))[0]; logd("my record ID = " + myRecordId + " new record ID = " + recordId); if (myRecordId == INVALID_RECORD_ID || myRecordId == recordId) { if (!adn.isEmpty()) { addOrChangeSimPbRecord(adn, recordId); int recordIndex = ((int[]) (ar.result))[0]; if (index == 0) { // add contact addSimPbRecord(adn, recordIndex); } else if (adn.isEmpty()){ // delete contact AdnRecord deletedRecord = mSimPbRecords.get(index - 1); int adnRecordIndex = deletedRecord.getRecId(); logd("Record number for deleted ADN is " + adnRecordIndex); if(recordIndex == adnRecordIndex) { deleteSimPbRecord(index); } else { deleteSimPbRecord(recordId); e = new RuntimeException( "The index for deleted ADN record did not match"); } } else { e = new RuntimeException("The record ID for update doesn't match"); // Change contact if (mSimPbRecords.size() > index - 1) { AdnRecord oldRecord = mSimPbRecords.get(index - 1); int adnRecordIndex = oldRecord.getRecId(); logd("Record number for changed ADN is " + adnRecordIndex); if(recordIndex == adnRecordIndex) { updateSimPbRecord(adn, recordIndex, index); } else { e = new RuntimeException( "The index for changed ADN record did not match"); } } else { e = new RuntimeException( "The index for changed ADN record is out of the border"); } } } else { e = new RuntimeException("Update adn record failed", ar.exception); } Loading Loading @@ -554,15 +564,14 @@ public class SimPhonebookRecordCache extends Handler { private void populateAdnRecords(List<SimPhonebookRecord> records) { if (records != null) { Map<Integer, AdnRecord> newRecords = records.stream().map(record -> {return new AdnRecord(IccConstants.EF_ADN, record.getRecordId(), List<AdnRecord> newRecords = records.stream().map(record -> {return new AdnRecord(0, // PBR or ADN record.getRecordIndex(), record.getAlphaTag(), record.getNumber(), record.getEmails(), record.getAdditionalNumbers());}) .collect(Collectors.toMap(AdnRecord::getRecId, adn -> adn)); mSimPbRecords.putAll(newRecords); record.getAdditionalNumbers());}).collect(Collectors.toList()); mSimPbRecords.addAll(newRecords); } } Loading @@ -575,39 +584,30 @@ public class SimPhonebookRecordCache extends Handler { sendMessageDelayed(message, RETRY_INTERVAL); } private void addOrChangeSimPbRecord(AdnRecord record, int recordId) { logd("Record number for the added or changed ADN is " + recordId); record.setRecId(recordId); if (ENABLE_INFLATE_WITH_EMPTY_RECORDS) { mSimPbRecords.replace(recordId, record); } else { mSimPbRecords.put(recordId, record); } private void addSimPbRecord(AdnRecord addedRecord, int recordIndex) { logd("Record number for the added ADN is " + recordIndex); addedRecord.setRecId(recordIndex); mSimPbRecords.add(addedRecord); } private void deleteSimPbRecord(int recordId) { logd("Record number for the deleted ADN is " + recordId); if (ENABLE_INFLATE_WITH_EMPTY_RECORDS) { mSimPbRecords.replace(recordId, new AdnRecord(IccConstants.EF_ADN, recordId, null, null, null, null)); } else { if (mSimPbRecords.containsKey(recordId)) { mSimPbRecords.remove(recordId); } private void deleteSimPbRecord(int index) { logd("Record number for the deleted ADN is " + index); mSimPbRecords.remove(index - 1); } private void updateSimPbRecord(AdnRecord newRecord, int recordIndex, int index) { logd("Record number for the updated ADN is " + recordIndex); newRecord.setRecId(recordIndex); mSimPbRecords.set(index - 1, newRecord); } private void invalidateSimPbCache() { logd("invalidateSimPbCache"); mIsCacheInvalidated.set(true); if (ENABLE_INFLATE_WITH_EMPTY_RECORDS) { mSimPbRecords.replaceAll((k, v) -> new AdnRecord(IccConstants.EF_ADN, k, null, null, null, null)); } else { mSimPbRecords.clear(); } } private void logd(String msg) { if (DBG) { Loading @@ -622,14 +622,14 @@ public class SimPhonebookRecordCache extends Handler { } private final static class UpdateRequest { private int myRecordId; private int index; private Message response; private AdnRecord adnRecord; private SimPhonebookRecord phonebookRecord; UpdateRequest(int recordId, AdnRecord record, SimPhonebookRecord phonebookRecord, UpdateRequest(int index, AdnRecord record, SimPhonebookRecord phonebookRecord, Message response) { this.myRecordId = recordId; this.index = index; this.adnRecord = record; this.phonebookRecord = phonebookRecord; this.response = response; Loading
tests/telephonytests/src/com/android/internal/telephony/SimulatedCommands.java +1 −8 File changed.Preview size limit exceeded, changes collapsed. Show changes