SimContact.java revision a75206b1cba895ce629b9383e4fd0fef24049e7b
1819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott/*
2819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott * Copyright (C) 2016 The Android Open Source Project
3819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott *
4819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott * Licensed under the Apache License, Version 2.0 (the "License");
5819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott * you may not use this file except in compliance with the License.
6819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott * You may obtain a copy of the License at
7819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott *
8819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott *      http://www.apache.org/licenses/LICENSE-2.0
9819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott *
10819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott * Unless required by applicable law or agreed to in writing, software
11819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott * distributed under the License is distributed on an "AS IS" BASIS,
12819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott * See the License for the specific language governing permissions and
14819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott * limitations under the License.
15819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott */
16819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerottpackage com.android.contacts.common.model;
17819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott
18819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerottimport android.content.ContentProviderOperation;
19819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerottimport android.database.MatrixCursor;
20819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerottimport android.net.Uri;
21819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerottimport android.os.Parcel;
22819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerottimport android.os.Parcelable;
23819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerottimport android.provider.ContactsContract;
24819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerottimport android.provider.ContactsContract.CommonDataKinds.Email;
25819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerottimport android.provider.ContactsContract.CommonDataKinds.Phone;
26819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerottimport android.provider.ContactsContract.CommonDataKinds.StructuredName;
27a75206b1cba895ce629b9383e4fd0fef24049e7bMarcus Hagerottimport android.text.TextUtils;
28819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott
29819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerottimport com.android.contacts.common.model.account.AccountWithDataSet;
302aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerottimport com.google.common.collect.ComparisonChain;
312aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerottimport com.google.common.collect.Ordering;
32819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott
33819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerottimport java.util.Arrays;
34819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerottimport java.util.Collection;
352aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerottimport java.util.Collections;
362aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerottimport java.util.Comparator;
37819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerottimport java.util.List;
382aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerottimport java.util.Objects;
39819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott
40819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott/**
41819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott * Holds data for contacts loaded from the SIM card.
42819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott */
43819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerottpublic class SimContact implements Parcelable {
44819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    private final long mId;
45819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    private final String mName;
46819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    private final String mPhone;
47819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    private final String[] mEmails;
48819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott
49a75206b1cba895ce629b9383e4fd0fef24049e7bMarcus Hagerott    public SimContact(long id, String name, String phone) {
50a75206b1cba895ce629b9383e4fd0fef24049e7bMarcus Hagerott        this(id, name, phone, null);
51a75206b1cba895ce629b9383e4fd0fef24049e7bMarcus Hagerott    }
52a75206b1cba895ce629b9383e4fd0fef24049e7bMarcus Hagerott
53819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    public SimContact(long id, String name, String phone, String[] emails) {
542aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott        mId = id;
552aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott        mName = name;
5619d7ecafdf245ef8895f94b62253bf6dc73f5a17Marcus Hagerott        mPhone = phone == null ? "" : phone.trim();
572aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott        mEmails = emails;
582aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott    }
596c42b4c3cdfa23031b7cad5d90b68647b75a3948Marcus Hagerott
60a75206b1cba895ce629b9383e4fd0fef24049e7bMarcus Hagerott    public SimContact(SimContact other) {
61a75206b1cba895ce629b9383e4fd0fef24049e7bMarcus Hagerott        this(other.mId, other.mName, other.mPhone, other.mEmails);
62a75206b1cba895ce629b9383e4fd0fef24049e7bMarcus Hagerott    }
63a75206b1cba895ce629b9383e4fd0fef24049e7bMarcus Hagerott
64819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    public long getId() {
65819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        return mId;
66819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    }
67819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott
68819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    public String getName() {
69819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        return mName;
70819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    }
71819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott
72819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    public String getPhone() {
73819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        return mPhone;
74819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    }
75819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott
76819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    public String[] getEmails() {
77819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        return mEmails;
78819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    }
79819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott
80819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    public void appendCreateContactOperations(List<ContentProviderOperation> ops,
81819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott            AccountWithDataSet targetAccount) {
828e9e782cb7f15a8bcca3335374f641d5a149a5a2Marcus Hagerott        // There is nothing to save so skip it.
838e9e782cb7f15a8bcca3335374f641d5a149a5a2Marcus Hagerott        if (!hasName() && !hasPhone() && !hasEmails()) return;
84819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott
85819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        final int rawContactOpIndex = ops.size();
86819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
87819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott                .withYieldAllowed(true)
88819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott                .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, targetAccount.name)
89819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott                .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, targetAccount.type)
90819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott                .withValue(ContactsContract.RawContacts.DATA_SET, targetAccount.dataSet)
91819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott                .build());
92819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        if (mName != null) {
93819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott            ops.add(createInsertOp(rawContactOpIndex, StructuredName.CONTENT_ITEM_TYPE,
94819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott                    StructuredName.DISPLAY_NAME, mName));
95819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        }
9619d7ecafdf245ef8895f94b62253bf6dc73f5a17Marcus Hagerott        if (!mPhone.isEmpty()) {
97819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott            ops.add(createInsertOp(rawContactOpIndex, Phone.CONTENT_ITEM_TYPE,
98819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott                    Phone.NUMBER, mPhone));
99819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        }
100819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        if (mEmails != null) {
101819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott            for (String email : mEmails) {
102819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott                ops.add(createInsertOp(rawContactOpIndex, Email.CONTENT_ITEM_TYPE,
103819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott                        Email.ADDRESS, email));
104819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott            }
105819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        }
106819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    }
107819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott
108819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    private ContentProviderOperation createInsertOp(int rawContactOpIndex, String mimeType,
109819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott            String column, String value) {
110819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        return ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
111819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactOpIndex)
112819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott                .withValue(ContactsContract.Data.MIMETYPE, mimeType)
113819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott                .withValue(column, value)
114819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott                .build();
115819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    }
116819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott
117819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    public void appendAsContactRow(MatrixCursor cursor) {
118819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        cursor.newRow().add(ContactsContract.Contacts._ID, mId)
119819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott                .add(ContactsContract.Contacts.DISPLAY_NAME_PRIMARY, mName)
120819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott                .add(ContactsContract.Contacts.LOOKUP_KEY, getLookupKey());
121819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    }
122819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott
1232aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott    public boolean hasName() {
124a75206b1cba895ce629b9383e4fd0fef24049e7bMarcus Hagerott        return !TextUtils.isEmpty(mName);
1252aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott    }
1262aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott
1272aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott    public boolean hasPhone() {
12819d7ecafdf245ef8895f94b62253bf6dc73f5a17Marcus Hagerott        return !mPhone.isEmpty();
1292aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott    }
1302aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott
1312aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott    public boolean hasEmails() {
1322aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott        return mEmails != null && mEmails.length > 0;
1332aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott    }
1342aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott
135819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    /**
136819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott     * Generate a "fake" lookup key. This is needed because
137819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott     * {@link com.android.contacts.common.ContactPhotoManager} will only generate a letter avatar
138819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott     * if the contact has a lookup key.
139819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott     */
140819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    private String getLookupKey() {
141819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        if (mName != null) {
142819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott            return "sim-n-" + Uri.encode(mName);
143819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        } else if (mPhone != null) {
144819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott            return "sim-p-" + Uri.encode(mPhone);
145819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        } else {
146819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott            return null;
147819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        }
148819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    }
149819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott
150819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    @Override
151819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    public String toString() {
152819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        return "SimContact{" +
153819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott                "mId=" + mId +
154819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott                ", mName='" + mName + '\'' +
155819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott                ", mPhone='" + mPhone + '\'' +
156819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott                ", mEmails=" + Arrays.toString(mEmails) +
157819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott                '}';
158819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    }
159819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott
160819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    @Override
161819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    public boolean equals(Object o) {
162819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        if (this == o) return true;
163819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        if (o == null || getClass() != o.getClass()) return false;
164819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott
165819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        final SimContact that = (SimContact) o;
166819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott
1676c42b4c3cdfa23031b7cad5d90b68647b75a3948Marcus Hagerott        return mId == that.mId && Objects.equals(mName, that.mName) &&
1686c42b4c3cdfa23031b7cad5d90b68647b75a3948Marcus Hagerott                Objects.equals(mPhone, that.mPhone) && Arrays.equals(mEmails, that.mEmails);
169819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    }
170819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott
171819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    @Override
172819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    public int hashCode() {
173819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        int result = (int) (mId ^ (mId >>> 32));
174819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        result = 31 * result + (mName != null ? mName.hashCode() : 0);
175819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        result = 31 * result + (mPhone != null ? mPhone.hashCode() : 0);
176819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        result = 31 * result + Arrays.hashCode(mEmails);
177819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        return result;
178819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    }
179819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott
180819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    @Override
181819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    public int describeContents() {
182819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        return 0;
183819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    }
184819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott
185819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    @Override
186819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    public void writeToParcel(Parcel dest, int flags) {
187819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        dest.writeLong(mId);
188819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        dest.writeString(mName);
189819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        dest.writeString(mPhone);
190819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        dest.writeStringArray(mEmails);
191819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    }
192819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott
1936c42b4c3cdfa23031b7cad5d90b68647b75a3948Marcus Hagerott    public static final Creator<SimContact> CREATOR = new Creator<SimContact>() {
1946c42b4c3cdfa23031b7cad5d90b68647b75a3948Marcus Hagerott        @Override
1956c42b4c3cdfa23031b7cad5d90b68647b75a3948Marcus Hagerott        public SimContact createFromParcel(Parcel source) {
1966c42b4c3cdfa23031b7cad5d90b68647b75a3948Marcus Hagerott            final long id = source.readLong();
1976c42b4c3cdfa23031b7cad5d90b68647b75a3948Marcus Hagerott            final String name = source.readString();
1986c42b4c3cdfa23031b7cad5d90b68647b75a3948Marcus Hagerott            final String phone = source.readString();
1996c42b4c3cdfa23031b7cad5d90b68647b75a3948Marcus Hagerott            final String[] emails = source.createStringArray();
2006c42b4c3cdfa23031b7cad5d90b68647b75a3948Marcus Hagerott            return new SimContact(id, name, phone, emails);
2016c42b4c3cdfa23031b7cad5d90b68647b75a3948Marcus Hagerott        }
2026c42b4c3cdfa23031b7cad5d90b68647b75a3948Marcus Hagerott
2036c42b4c3cdfa23031b7cad5d90b68647b75a3948Marcus Hagerott        @Override
2046c42b4c3cdfa23031b7cad5d90b68647b75a3948Marcus Hagerott        public SimContact[] newArray(int size) {
2056c42b4c3cdfa23031b7cad5d90b68647b75a3948Marcus Hagerott            return new SimContact[size];
2066c42b4c3cdfa23031b7cad5d90b68647b75a3948Marcus Hagerott        }
2076c42b4c3cdfa23031b7cad5d90b68647b75a3948Marcus Hagerott    };
2086c42b4c3cdfa23031b7cad5d90b68647b75a3948Marcus Hagerott
209819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    /**
210819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott     * Convert a collection of SIM contacts to a Cursor matching a query from
211819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott     * {@link android.provider.ContactsContract.Contacts#CONTENT_URI} with the provided projection.
212819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott     *
213819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott     * This allows a collection of SIM contacts to be displayed using the existing adapters for
214819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott     * contacts.
215819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott     */
216819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    public static final MatrixCursor convertToContactsCursor(Collection<SimContact> contacts,
217819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott            String[] projection) {
218819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        final MatrixCursor result = new MatrixCursor(projection);
219819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        for (SimContact contact : contacts) {
220819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott            contact.appendAsContactRow(result);
221819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        }
222819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott        return result;
223819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott    }
224819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott
2252aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott    /**
2262aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott     * Returns the index of a contact with a matching name and phone
2272aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott     * @param contacts list to search. Should be sorted using
2282aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott     * {@link SimContact#compareByPhoneThenName()}
2292aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott     * @param phone the phone to search for
2302aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott     * @param name the name to search for
2312aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott     */
2322aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott    public static int findByPhoneAndName(List<SimContact> contacts, String phone, String name) {
2336c42b4c3cdfa23031b7cad5d90b68647b75a3948Marcus Hagerott        return Collections.binarySearch(contacts, new SimContact(-1, name, phone, null),
2346c42b4c3cdfa23031b7cad5d90b68647b75a3948Marcus Hagerott                compareByPhoneThenName());
2352aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott    }
2362aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott
2372aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott    public static final Comparator<SimContact> compareByPhoneThenName() {
2382aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott        return new Comparator<SimContact>() {
2392aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott            @Override
2402aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott            public int compare(SimContact lhs, SimContact rhs) {
2412aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott                return ComparisonChain.start()
24219d7ecafdf245ef8895f94b62253bf6dc73f5a17Marcus Hagerott                        .compare(lhs.mPhone, rhs.mPhone)
2432aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott                        .compare(lhs.mName, rhs.mName, Ordering.<String>natural().nullsFirst())
2442aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott                        .result();
2452aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott            }
2462aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott        };
2472aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott    }
2482aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott
2492aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott    public static final Comparator<SimContact> compareById() {
2502aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott        return new Comparator<SimContact>() {
2512aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott            @Override
2522aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott            public int compare(SimContact lhs, SimContact rhs) {
2532aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott                // We assume ids are unique.
2542aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott                return Long.compare(lhs.mId, rhs.mId);
2552aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott            }
2562aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott        };
2572aa3198b6881c3272a0295fec85646e7ef2282cfMarcus Hagerott    }
258819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerott}
259