Merge ab/7061308 into stage.
Bug: 180401296
Merged-In: I05d576339afeaca4046628c88d9738d2d970514e
Change-Id: Iff02f9c0e289a4e9c907d2f42dcfdbea54322970
diff --git a/Android.bp b/Android.bp
index 1fd8e8b..7c09a13 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,3 +1,34 @@
+package {
+ default_applicable_licenses: ["packages_apps_Contacts_license"],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+ name: "packages_apps_Contacts_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ "SPDX-license-identifier-BSD",
+ "SPDX-license-identifier-CC-BY",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
android_app {
name: "Contacts",
diff --git a/src/com/android/contacts/SimImportFragment.java b/src/com/android/contacts/SimImportFragment.java
index cee1b1a..1d16df0 100644
--- a/src/com/android/contacts/SimImportFragment.java
+++ b/src/com/android/contacts/SimImportFragment.java
@@ -18,7 +18,6 @@
import android.app.Activity;
import android.app.Fragment;
import android.app.LoaderManager;
-import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.IntentFilter;
import android.content.Loader;
@@ -26,7 +25,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.material.snackbar.Snackbar;
-import androidx.localbroadcastmanager.content.LocalBroadcastManager;
+
import androidx.collection.ArrayMap;
import androidx.core.view.ViewCompat;
import androidx.core.widget.ContentLoadingProgressBar;
@@ -372,7 +371,7 @@
if (position < 0 || position >= getCount()) {
return View.NO_ID;
}
- return getItem(position).getId();
+ return getItem(position).getRecordNumber();
}
@Override
diff --git a/src/com/android/contacts/database/SimContactDaoImpl.java b/src/com/android/contacts/database/SimContactDaoImpl.java
index 5ba6bd5..54106f0 100644
--- a/src/com/android/contacts/database/SimContactDaoImpl.java
+++ b/src/com/android/contacts/database/SimContactDaoImpl.java
@@ -26,20 +26,20 @@
import android.net.Uri;
import android.os.Build;
import android.os.RemoteException;
-import android.provider.BaseColumns;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.RawContacts;
-import androidx.annotation.VisibleForTesting;
-import androidx.collection.ArrayMap;
+import android.provider.SimPhonebookContract;
+import android.provider.SimPhonebookContract.SimRecords;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
-import android.text.TextUtils;
import android.util.SparseArray;
+import androidx.collection.ArrayMap;
+
import com.android.contacts.R;
import com.android.contacts.compat.CompatUtils;
import com.android.contacts.model.SimCard;
@@ -47,6 +47,7 @@
import com.android.contacts.model.account.AccountWithDataSet;
import com.android.contacts.util.PermissionsUtil;
import com.android.contacts.util.SharedPreferenceUtil;
+
import com.google.common.base.Joiner;
import java.util.ArrayList;
@@ -75,14 +76,6 @@
// query parameter limit.
static final int QUERY_MAX_BATCH_SIZE = 100;
- @VisibleForTesting
- public static final Uri ICC_CONTENT_URI = Uri.parse("content://icc/adn");
-
- public static String _ID = BaseColumns._ID;
- public static String NAME = "name";
- public static String NUMBER = "number";
- public static String EMAILS = "emails";
-
private final Context mContext;
private final ContentResolver mResolver;
private final TelephonyManager mTelephonyManager;
@@ -128,18 +121,14 @@
if (sim.hasValidSubscriptionId()) {
return loadSimContacts(sim.getSubscriptionId());
}
- return loadSimContacts();
+ // Return an empty list.
+ return new ArrayList<>(0);
}
public ArrayList<SimContact> loadSimContacts(int subscriptionId) {
- return loadFrom(ICC_CONTENT_URI.buildUpon()
- .appendPath("subId")
- .appendPath(String.valueOf(subscriptionId))
- .build());
- }
-
- public ArrayList<SimContact> loadSimContacts() {
- return loadFrom(ICC_CONTENT_URI);
+ return loadFrom(
+ SimRecords.getContentUri(
+ subscriptionId, SimPhonebookContract.ElementaryFiles.EF_ADN));
}
@Override
@@ -273,7 +262,12 @@
private static final Object SIM_READ_LOCK = new Object();
private ArrayList<SimContact> loadFrom(Uri uri) {
synchronized (SIM_READ_LOCK) {
- final Cursor cursor = mResolver.query(uri, null, null, null, null);
+ final Cursor cursor = mResolver.query(uri,
+ new String[]{
+ SimRecords.RECORD_NUMBER,
+ SimRecords.NAME,
+ SimRecords.PHONE_NUMBER
+ }, null, null);
if (cursor == null) {
// Assume null means there are no SIM contacts.
return new ArrayList<>(0);
@@ -288,22 +282,20 @@
}
private ArrayList<SimContact> loadFromCursor(Cursor cursor) {
- final int colId = cursor.getColumnIndex(_ID);
- final int colName = cursor.getColumnIndex(NAME);
- final int colNumber = cursor.getColumnIndex(NUMBER);
- final int colEmails = cursor.getColumnIndex(EMAILS);
+ final int colRecordNumber = cursor.getColumnIndex(SimRecords.RECORD_NUMBER);
+ final int colName = cursor.getColumnIndex(SimRecords.NAME);
+ final int colNumber = cursor.getColumnIndex(SimRecords.PHONE_NUMBER);
final ArrayList<SimContact> result = new ArrayList<>();
while (cursor.moveToNext()) {
- final long id = cursor.getLong(colId);
+ final int recordNumber = cursor.getInt(colRecordNumber);
final String name = cursor.getString(colName);
final String number = cursor.getString(colNumber);
- final String emails = cursor.getString(colEmails);
- final SimContact contact = new SimContact(id, name, number, parseEmails(emails));
+ final SimContact contact = new SimContact(recordNumber, name, number, null);
// Only include contact if it has some useful data
- if (contact.hasName() || contact.hasPhone() || contact.hasEmails()) {
+ if (contact.hasName() || contact.hasPhone()) {
result.add(contact);
}
}
@@ -392,10 +384,6 @@
return ops;
}
- private String[] parseEmails(String emails) {
- return !TextUtils.isEmpty(emails) ? emails.split(",") : null;
- }
-
private boolean hasTelephony() {
return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
}
diff --git a/src/com/android/contacts/model/SimCard.java b/src/com/android/contacts/model/SimCard.java
index ea74379..969d96d 100644
--- a/src/com/android/contacts/model/SimCard.java
+++ b/src/com/android/contacts/model/SimCard.java
@@ -19,6 +19,7 @@
import androidx.annotation.RequiresApi;
import android.telephony.PhoneNumberUtils;
import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.Log;
@@ -78,11 +79,6 @@
mCountryCode = countryCode != null ? countryCode.toUpperCase(Locale.US) : null;
}
- public SimCard(String simId, CharSequence carrierName,
- CharSequence displayName, String phoneNumber, String countryCode) {
- this(simId, NO_SUBSCRIPTION_ID, carrierName, displayName, phoneNumber, countryCode);
- }
-
public String getSimId() {
return mSimId;
}
@@ -245,12 +241,14 @@
public static SimCard create(TelephonyManager telephony, String displayLabel) {
if (telephony.getSimState() == TelephonyManager.SIM_STATE_READY) {
- return new SimCard(telephony.getSimSerialNumber(),
+ return new SimCard(telephony.getSimSerialNumber(), telephony.getSubscriptionId(),
telephony.getSimOperatorName(), displayLabel, telephony.getLine1Number(),
telephony.getSimCountryIso());
} else {
// This should never happen but in case it does just fallback to an "empty" instance
- return new SimCard(/* SIM id */ "", /* operator name */ null, displayLabel,
+ return new SimCard(/* SIM id */ "",
+ /* subscriptionId */ SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+ /* operator name */ null, displayLabel,
/* phone number */ "", /* Country code */ null);
}
}
diff --git a/src/com/android/contacts/model/SimContact.java b/src/com/android/contacts/model/SimContact.java
index 7babe27..820e346 100644
--- a/src/com/android/contacts/model/SimContact.java
+++ b/src/com/android/contacts/model/SimContact.java
@@ -43,28 +43,28 @@
* Holds data for contacts loaded from the SIM card.
*/
public class SimContact implements Parcelable {
- private final long mId;
+ private final int mRecordNumber;
private final String mName;
private final String mPhone;
private final String[] mEmails;
- public SimContact(long id, String name, String phone) {
- this(id, name, phone, null);
+ public SimContact(int recordNumber, String name, String phone) {
+ this(recordNumber, name, phone, null);
}
- public SimContact(long id, String name, String phone, String[] emails) {
- mId = id;
+ public SimContact(int recordNumber, String name, String phone, String[] emails) {
+ mRecordNumber = recordNumber;
mName = name;
mPhone = phone == null ? "" : phone.trim();
mEmails = emails;
}
public SimContact(SimContact other) {
- this(other.mId, other.mName, other.mPhone, other.mEmails);
+ this(other.mRecordNumber, other.mName, other.mPhone, other.mEmails);
}
- public long getId() {
- return mId;
+ public int getRecordNumber() {
+ return mRecordNumber;
}
public String getName() {
@@ -117,7 +117,7 @@
}
public void appendAsContactRow(MatrixCursor cursor) {
- cursor.newRow().add(ContactsContract.Contacts._ID, mId)
+ cursor.newRow().add(ContactsContract.Contacts._ID, mRecordNumber)
.add(ContactsContract.Contacts.DISPLAY_NAME_PRIMARY, mName)
.add(ContactsContract.Contacts.LOOKUP_KEY, getLookupKey());
}
@@ -152,7 +152,7 @@
@Override
public String toString() {
return "SimContact{" +
- "mId=" + mId +
+ "mId=" + mRecordNumber +
", mName='" + mName + '\'' +
", mPhone='" + mPhone + '\'' +
", mEmails=" + Arrays.toString(mEmails) +
@@ -166,13 +166,13 @@
final SimContact that = (SimContact) o;
- return mId == that.mId && Objects.equals(mName, that.mName) &&
+ return mRecordNumber == that.mRecordNumber && Objects.equals(mName, that.mName) &&
Objects.equals(mPhone, that.mPhone) && Arrays.equals(mEmails, that.mEmails);
}
@Override
public int hashCode() {
- int result = (int) (mId ^ (mId >>> 32));
+ int result = (int) (mRecordNumber ^ (mRecordNumber >>> 32));
result = 31 * result + (mName != null ? mName.hashCode() : 0);
result = 31 * result + (mPhone != null ? mPhone.hashCode() : 0);
result = 31 * result + Arrays.hashCode(mEmails);
@@ -186,7 +186,7 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeLong(mId);
+ dest.writeInt(mRecordNumber);
dest.writeString(mName);
dest.writeString(mPhone);
dest.writeStringArray(mEmails);
@@ -195,11 +195,11 @@
public static final Creator<SimContact> CREATOR = new Creator<SimContact>() {
@Override
public SimContact createFromParcel(Parcel source) {
- final long id = source.readLong();
+ final int recordNumber = source.readInt();
final String name = source.readString();
final String phone = source.readString();
final String[] emails = source.createStringArray();
- return new SimContact(id, name, phone, emails);
+ return new SimContact(recordNumber, name, phone, emails);
}
@Override
@@ -253,7 +253,7 @@
@Override
public int compare(SimContact lhs, SimContact rhs) {
// We assume ids are unique.
- return Long.compare(lhs.mId, rhs.mId);
+ return Long.compare(lhs.mRecordNumber, rhs.mRecordNumber);
}
};
}
diff --git a/tests/Android.bp b/tests/Android.bp
index 2e1d47b..10ebbc9 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -1,3 +1,13 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "packages_apps_Contacts_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-CC-BY
+ default_applicable_licenses: ["packages_apps_Contacts_license"],
+}
+
android_test {
name: "ContactsTests",
@@ -12,6 +22,8 @@
static_libs: [
"androidx.test.rules",
+ "androidx.test.runner",
+ "androidx.test.ext.junit",
"hamcrest-library",
"mockito-target-minus-junit4",
"ub-uiautomator",
diff --git a/tests/src/com/android/contacts/activities/SimImportActivityTest.java b/tests/src/com/android/contacts/activities/SimImportActivityTest.java
index 7069ef1..250ce4b 100644
--- a/tests/src/com/android/contacts/activities/SimImportActivityTest.java
+++ b/tests/src/com/android/contacts/activities/SimImportActivityTest.java
@@ -40,6 +40,8 @@
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Data;
+import android.provider.SimPhonebookContract;
+import android.provider.SimPhonebookContract.SimRecords;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.Until;
@@ -48,9 +50,9 @@
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.test.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
import androidx.test.filters.SdkSuppress;
-import androidx.test.runner.AndroidJUnit4;
import com.android.contacts.SimImportService;
import com.android.contacts.database.SimContactDao;
@@ -224,10 +226,10 @@
final AccountWithDataSet targetAccount = mAccountHelper.addTestAccount(
mAccountHelper.generateAccountName("SimImportActivity0_targetAccount_"));
- final MockContentProvider iccProvider = new MockContentProvider();
- iccProvider.expect(MockContentProvider.Query.forAnyUri())
- .withDefaultProjection(new String[] {SimContactDaoImpl._ID, SimContactDaoImpl.NAME,
- SimContactDaoImpl.NUMBER, SimContactDaoImpl.EMAILS })
+ final MockContentProvider simPhonebookProvider = new MockContentProvider();
+ simPhonebookProvider.expect(MockContentProvider.Query.forAnyUri())
+ .withProjection(
+ SimRecords.RECORD_NUMBER, SimRecords.NAME, SimRecords.PHONE_NUMBER)
.anyNumberOfTimes()
.returnRow(toCursorRow(new SimContact(1, "Import One", "5550101")))
.returnRow(toCursorRow(new SimContact(2, "Skip Two", "5550102")))
@@ -236,7 +238,7 @@
.returnRow(toCursorRow(new SimContact(5, "Skip Five", "5550105")))
.returnRow(toCursorRow(new SimContact(6, "Import Six", "5550106")));
final MockContentResolver mockResolver = new MockContentResolver();
- mockResolver.addProvider("icc", iccProvider);
+ mockResolver.addProvider(SimPhonebookContract.AUTHORITY, simPhonebookProvider);
final ContentProviderClient contactsProviderClient = mContext.getContentResolver()
.acquireContentProviderClient(ContactsContract.AUTHORITY);
mockResolver.addProvider(ContactsContract.AUTHORITY, new ForwardingContentProvider(
@@ -258,6 +260,7 @@
mActivity = mInstrumentation.startActivitySync(
new Intent(mContext, SimImportActivity.class)
+ .putExtra(SimImportActivity.EXTRA_SUBSCRIPTION_ID, 1)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
assertTrue(mDevice.wait(Until.hasObject(By.desc("Show more")), TIMEOUT));
@@ -319,6 +322,7 @@
mActivity = mInstrumentation.startActivitySync(
new Intent(mContext, SimImportActivity.class)
+ .putExtra(SimImportActivity.EXTRA_SUBSCRIPTION_ID, 1)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
assertTrue(mDevice.wait(Until.hasObject(By.text("Import One")), TIMEOUT));
@@ -351,7 +355,7 @@
}
private Object[] toCursorRow(SimContact contact) {
- return new Object[] { contact.getId(), contact.getName(), contact.getPhone(), null };
+ return new Object[]{contact.getRecordNumber(), contact.getName(), contact.getPhone()};
}
private SimCard someSimCard() {
diff --git a/tests/src/com/android/contacts/database/SimContactDaoTests.java b/tests/src/com/android/contacts/database/SimContactDaoTests.java
index 0b5b37f..680ba10 100644
--- a/tests/src/com/android/contacts/database/SimContactDaoTests.java
+++ b/tests/src/com/android/contacts/database/SimContactDaoTests.java
@@ -45,16 +45,18 @@
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.Data;
+import android.provider.SimPhonebookContract;
+import android.provider.SimPhonebookContract.SimRecords;
import android.test.mock.MockContentResolver;
import android.test.mock.MockContext;
import androidx.annotation.RequiresApi;
import androidx.test.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
import androidx.test.filters.Suppress;
-import androidx.test.runner.AndroidJUnit4;
import com.android.contacts.model.SimCard;
import com.android.contacts.model.SimContact;
@@ -578,92 +580,78 @@
@RunWith(AndroidJUnit4.class)
public static class LoadContactsUnitTests {
- private MockContentProvider mMockIccProvider;
+ private MockContentProvider mMockSimPhonebookProvider;
private Context mContext;
@Before
public void setUp() {
mContext = mock(MockContext.class);
final MockContentResolver mockResolver = new MockContentResolver();
- mMockIccProvider = new MockContentProvider();
- mockResolver.addProvider("icc", mMockIccProvider);
+ mMockSimPhonebookProvider = new MockContentProvider();
+ mockResolver.addProvider(SimPhonebookContract.AUTHORITY, mMockSimPhonebookProvider);
when(mContext.getContentResolver()).thenReturn(mockResolver);
}
@Test
public void createsContactsFromCursor() {
- mMockIccProvider.expect(MockContentProvider.Query.forAnyUri())
+ mMockSimPhonebookProvider.expect(MockContentProvider.Query.forAnyUri())
.withDefaultProjection(
- SimContactDaoImpl._ID, SimContactDaoImpl.NAME,
- SimContactDaoImpl.NUMBER, SimContactDaoImpl.EMAILS)
+ SimRecords.RECORD_NUMBER, SimRecords.NAME, SimRecords.PHONE_NUMBER)
.withAnyProjection()
.withAnySelection()
.withAnySortOrder()
- .returnRow(1, "Name One", "5550101", null)
- .returnRow(2, "Name Two", "5550102", null)
- .returnRow(3, "Name Three", null, null)
- .returnRow(4, null, "5550104", null)
- .returnRow(5, "Name Five", "5550105",
- "five@example.com,nf@example.com,name.five@example.com")
- .returnRow(6, "Name Six", "5550106", "thesix@example.com");
+ .returnRow(1, "Name One", "5550101")
+ .returnRow(2, "Name Two", "5550102")
+ .returnRow(3, "Name Three", null)
+ .returnRow(4, null, "5550104");
final SimContactDao sut = SimContactDao.create(mContext);
final List<SimContact> contacts = sut
- .loadContactsForSim(new SimCard("123", "carrier", "sim", null, "us"));
+ .loadContactsForSim(new SimCard("123", 1, "carrier", "sim", null, "us"));
assertThat(contacts, equalTo(
Arrays.asList(
new SimContact(1, "Name One", "5550101", null),
new SimContact(2, "Name Two", "5550102", null),
new SimContact(3, "Name Three", null, null),
- new SimContact(4, null, "5550104", null),
- new SimContact(5, "Name Five", "5550105", new String[] {
- "five@example.com", "nf@example.com", "name.five@example.com"
- }),
- new SimContact(6, "Name Six", "5550106", new String[] {
- "thesix@example.com"
- })
+ new SimContact(4, null, "5550104", null)
)));
}
@Test
public void excludesEmptyContactsFromResult() {
- mMockIccProvider.expect(MockContentProvider.Query.forAnyUri())
+ mMockSimPhonebookProvider.expect(MockContentProvider.Query.forAnyUri())
.withDefaultProjection(
- SimContactDaoImpl._ID, SimContactDaoImpl.NAME,
- SimContactDaoImpl.NUMBER, SimContactDaoImpl.EMAILS)
+ SimRecords.RECORD_NUMBER, SimRecords.NAME, SimRecords.PHONE_NUMBER)
.withAnyProjection()
.withAnySelection()
.withAnySortOrder()
- .returnRow(1, "Non Empty1", "5550101", null)
- .returnRow(2, "", "", "")
- .returnRow(3, "Non Empty2", null, null)
- .returnRow(4, null, null, null)
- .returnRow(5, "", null, null)
- .returnRow(6, null, "5550102", null)
- .returnRow(7, null, null, "user@example.com");
+ .returnRow(1, "Non Empty1", "5550101")
+ .returnRow(2, "", "")
+ .returnRow(3, "Non Empty2", null)
+ .returnRow(4, null, null)
+ .returnRow(5, "", null)
+ .returnRow(6, null, "5550102");
final SimContactDao sut = SimContactDao.create(mContext);
final List<SimContact> contacts = sut
- .loadContactsForSim(new SimCard("123", "carrier", "sim", null, "us"));
+ .loadContactsForSim(new SimCard("123", 1, "carrier", "sim", null, "us"));
assertThat(contacts, equalTo(
Arrays.asList(
new SimContact(1, "Non Empty1", "5550101", null),
new SimContact(3, "Non Empty2", null, null),
- new SimContact(6, null, "5550102", null),
- new SimContact(7, null, null, new String[] { "user@example.com" })
+ new SimContact(6, null, "5550102", null)
)));
}
@Test
public void usesSimCardSubscriptionIdIfAvailable() {
- mMockIccProvider.expectQuery(SimContactDaoImpl.ICC_CONTENT_URI.buildUpon()
- .appendPath("subId").appendPath("2").build())
+ mMockSimPhonebookProvider.expectQuery(SimRecords.getContentUri(2,
+ SimPhonebookContract.ElementaryFiles.EF_ADN))
.withDefaultProjection(
- SimContactDaoImpl._ID, SimContactDaoImpl.NAME,
- SimContactDaoImpl.NUMBER, SimContactDaoImpl.EMAILS)
+ SimRecords.RECORD_NUMBER, SimRecords.NAME, SimRecords.PHONE_NUMBER)
.withAnyProjection()
.withAnySelection()
.withAnySortOrder()
@@ -671,32 +659,14 @@
final SimContactDao sut = SimContactDao.create(mContext);
sut.loadContactsForSim(new SimCard("123", 2, "carrier", "sim", null, "us"));
- mMockIccProvider.verify();
- }
-
- @Test
- public void omitsSimCardSubscriptionIdIfUnavailable() {
- mMockIccProvider.expectQuery(SimContactDaoImpl.ICC_CONTENT_URI)
- .withDefaultProjection(
- SimContactDaoImpl._ID, SimContactDaoImpl.NAME,
- SimContactDaoImpl.NUMBER, SimContactDaoImpl.EMAILS)
- .withAnyProjection()
- .withAnySelection()
- .withAnySortOrder()
- .returnEmptyCursor();
-
- final SimContactDao sut = SimContactDao.create(mContext);
- sut.loadContactsForSim(new SimCard("123", SimCard.NO_SUBSCRIPTION_ID,
- "carrier", "sim", null, "us"));
- mMockIccProvider.verify();
+ mMockSimPhonebookProvider.verify();
}
@Test
public void returnsEmptyListForEmptyCursor() {
- mMockIccProvider.expect(MockContentProvider.Query.forAnyUri())
+ mMockSimPhonebookProvider.expect(MockContentProvider.Query.forAnyUri())
.withDefaultProjection(
- SimContactDaoImpl._ID, SimContactDaoImpl.NAME,
- SimContactDaoImpl.NUMBER, SimContactDaoImpl.EMAILS)
+ SimRecords.RECORD_NUMBER, SimRecords.NAME, SimRecords.PHONE_NUMBER)
.withAnyProjection()
.withAnySelection()
.withAnySortOrder()
@@ -704,7 +674,7 @@
final SimContactDao sut = SimContactDao.create(mContext);
List<SimContact> result = sut
- .loadContactsForSim(new SimCard("123", "carrier", "sim", null, "us"));
+ .loadContactsForSim(new SimCard("123", 1, "carrier", "sim", null, "us"));
assertTrue(result.isEmpty());
}
@@ -725,7 +695,7 @@
final SimContactDao sut = SimContactDao.create(mContext);
final List<SimContact> result = sut
- .loadContactsForSim(new SimCard("123", "carrier", "sim", null, "us"));
+ .loadContactsForSim(new SimCard("123", 1, "carrier", "sim", null, "us"));
assertTrue(result.isEmpty());
}
}
diff --git a/tests/src/com/android/contacts/model/RawContactDeltaListTests.java b/tests/src/com/android/contacts/model/RawContactDeltaListTests.java
index 03e1d4f..d9ff184 100644
--- a/tests/src/com/android/contacts/model/RawContactDeltaListTests.java
+++ b/tests/src/com/android/contacts/model/RawContactDeltaListTests.java
@@ -17,6 +17,8 @@
package com.android.contacts.model;
import android.content.ContentProviderOperation;
+import android.content.ContentProviderResult;
+import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.net.Uri;
@@ -56,6 +58,8 @@
public static final long CONTACT_BOB = 10;
public static final long CONTACT_MARY = 11;
+ public static final long INSERTED_CONTACT_ID = 3;
+
public static final long PHONE_RED = 20;
public static final long PHONE_GREEN = 21;
public static final long PHONE_BLUE = 22;
@@ -182,6 +186,8 @@
static void assertDiffPattern(ArrayList<CPOWrapper> diff, CPOWrapper... pattern) {
assertEquals("Unexpected operations", pattern.length, diff.size());
+
+ ContentProviderResult[] fakeBackReferences = new ContentProviderResult[diff.size()];
for (int i = 0; i < pattern.length; i++) {
final CPOWrapper expected = pattern[i];
final CPOWrapper found = diff.get(i);
@@ -193,21 +199,25 @@
final String foundType = getTypeString(found);
assertEquals("Unexpected type", expectedType, foundType);
- if (CompatUtils.isDeleteCompat(expected)) continue;
-
- try {
- final ContentValues expectedValues = getValues(expected.getOperation());
- final ContentValues foundValues = getValues(found.getOperation());
-
- expectedValues.remove(BaseColumns._ID);
- foundValues.remove(BaseColumns._ID);
-
- assertEquals("Unexpected values", expectedValues, foundValues);
- } catch (NoSuchFieldException e) {
- fail(e.toString());
- } catch (IllegalAccessException e) {
- fail(e.toString());
+ if (CompatUtils.isDeleteCompat(expected)) {
+ continue;
}
+
+ if (CompatUtils.isInsertCompat(found)) {
+ fakeBackReferences[i] = new ContentProviderResult(
+ ContentUris.withAppendedId(RawContacts.CONTENT_URI, INSERTED_CONTACT_ID));
+ } else if (CompatUtils.isUpdateCompat(found)) {
+ fakeBackReferences[i] = new ContentProviderResult(1);
+ }
+
+
+ ContentValues expectedValues = expected.getOperation().resolveValueBackReferences(
+ new ContentProviderResult[0], 0);
+ ContentValues foundValues = found.getOperation().resolveValueBackReferences(
+ fakeBackReferences, fakeBackReferences.length);
+ expectedValues.remove(BaseColumns._ID);
+ foundValues.remove(BaseColumns._ID);
+ assertEquals("Unexpected values", expectedValues, foundValues);
}
}
@@ -247,6 +257,7 @@
static CPOWrapper buildUpdateAggregationKeepTogether(long rawContactId) {
final ContentValues values = new ContentValues();
values.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId);
+ values.put(AggregationExceptions.RAW_CONTACT_ID2, INSERTED_CONTACT_ID);
values.put(AggregationExceptions.TYPE, AggregationExceptions.TYPE_KEEP_TOGETHER);
return buildCPOWrapper(AggregationExceptions.CONTENT_URI, TYPE_UPDATE, values);
}
@@ -462,7 +473,8 @@
assertDiffPattern(first,
buildAssertVersion(VER_FIRST),
buildUpdateAggregationSuspended(),
- buildCPOWrapper(Data.CONTENT_URI, TYPE_INSERT, buildDataInsert(bluePhone, CONTACT_BOB)),
+ buildCPOWrapper(Data.CONTENT_URI, TYPE_INSERT,
+ buildDataInsert(bluePhone, CONTACT_BOB)),
buildUpdateAggregationDefault());
// Merge in the second version, verify that our insert remains
@@ -470,7 +482,8 @@
assertDiffPattern(merged,
buildAssertVersion(VER_SECOND),
buildUpdateAggregationSuspended(),
- buildCPOWrapper(Data.CONTENT_URI, TYPE_INSERT, buildDataInsert(bluePhone, CONTACT_BOB)),
+ buildCPOWrapper(Data.CONTENT_URI, TYPE_INSERT,
+ buildDataInsert(bluePhone, CONTACT_BOB)),
buildUpdateAggregationDefault());
}
@@ -479,10 +492,11 @@
VER_FIRST, buildPhone(PHONE_RED)));
final RawContactDeltaList second = buildSet(buildBeforeEntity(mContext, CONTACT_BOB,
VER_SECOND, buildPhone(PHONE_RED)), buildBeforeEntity(mContext, CONTACT_MARY,
- VER_SECOND, buildPhone(PHONE_RED)));
+ VER_SECOND, buildPhone(PHONE_RED)));
// Add new contact locally, should remain insert
final ContentValues joePhoneInsert = buildPhone(PHONE_BLUE);
+ joePhoneInsert.put(Data.RAW_CONTACT_ID, INSERTED_CONTACT_ID);
final RawContactDelta joeContact = buildAfterEntity(joePhoneInsert);
final ContentValues joeContactInsert = joeContact.getValues().getCompleteValues();
joeContactInsert.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_SUSPENDED);
@@ -542,6 +556,7 @@
buildUpdateAggregationDefault());
final ContentValues phoneInsert = phone.getCompleteValues();
+ phoneInsert.put(Data.RAW_CONTACT_ID, INSERTED_CONTACT_ID);
final ContentValues contactInsert = first.getByRawContactId(CONTACT_MARY).getValues()
.getCompleteValues();
contactInsert.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_SUSPENDED);
@@ -562,11 +577,11 @@
final RawContactDeltaList second = buildSet(buildBeforeEntity(mContext, CONTACT_BOB,
VER_SECOND, buildPhone(PHONE_RED)));
- assertEquals((Long)VER_FIRST, getVersion(first, CONTACT_BOB));
- assertEquals((Long)VER_SECOND, getVersion(second, CONTACT_BOB));
+ assertEquals((Long) VER_FIRST, getVersion(first, CONTACT_BOB));
+ assertEquals((Long) VER_SECOND, getVersion(second, CONTACT_BOB));
final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first);
- assertEquals((Long)VER_SECOND, getVersion(merged, CONTACT_BOB));
+ assertEquals((Long) VER_SECOND, getVersion(merged, CONTACT_BOB));
}
public void testMergeAfterEnsureAndTrim() {
@@ -585,7 +600,8 @@
assertDiffPattern(first,
buildAssertVersion(VER_FIRST),
buildUpdateAggregationSuspended(),
- buildCPOWrapper(Data.CONTENT_URI, TYPE_INSERT, buildDataInsert(bobPhone, CONTACT_BOB)),
+ buildCPOWrapper(Data.CONTENT_URI, TYPE_INSERT,
+ buildDataInsert(bobPhone, CONTACT_BOB)),
buildUpdateAggregationDefault());
// Trim values and ensure that we don't insert things
diff --git a/tests/src/com/android/contacts/tests/FakeSimContactDao.java b/tests/src/com/android/contacts/tests/FakeSimContactDao.java
index c40ab25..ab6c653 100644
--- a/tests/src/com/android/contacts/tests/FakeSimContactDao.java
+++ b/tests/src/com/android/contacts/tests/FakeSimContactDao.java
@@ -110,5 +110,4 @@
result.canReadSimContacts = false;
return result;
}
-
}
diff --git a/tests/src/com/android/contacts/tests/SimContactsTestHelper.java b/tests/src/com/android/contacts/tests/SimContactsTestHelper.java
index 740d013..99c95cb 100644
--- a/tests/src/com/android/contacts/tests/SimContactsTestHelper.java
+++ b/tests/src/com/android/contacts/tests/SimContactsTestHelper.java
@@ -28,13 +28,15 @@
import android.database.Cursor;
import android.net.Uri;
import android.os.RemoteException;
+import android.provider.SimPhonebookContract;
+import android.provider.SimPhonebookContract.ElementaryFiles;
+import android.provider.SimPhonebookContract.SimRecords;
import android.telephony.TelephonyManager;
import androidx.annotation.NonNull;
import androidx.test.InstrumentationRegistry;
import com.android.contacts.database.SimContactDao;
-import com.android.contacts.database.SimContactDaoImpl;
import com.android.contacts.model.SimCard;
import com.android.contacts.model.SimContact;
@@ -47,6 +49,8 @@
private final TelephonyManager mTelephonyManager;
private final ContentResolver mResolver;
private final SimContactDao mSimDao;
+ private final int mSubscriptionId;
+ private final Uri mDefaultSimAdnUri;
public SimContactsTestHelper() {
this(InstrumentationRegistry.getTargetContext());
@@ -57,10 +61,13 @@
mResolver = context.getContentResolver();
mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
mSimDao = SimContactDao.create(context);
+ mSubscriptionId = mTelephonyManager.getSubscriptionId();
+ mDefaultSimAdnUri = SimRecords.getContentUri(
+ mTelephonyManager.getSubscriptionId(), ElementaryFiles.EF_ADN);
}
public int getSimContactCount() {
- Cursor cursor = mContext.getContentResolver().query(SimContactDaoImpl.ICC_CONTENT_URI,
+ Cursor cursor = mContext.getContentResolver().query(mDefaultSimAdnUri,
null, null, null, null);
try {
return cursor.getCount();
@@ -71,15 +78,13 @@
public Uri addSimContact(String name, String number) {
ContentValues values = new ContentValues();
- // Oddly even though it's called name when querying we have to use "tag" for it to work
- // when inserting.
if (name != null) {
- values.put("tag", name);
+ values.put(SimRecords.NAME, name);
}
if (number != null) {
- values.put(SimContactDaoImpl.NUMBER, number);
+ values.put(SimRecords.PHONE_NUMBER, number);
}
- return mResolver.insert(SimContactDaoImpl.ICC_CONTENT_URI, values);
+ return mResolver.insert(mDefaultSimAdnUri, values);
}
public ContentProviderResult[] deleteAllSimContacts()
@@ -92,11 +97,11 @@
ArrayList<ContentProviderOperation> ops = new ArrayList<>();
for (SimContact contact : contacts) {
ops.add(ContentProviderOperation
- .newDelete(SimContactDaoImpl.ICC_CONTENT_URI)
- .withSelection(getWriteSelection(contact), null)
+ .newDelete(SimRecords.getItemUri(
+ mSubscriptionId, ElementaryFiles.EF_ADN, contact.getRecordNumber()))
.build());
}
- return mResolver.applyBatch(SimContactDaoImpl.ICC_CONTENT_URI.getAuthority(), ops);
+ return mResolver.applyBatch(SimPhonebookContract.AUTHORITY, ops);
}
public ContentProviderResult[] restore(ArrayList<ContentProviderOperation> restoreOps)
@@ -106,7 +111,7 @@
// Remove SIM contacts because we assume that caller wants the data to be in the exact
// state as when the restore ops were captured.
deleteAllSimContacts();
- return mResolver.applyBatch(SimContactDaoImpl.ICC_CONTENT_URI.getAuthority(), restoreOps);
+ return mResolver.applyBatch(SimPhonebookContract.AUTHORITY, restoreOps);
}
public ArrayList<ContentProviderOperation> captureRestoreSnapshot() {
@@ -124,24 +129,16 @@
" Please manually remove SIM contacts with emails.");
}
ops.add(ContentProviderOperation
- .newInsert(SimContactDaoImpl.ICC_CONTENT_URI)
- .withValue("tag", contact.getName())
- .withValue("number", contact.getPhone())
+ .newInsert(mDefaultSimAdnUri)
+ .withValue(SimRecords.NAME, contact.getName())
+ .withValue(SimRecords.PHONE_NUMBER, contact.getPhone())
.build());
}
return ops;
}
- public String getWriteSelection(SimContact simContact) {
- return "tag='" + simContact.getName() + "' AND " + SimContactDaoImpl.NUMBER + "='" +
- simContact.getPhone() + "'";
- }
-
- public int deleteSimContact(@NonNull String name, @NonNull String number) {
- // IccProvider doesn't use the selection args.
- final String selection = "tag='" + name + "' AND " +
- SimContactDaoImpl.NUMBER + "='" + number + "'";
- return mResolver.delete(SimContactDaoImpl.ICC_CONTENT_URI, selection, null);
+ public int deleteSimContact(@NonNull Uri recordUri) {
+ return mResolver.delete(recordUri, null);
}
public boolean isSimReady() {
@@ -156,7 +153,7 @@
if (!isSimReady()) return false;
final String name = "writabeProbe" + System.nanoTime();
final Uri uri = addSimContact(name, "15095550101");
- return uri != null && deleteSimContact(name, "15095550101") == 1;
+ return uri != null && deleteSimContact(uri) == 1;
}
public void assumeSimReady() {