Loading src/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java +7 −6 Original line number Diff line number Diff line Loading @@ -166,10 +166,6 @@ 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 @@ -219,12 +215,14 @@ 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 @@ -272,12 +270,15 @@ 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 +6 −41 Original line number Diff line number Diff line Loading @@ -4370,21 +4370,10 @@ public class RILUtils { */ public static android.hardware.radio.V1_6.PhonebookRecordInfo convertToHalPhonebookRecordInfo( SimPhonebookRecord record) { 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()); if(record != null) { return record.toPhonebookRecordInfo(); } if (record.getAdditionalNumbers() != null) { for (String addNum : record.getAdditionalNumbers()) { pbRecordInfo.additionalNumbers.add(convertToHalPhonebookRecordInfoNumber(addNum)); } } return pbRecordInfo; return null; } /** Loading @@ -4394,34 +4383,10 @@ public class RILUtils { */ public static android.hardware.radio.sim.PhonebookRecordInfo convertToHalPhonebookRecordInfoAidl(SimPhonebookRecord record) { 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]); } pbRecordInfo.additionalNumbers = additionalNumbers; } return pbRecordInfo; if(record != null) { return record.toPhonebookRecordInfoAidl(); } /** * 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, '?'); return null; } /** Loading src/java/com/android/internal/telephony/uicc/SimPhonebookRecord.java +99 −17 Original line number Diff line number Diff line Loading @@ -16,12 +16,14 @@ 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 @@ -30,15 +32,16 @@ import java.util.Arrays; */ public class SimPhonebookRecord { // Instance variables private int mRecordIndex = 0; private int mRecordId = 0; private String mAlphaTag; private String mNumber; private String[] mEmails; private String[] mAdditionalNumbers; public SimPhonebookRecord (int recordIndex, String alphaTag, String number, // Instance methods public SimPhonebookRecord (int recordId, String alphaTag, String number, String[] emails, String[] adNumbers) { mRecordIndex = recordIndex; mRecordId = recordId; mAlphaTag = alphaTag; mNumber = convertRecordFormatToNumber(number); mEmails = emails; Loading @@ -50,8 +53,58 @@ public class SimPhonebookRecord { } } public int getRecordIndex() { return mRecordIndex; 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 String getAlphaTag() { Loading @@ -70,15 +123,35 @@ public class SimPhonebookRecord { return mAdditionalNumbers; } /** Convert null to an empty String */ private String convertNullToEmptyString(String str) { return str != null ? str : ""; } /** * convert phone number in the SIM phonebook record format to GSM pause/wild/wait character * 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 */ private static String convertRecordFormatToNumber(String input) { private 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 @@ -89,8 +162,8 @@ public class SimPhonebookRecord { @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("SimPhoneBookRecord{").append("index =") .append(mRecordIndex).append(", name = ") sb.append("SimPhoneBookRecord{").append("ID =") .append(mRecordId).append(", name = ") .append(mAlphaTag == null ? "null" : mAlphaTag) .append(", number = ").append(mNumber == null ? "null" : mNumber) .append(", email count = ").append(mEmails == null ? 0 : mEmails.length) Loading @@ -103,19 +176,28 @@ public class SimPhonebookRecord { } public final static class Builder { private int mRecordIndex = 0; private int mRecordId = 0; private String mAlphaTag = null; private String mNumber = null; private String[] mEmails; private String[] mAdditionalNumbers; public SimPhonebookRecord build() { return new SimPhonebookRecord(mRecordIndex, mAlphaTag, mNumber, mEmails, mAdditionalNumbers); 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; } public Builder setRecordIndex(int index) { mRecordIndex = index; public Builder setRecordId(int recordId) { mRecordId = recordId; return this; } Loading src/java/com/android/internal/telephony/uicc/SimPhonebookRecordCache.java +97 −97 Original line number Diff line number Diff line Loading @@ -29,13 +29,16 @@ 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 @@ -56,6 +59,9 @@ 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 @@ -67,6 +73,7 @@ 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 @@ -76,9 +83,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 List<AdnRecord> mSimPbRecords = Collections.synchronizedList(new ArrayList<AdnRecord>()); private List<UpdateRequest> mUpdateRequests = private final ConcurrentSkipListMap<Integer, AdnRecord> mSimPbRecords = new ConcurrentSkipListMap<Integer, AdnRecord>(); private final 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 @@ -148,7 +155,9 @@ public class SimPhonebookRecordCache extends Handler { synchronized (mReadLock) { for (Message response : mAdnLoadingWaiters){ if (response != null) { AsyncResult.forMessage(response).result = mSimPbRecords; List<AdnRecord> result = new ArrayList<AdnRecord>(mSimPbRecords.values()); AsyncResult.forMessage(response, result, null); response.sendToTarget(); } } Loading Loading @@ -239,7 +248,14 @@ public class SimPhonebookRecordCache extends Handler { @VisibleForTesting public List<AdnRecord> getAdnRecords() { return mSimPbRecords; return mSimPbRecords.values().stream().collect(Collectors.toList()); } @VisibleForTesting public void clear() { if (!ENABLE_INFLATE_WITH_EMPTY_RECORDS) { mSimPbRecords.clear(); } } private void notifyAdnLoadingWaiters() { Loading @@ -254,68 +270,50 @@ public class SimPhonebookRecordCache extends Handler { sendErrorResponse(response, "There is an invalid new Adn for update"); return; } 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; } } boolean found = mSimPbRecords.containsKey(recordId); if (!found) { sendErrorResponse(response, "There is an invalid old Adn for update"); return; } updateSimPhonebookByNewAdn(index, newAdn, response); updateSimPhonebookByNewAdn(recordId, 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; } if (index == 0 && mAdnCapacity.get() != null && mAdnCapacity.get().isSimFull()) { 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()) { sendErrorResponse(response, "SIM Phonebook record is full"); return; } updateSimPhonebookByNewAdn(index, newAdn, response); updateSimPhonebookByNewAdn(recordId, newAdn, response); } private void updateSimPhonebookByNewAdn(int index, AdnRecord newAdn, Message response) { int recordIndex = (index == 0) ? newAdn.getRecId() : mSimPbRecords.get(index - 1).getRecId(); 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; SimPhonebookRecord updateAdn = new SimPhonebookRecord.Builder() .setRecordIndex(recordIndex) .setRecordId(updatingRecordId) .setAlphaTag(newAdn.getAlphaTag()) .setNumber(newAdn.getNumber()) .setEmails(newAdn.getEmails()) .setAdditionalNumbers(newAdn.getAdditionalNumbers()) .build(); UpdateRequest updateRequest = new UpdateRequest(index, newAdn, updateAdn, response); UpdateRequest updateRequest = new UpdateRequest(recordId, newAdn, updateAdn, response); mUpdateRequests.add(updateRequest); final boolean isCapacityInvalid = isAdnCapacityInvalid(); if (isCapacityInvalid) { Loading Loading @@ -440,8 +438,9 @@ public class SimPhonebookRecordCache extends Handler { } mAdnCapacity.set(newCapacity); if (oldCapacity == null && newCapacity != null) { inflateWithEmptyRecords(newCapacity); if (!newCapacity.isSimEmpty()){ invalidateSimPbCache(); mIsCacheInvalidated.set(true); fillCacheWithoutWaiting(); } else { notifyAdnLoadingWaiters(); Loading @@ -461,6 +460,18 @@ 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 @@ -494,41 +505,20 @@ public class SimPhonebookRecordCache extends Handler { UpdateRequest updateRequest = (UpdateRequest)ar.userObj; mIsUpdateDone = true; if (ar.exception == null) { int index = updateRequest.index; int myRecordId = updateRequest.myRecordId; AdnRecord adn = updateRequest.adnRecord; 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); 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); } else { e = new RuntimeException( "The index for deleted ADN record did not match"); deleteSimPbRecord(recordId); } } else { // 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"); } e = new RuntimeException("The record ID for update doesn't match"); } } else { e = new RuntimeException("Update adn record failed", ar.exception); } Loading Loading @@ -564,14 +554,15 @@ public class SimPhonebookRecordCache extends Handler { private void populateAdnRecords(List<SimPhonebookRecord> records) { if (records != null) { List<AdnRecord> newRecords = records.stream().map(record -> {return new AdnRecord(0, // PBR or ADN record.getRecordIndex(), Map<Integer, AdnRecord> newRecords = records.stream().map(record -> {return new AdnRecord(IccConstants.EF_ADN, record.getRecordId(), record.getAlphaTag(), record.getNumber(), record.getEmails(), record.getAdditionalNumbers());}).collect(Collectors.toList()); mSimPbRecords.addAll(newRecords); record.getAdditionalNumbers());}) .collect(Collectors.toMap(AdnRecord::getRecId, adn -> adn)); mSimPbRecords.putAll(newRecords); } } Loading @@ -584,30 +575,39 @@ public class SimPhonebookRecordCache extends Handler { sendMessageDelayed(message, RETRY_INTERVAL); } private void addSimPbRecord(AdnRecord addedRecord, int recordIndex) { logd("Record number for the added ADN is " + recordIndex); addedRecord.setRecId(recordIndex); mSimPbRecords.add(addedRecord); 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 deleteSimPbRecord(int index) { logd("Record number for the deleted ADN is " + index); mSimPbRecords.remove(index - 1); 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 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 index; private int myRecordId; private Message response; private AdnRecord adnRecord; private SimPhonebookRecord phonebookRecord; UpdateRequest(int index, AdnRecord record, SimPhonebookRecord phonebookRecord, UpdateRequest(int recordId, AdnRecord record, SimPhonebookRecord phonebookRecord, Message response) { this.index = index; this.myRecordId = recordId; this.adnRecord = record; this.phonebookRecord = phonebookRecord; this.response = response; Loading tests/telephonytests/src/com/android/internal/telephony/SimulatedCommands.java +8 −1 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
src/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java +7 −6 Original line number Diff line number Diff line Loading @@ -166,10 +166,6 @@ 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 @@ -219,12 +215,14 @@ 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 @@ -272,12 +270,15 @@ 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 +6 −41 Original line number Diff line number Diff line Loading @@ -4370,21 +4370,10 @@ public class RILUtils { */ public static android.hardware.radio.V1_6.PhonebookRecordInfo convertToHalPhonebookRecordInfo( SimPhonebookRecord record) { 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()); if(record != null) { return record.toPhonebookRecordInfo(); } if (record.getAdditionalNumbers() != null) { for (String addNum : record.getAdditionalNumbers()) { pbRecordInfo.additionalNumbers.add(convertToHalPhonebookRecordInfoNumber(addNum)); } } return pbRecordInfo; return null; } /** Loading @@ -4394,34 +4383,10 @@ public class RILUtils { */ public static android.hardware.radio.sim.PhonebookRecordInfo convertToHalPhonebookRecordInfoAidl(SimPhonebookRecord record) { 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]); } pbRecordInfo.additionalNumbers = additionalNumbers; } return pbRecordInfo; if(record != null) { return record.toPhonebookRecordInfoAidl(); } /** * 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, '?'); return null; } /** Loading
src/java/com/android/internal/telephony/uicc/SimPhonebookRecord.java +99 −17 Original line number Diff line number Diff line Loading @@ -16,12 +16,14 @@ 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 @@ -30,15 +32,16 @@ import java.util.Arrays; */ public class SimPhonebookRecord { // Instance variables private int mRecordIndex = 0; private int mRecordId = 0; private String mAlphaTag; private String mNumber; private String[] mEmails; private String[] mAdditionalNumbers; public SimPhonebookRecord (int recordIndex, String alphaTag, String number, // Instance methods public SimPhonebookRecord (int recordId, String alphaTag, String number, String[] emails, String[] adNumbers) { mRecordIndex = recordIndex; mRecordId = recordId; mAlphaTag = alphaTag; mNumber = convertRecordFormatToNumber(number); mEmails = emails; Loading @@ -50,8 +53,58 @@ public class SimPhonebookRecord { } } public int getRecordIndex() { return mRecordIndex; 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 String getAlphaTag() { Loading @@ -70,15 +123,35 @@ public class SimPhonebookRecord { return mAdditionalNumbers; } /** Convert null to an empty String */ private String convertNullToEmptyString(String str) { return str != null ? str : ""; } /** * convert phone number in the SIM phonebook record format to GSM pause/wild/wait character * 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 */ private static String convertRecordFormatToNumber(String input) { private 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 @@ -89,8 +162,8 @@ public class SimPhonebookRecord { @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("SimPhoneBookRecord{").append("index =") .append(mRecordIndex).append(", name = ") sb.append("SimPhoneBookRecord{").append("ID =") .append(mRecordId).append(", name = ") .append(mAlphaTag == null ? "null" : mAlphaTag) .append(", number = ").append(mNumber == null ? "null" : mNumber) .append(", email count = ").append(mEmails == null ? 0 : mEmails.length) Loading @@ -103,19 +176,28 @@ public class SimPhonebookRecord { } public final static class Builder { private int mRecordIndex = 0; private int mRecordId = 0; private String mAlphaTag = null; private String mNumber = null; private String[] mEmails; private String[] mAdditionalNumbers; public SimPhonebookRecord build() { return new SimPhonebookRecord(mRecordIndex, mAlphaTag, mNumber, mEmails, mAdditionalNumbers); 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; } public Builder setRecordIndex(int index) { mRecordIndex = index; public Builder setRecordId(int recordId) { mRecordId = recordId; return this; } Loading
src/java/com/android/internal/telephony/uicc/SimPhonebookRecordCache.java +97 −97 Original line number Diff line number Diff line Loading @@ -29,13 +29,16 @@ 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 @@ -56,6 +59,9 @@ 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 @@ -67,6 +73,7 @@ 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 @@ -76,9 +83,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 List<AdnRecord> mSimPbRecords = Collections.synchronizedList(new ArrayList<AdnRecord>()); private List<UpdateRequest> mUpdateRequests = private final ConcurrentSkipListMap<Integer, AdnRecord> mSimPbRecords = new ConcurrentSkipListMap<Integer, AdnRecord>(); private final 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 @@ -148,7 +155,9 @@ public class SimPhonebookRecordCache extends Handler { synchronized (mReadLock) { for (Message response : mAdnLoadingWaiters){ if (response != null) { AsyncResult.forMessage(response).result = mSimPbRecords; List<AdnRecord> result = new ArrayList<AdnRecord>(mSimPbRecords.values()); AsyncResult.forMessage(response, result, null); response.sendToTarget(); } } Loading Loading @@ -239,7 +248,14 @@ public class SimPhonebookRecordCache extends Handler { @VisibleForTesting public List<AdnRecord> getAdnRecords() { return mSimPbRecords; return mSimPbRecords.values().stream().collect(Collectors.toList()); } @VisibleForTesting public void clear() { if (!ENABLE_INFLATE_WITH_EMPTY_RECORDS) { mSimPbRecords.clear(); } } private void notifyAdnLoadingWaiters() { Loading @@ -254,68 +270,50 @@ public class SimPhonebookRecordCache extends Handler { sendErrorResponse(response, "There is an invalid new Adn for update"); return; } 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; } } boolean found = mSimPbRecords.containsKey(recordId); if (!found) { sendErrorResponse(response, "There is an invalid old Adn for update"); return; } updateSimPhonebookByNewAdn(index, newAdn, response); updateSimPhonebookByNewAdn(recordId, 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; } if (index == 0 && mAdnCapacity.get() != null && mAdnCapacity.get().isSimFull()) { 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()) { sendErrorResponse(response, "SIM Phonebook record is full"); return; } updateSimPhonebookByNewAdn(index, newAdn, response); updateSimPhonebookByNewAdn(recordId, newAdn, response); } private void updateSimPhonebookByNewAdn(int index, AdnRecord newAdn, Message response) { int recordIndex = (index == 0) ? newAdn.getRecId() : mSimPbRecords.get(index - 1).getRecId(); 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; SimPhonebookRecord updateAdn = new SimPhonebookRecord.Builder() .setRecordIndex(recordIndex) .setRecordId(updatingRecordId) .setAlphaTag(newAdn.getAlphaTag()) .setNumber(newAdn.getNumber()) .setEmails(newAdn.getEmails()) .setAdditionalNumbers(newAdn.getAdditionalNumbers()) .build(); UpdateRequest updateRequest = new UpdateRequest(index, newAdn, updateAdn, response); UpdateRequest updateRequest = new UpdateRequest(recordId, newAdn, updateAdn, response); mUpdateRequests.add(updateRequest); final boolean isCapacityInvalid = isAdnCapacityInvalid(); if (isCapacityInvalid) { Loading Loading @@ -440,8 +438,9 @@ public class SimPhonebookRecordCache extends Handler { } mAdnCapacity.set(newCapacity); if (oldCapacity == null && newCapacity != null) { inflateWithEmptyRecords(newCapacity); if (!newCapacity.isSimEmpty()){ invalidateSimPbCache(); mIsCacheInvalidated.set(true); fillCacheWithoutWaiting(); } else { notifyAdnLoadingWaiters(); Loading @@ -461,6 +460,18 @@ 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 @@ -494,41 +505,20 @@ public class SimPhonebookRecordCache extends Handler { UpdateRequest updateRequest = (UpdateRequest)ar.userObj; mIsUpdateDone = true; if (ar.exception == null) { int index = updateRequest.index; int myRecordId = updateRequest.myRecordId; AdnRecord adn = updateRequest.adnRecord; 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); 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); } else { e = new RuntimeException( "The index for deleted ADN record did not match"); deleteSimPbRecord(recordId); } } else { // 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"); } e = new RuntimeException("The record ID for update doesn't match"); } } else { e = new RuntimeException("Update adn record failed", ar.exception); } Loading Loading @@ -564,14 +554,15 @@ public class SimPhonebookRecordCache extends Handler { private void populateAdnRecords(List<SimPhonebookRecord> records) { if (records != null) { List<AdnRecord> newRecords = records.stream().map(record -> {return new AdnRecord(0, // PBR or ADN record.getRecordIndex(), Map<Integer, AdnRecord> newRecords = records.stream().map(record -> {return new AdnRecord(IccConstants.EF_ADN, record.getRecordId(), record.getAlphaTag(), record.getNumber(), record.getEmails(), record.getAdditionalNumbers());}).collect(Collectors.toList()); mSimPbRecords.addAll(newRecords); record.getAdditionalNumbers());}) .collect(Collectors.toMap(AdnRecord::getRecId, adn -> adn)); mSimPbRecords.putAll(newRecords); } } Loading @@ -584,30 +575,39 @@ public class SimPhonebookRecordCache extends Handler { sendMessageDelayed(message, RETRY_INTERVAL); } private void addSimPbRecord(AdnRecord addedRecord, int recordIndex) { logd("Record number for the added ADN is " + recordIndex); addedRecord.setRecId(recordIndex); mSimPbRecords.add(addedRecord); 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 deleteSimPbRecord(int index) { logd("Record number for the deleted ADN is " + index); mSimPbRecords.remove(index - 1); 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 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 index; private int myRecordId; private Message response; private AdnRecord adnRecord; private SimPhonebookRecord phonebookRecord; UpdateRequest(int index, AdnRecord record, SimPhonebookRecord phonebookRecord, UpdateRequest(int recordId, AdnRecord record, SimPhonebookRecord phonebookRecord, Message response) { this.index = index; this.myRecordId = recordId; this.adnRecord = record; this.phonebookRecord = phonebookRecord; this.response = response; Loading
tests/telephonytests/src/com/android/internal/telephony/SimulatedCommands.java +8 −1 File changed.Preview size limit exceeded, changes collapsed. Show changes