ExchangeDirectoryProvider.java revision 7307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20c
15aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank/*
25aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank * Copyright (C) 2010 The Android Open Source Project
35aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank *
45aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank * Licensed under the Apache License, Version 2.0 (the "License");
55aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank * you may not use this file except in compliance with the License.
65aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank * You may obtain a copy of the License at
75aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank *
85aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank *      http://www.apache.org/licenses/LICENSE-2.0
95aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank *
105aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank * Unless required by applicable law or agreed to in writing, software
115aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank * distributed under the License is distributed on an "AS IS" BASIS,
125aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank * See the License for the specific language governing permissions and
145aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank * limitations under the License.
155aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank */
165aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank
175aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blankpackage com.android.exchange.provider;
185aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank
191f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikovimport com.android.email.R;
207307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blankimport com.android.email.Utility;
211f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikovimport com.android.email.VendorPolicyLoader;
22d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikovimport com.android.email.mail.PackedString;
237307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blankimport com.android.email.provider.EmailContent;
245aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blankimport com.android.email.provider.EmailContent.Account;
257307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blankimport com.android.email.provider.EmailContent.AccountColumns;
265aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blankimport com.android.exchange.EasSyncService;
275aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blankimport com.android.exchange.provider.GalResult.GalData;
285aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank
291f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikovimport android.accounts.AccountManager;
305aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blankimport android.content.ContentProvider;
315aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blankimport android.content.ContentValues;
327307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blankimport android.content.Context;
335aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blankimport android.content.UriMatcher;
345aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blankimport android.database.Cursor;
355aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blankimport android.database.MatrixCursor;
365aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blankimport android.net.Uri;
375aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blankimport android.os.Binder;
38469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blankimport android.provider.ContactsContract;
395aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blankimport android.provider.ContactsContract.CommonDataKinds;
40469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blankimport android.provider.ContactsContract.Contacts;
41469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blankimport android.provider.ContactsContract.Directory;
42469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blankimport android.provider.ContactsContract.RawContacts;
43d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Email;
44d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Phone;
45d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName;
46d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikovimport android.provider.ContactsContract.Contacts.Data;
47d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikovimport android.text.TextUtils;
48d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov
49d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikovimport java.util.HashMap;
50d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikovimport java.util.List;
515aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank
525aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank/**
535aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank * ExchangeDirectoryProvider provides real-time data from the Exchange server; at the moment, it is
545aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank * used solely to provide GAL (Global Address Lookup) service to email address adapters
555aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank */
565aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blankpublic class ExchangeDirectoryProvider extends ContentProvider {
57eb9cccf5c94b043baecb03d06738f7eedef03378Marc Blank    public static final String EXCHANGE_GAL_AUTHORITY = "com.android.exchange.directory.provider";
585aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank
59d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov    private static final int DEFAULT_CONTACT_ID = 1;
60469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank    private static final int DEFAULT_LOOKUP_LIMIT = 20;
61d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov
625aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank    private static final int GAL_BASE = 0;
631f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov    private static final int GAL_DIRECTORIES = GAL_BASE;
641f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov    private static final int GAL_FILTER = GAL_BASE + 1;
651f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov    private static final int GAL_CONTACT = GAL_BASE + 2;
661f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov    private static final int GAL_CONTACT_WITH_ID = GAL_BASE + 3;
67f6e831704c7df2b841760931469b1e995b957cd9Dmitri Plotnikov    private static final int GAL_EMAIL_FILTER = GAL_BASE + 4;
685aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank
695aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank    private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
707307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank    /*package*/ final HashMap<String, Long> mAccountIdMap = new HashMap<String, Long>();
715aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank
725aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank    static {
731f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov        sURIMatcher.addURI(EXCHANGE_GAL_AUTHORITY, "directories", GAL_DIRECTORIES);
745aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank        sURIMatcher.addURI(EXCHANGE_GAL_AUTHORITY, "contacts/filter/*", GAL_FILTER);
751f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov        sURIMatcher.addURI(EXCHANGE_GAL_AUTHORITY, "contacts/lookup/*/entities", GAL_CONTACT);
76d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov        sURIMatcher.addURI(EXCHANGE_GAL_AUTHORITY, "contacts/lookup/*/#/entities",
77d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                GAL_CONTACT_WITH_ID);
78f6e831704c7df2b841760931469b1e995b957cd9Dmitri Plotnikov        sURIMatcher.addURI(EXCHANGE_GAL_AUTHORITY, "data/emails/filter/*", GAL_EMAIL_FILTER);
795aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank    }
805aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank
815aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank    @Override
825aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank    public boolean onCreate() {
835aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank        return true;
845aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank    }
855aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank
86d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov    static class GalProjection {
87d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov        final int size;
88d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov        final HashMap<String, Integer> columnMap = new HashMap<String, Integer>();
89d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov
90d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov        GalProjection(String[] projection) {
91d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            size = projection.length;
92d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            for (int i = 0; i < projection.length; i++) {
93d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                columnMap.put(projection[i], i);
94d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            }
95d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov        }
96d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov    }
97d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov
98d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov    static class GalContactRow {
99d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov        private final GalProjection mProjection;
100d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov        private Object[] row;
101d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov        static long dataId = 1;
102d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov
103d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov        GalContactRow(GalProjection projection, long contactId, String lookupKey,
104d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                String accountName, String displayName) {
105d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            this.mProjection = projection;
106d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            row = new Object[projection.size];
107d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov
108d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            put(Contacts.Entity.CONTACT_ID, contactId);
109d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov
110d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            // We only have one raw contact per aggregate, so they can have the same ID
111d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            put(Contacts.Entity.RAW_CONTACT_ID, contactId);
112d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            put(Contacts.Entity.DATA_ID, dataId++);
113d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov
114d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            put(Contacts.DISPLAY_NAME, displayName);
115d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov
116d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            // TODO alternative display name
117d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            put(Contacts.DISPLAY_NAME_ALTERNATIVE, displayName);
118d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov
119d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            put(RawContacts.ACCOUNT_TYPE, com.android.email.Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
120d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            put(RawContacts.ACCOUNT_NAME, accountName);
121d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            put(RawContacts.RAW_CONTACT_IS_READ_ONLY, 1);
122d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            put(Data.IS_READ_ONLY, 1);
123d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov        }
124d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov
125d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov        Object[] getRow () {
126d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            return row;
127d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov        }
128d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov
129d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov        void put(String columnName, Object value) {
130d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            Integer integer = mProjection.columnMap.get(columnName);
131d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            if (integer != null) {
132d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                row[integer] = value;
133d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            } else {
134d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                System.out.println("Unsupported column: " + columnName);
135d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            }
136d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov        }
137d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov
138d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov        static void addEmailAddress(MatrixCursor cursor, GalProjection galProjection,
139d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                long contactId, String lookupKey, String accountName, String displayName,
140d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                String address) {
141d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            if (!TextUtils.isEmpty(address)) {
142d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                GalContactRow r = new GalContactRow(
143d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                        galProjection, contactId, lookupKey, accountName, displayName);
144d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                r.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
145d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                r.put(Email.TYPE, Email.TYPE_WORK);
146d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                r.put(Email.ADDRESS, address);
147d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                cursor.addRow(r.getRow());
148d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            }
149d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov        }
150d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov
151d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov        static void addPhoneRow(MatrixCursor cursor, GalProjection projection, long contactId,
152d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                String lookupKey, String accountName, String displayName, int type, String number) {
153d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            if (!TextUtils.isEmpty(number)) {
154d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                GalContactRow r = new GalContactRow(
155d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                        projection, contactId, lookupKey, accountName, displayName);
156d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                r.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
157d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                r.put(Phone.TYPE, type);
158d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                r.put(Phone.NUMBER, number);
159d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                cursor.addRow(r.getRow());
160d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            }
161d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov        }
162d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov
163d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov        public static void addNameRow(MatrixCursor cursor, GalProjection galProjection,
164d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                long contactId, String lookupKey, String accountName, String displayName,
165d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                String firstName, String lastName) {
166d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            GalContactRow r = new GalContactRow(
167d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                    galProjection, contactId, lookupKey, accountName, displayName);
168d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            r.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
169d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            r.put(StructuredName.GIVEN_NAME, firstName);
170d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            r.put(StructuredName.FAMILY_NAME, lastName);
171d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            r.put(StructuredName.DISPLAY_NAME, displayName);
172d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            cursor.addRow(r.getRow());
173d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov        }
174d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov    }
175d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov
1767307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank    /**
1777307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank     * Find the record id of an Account, given its name (email address)
1787307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank     * @param accountName the name of the account
1797307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank     * @return the record id of the Account, or -1 if not found
1807307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank     */
1817307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank    /*package*/ long getAccountIdByName(Context context, String accountName) {
1827307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank        Long accountId = mAccountIdMap.get(accountName);
1837307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank        if (accountId == null) {
1847307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank            accountId = Utility.getFirstRowLong(context, Account.CONTENT_URI,
1857307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank                    EmailContent.ID_PROJECTION, AccountColumns.EMAIL_ADDRESS + "=?",
1867307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank                    new String[] {accountName}, null, EmailContent.ID_PROJECTION_COLUMN , -1L);
1877307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank            if (accountId != -1) {
1887307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank                mAccountIdMap.put(accountName, accountId);
1897307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank            }
1907307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank        }
1917307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank        return accountId;
1927307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank    }
1937307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank
1945aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank    @Override
1955aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
1965aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank            String sortOrder) {
1975aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank        int match = sURIMatcher.match(uri);
198d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov        MatrixCursor cursor;
199d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov        Object[] row;
200d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov        PackedString ps;
201d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov        String lookupKey;
202d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov
2035aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank        switch (match) {
2041f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov            case GAL_DIRECTORIES: {
2051f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                // Assuming that GAL can be used with all exchange accounts
2061f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                android.accounts.Account[] accounts = AccountManager.get(getContext())
2071f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                        .getAccountsByType(com.android.email.Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
2081f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                cursor = new MatrixCursor(projection);
2091f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                if (accounts != null) {
2101f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                    for (android.accounts.Account account : accounts) {
2111f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                        row = new Object[projection.length];
2121f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov
2131f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                        for (int i = 0; i < projection.length; i++) {
2141f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                            String column = projection[i];
2151f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                            if (column.equals(Directory.ACCOUNT_NAME)) {
2161f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                                row[i] = account.name;
2171f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                            } else if (column.equals(Directory.ACCOUNT_TYPE)) {
2181f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                                row[i] = account.type;
2191f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                            } else if (column.equals(Directory.TYPE_RESOURCE_ID)) {
2201f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                                if (VendorPolicyLoader.getInstance(getContext())
2211f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                                        .useAlternateExchangeStrings()) {
2221f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                                    row[i] = R.string.exchange_name_alternate;
2231f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                                } else {
2241f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                                    row[i] = R.string.exchange_name;
2251f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                                }
2261f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                            } else if (column.equals(Directory.DISPLAY_NAME)) {
2271f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                                row[i] = account.name;
2281f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                            } else if (column.equals(Directory.EXPORT_SUPPORT)) {
2291f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                                row[i] = Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY;
2301f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                            } else if (column.equals(Directory.SHORTCUT_SUPPORT)) {
2311f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                                row[i] = Directory.SHORTCUT_SUPPORT_FULL;
2321f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                            }
2331f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                        }
2341f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                        cursor.addRow(row);
2351f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                    }
2361f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                }
2371f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                return cursor;
2381f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov            }
2391f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov
240f6e831704c7df2b841760931469b1e995b957cd9Dmitri Plotnikov            case GAL_FILTER:
241f6e831704c7df2b841760931469b1e995b957cd9Dmitri Plotnikov            case GAL_EMAIL_FILTER: {
2425aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank                String filter = uri.getLastPathSegment();
2435aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank                // We should have at least two characters before doing a GAL search
2445aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank                if (filter == null || filter.length() < 2) {
2455aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank                    return null;
2465aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank                }
2471f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov
2481f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME);
2491f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                if (accountName == null) {
2501f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                    return null;
2511f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                }
2521f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov
253469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank                // Enforce a limit on the number of lookup responses
254469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank                String limitString = uri.getQueryParameter(ContactsContract.LIMIT_PARAM_KEY);
255469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank                int limit = DEFAULT_LOOKUP_LIMIT;
256469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank                if (limitString != null) {
257469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank                    try {
258469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank                        limit = Integer.parseInt(limitString);
259469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank                    } catch (NumberFormatException e) {
260469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank                        limit = 0;
261469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank                    }
262469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank                    if (limit <= 0) {
263469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank                        throw new IllegalArgumentException("Limit not valid: " + limitString);
264469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank                    }
265469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank                }
266469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank
2675aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank                long callingId = Binder.clearCallingIdentity();
2685aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank                try {
2697307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank                    // Find the account id to pass along to EasSyncService
2707307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank                    long accountId = getAccountIdByName(getContext(), accountName);
2717307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank                    if (accountId == -1) {
2727307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank                        // The account was deleted?
2737307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank                        return null;
2747307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank                    }
2757307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank
2765aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank                    // Get results from the Exchange account
2777307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank                    GalResult galResult = EasSyncService.searchGal(getContext(), accountId,
278469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank                            filter, limit);
2795aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank                    if (galResult != null) {
2805aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank                        return buildGalResultCursor(projection, galResult);
2815aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank                    }
2825aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank                } finally {
2835aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank                    Binder.restoreCallingIdentity(callingId);
2845aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank                }
2855aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank                break;
286d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            }
287d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov
288d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            case GAL_CONTACT:
289d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            case GAL_CONTACT_WITH_ID: {
2901f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME);
2911f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                if (accountName == null) {
2921f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                    return null;
2931f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                }
2941f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov
295d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                GalProjection galProjection = new GalProjection(projection);
296d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                cursor = new MatrixCursor(projection);
297d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                // Handle the decomposition of the key into rows suitable for CP2
2981f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov                List<String> pathSegments = uri.getPathSegments();
299d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                lookupKey = pathSegments.get(2);
300d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                long contactId = (match == GAL_CONTACT_WITH_ID)
301d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                        ? Long.parseLong(pathSegments.get(3))
302d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                        : DEFAULT_CONTACT_ID;
303d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                ps = new PackedString(lookupKey);
304d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                String displayName = ps.get(GalData.DISPLAY_NAME);
305d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                GalContactRow.addEmailAddress(cursor, galProjection, contactId, lookupKey,
306d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                        accountName, displayName, ps.get(GalData.EMAIL_ADDRESS));
307d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                GalContactRow.addPhoneRow(cursor, galProjection, contactId, accountName,
308d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                        displayName, displayName, Phone.TYPE_HOME, ps.get(GalData.HOME_PHONE));
309d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                GalContactRow.addPhoneRow(cursor, galProjection, contactId, accountName,
310d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                        displayName, displayName, Phone.TYPE_WORK, ps.get(GalData.WORK_PHONE));
311d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                GalContactRow.addPhoneRow(cursor, galProjection, contactId, accountName,
312d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                        displayName, displayName, Phone.TYPE_MOBILE, ps.get(GalData.MOBILE_PHONE));
313d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                GalContactRow.addNameRow(cursor, galProjection, contactId, accountName, displayName,
314d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                        ps.get(GalData.FIRST_NAME), ps.get(GalData.LAST_NAME), displayName);
315d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                return cursor;
316d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            }
3175aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank        }
3185aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank
3195aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank        return null;
3205aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank    }
3215aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank
3225aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank    /*package*/ Cursor buildGalResultCursor(String[] projection, GalResult galResult) {
3235aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank        int displayNameIndex = -1;
324d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov        int alternateDisplayNameIndex = -1;;
3255aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank        int emailIndex = -1;
326d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov        int idIndex = -1;
327d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov        int lookupIndex = -1;
3285aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank
3295aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank        for (int i = 0; i < projection.length; i++) {
3305aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank            String column = projection[i];
3315aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank            if (Contacts.DISPLAY_NAME.equals(column) ||
3325aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank                    Contacts.DISPLAY_NAME_PRIMARY.equals(column)) {
3335aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank                displayNameIndex = i;
3345aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank            } else if (Contacts.DISPLAY_NAME_ALTERNATIVE.equals(column)) {
335d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                alternateDisplayNameIndex = i;
3365aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank            } else if (CommonDataKinds.Email.ADDRESS.equals(column)) {
3375aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank                emailIndex = i;
338d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            } else if (Contacts._ID.equals(column)) {
339d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                idIndex = i;
340d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            } else if (Contacts.LOOKUP_KEY.equals(column)) {
341d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                lookupIndex = i;
3425aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank            }
3435aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank        }
3445aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank
3455aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank        Object[] row = new Object[projection.length];
3465aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank
3475aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank        /*
3485aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank         * ContactsProvider will ensure that every request has a non-null projection.
3495aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank         */
3505aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank        MatrixCursor cursor = new MatrixCursor(projection);
3515aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank        int count = galResult.galData.size();
3525aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank        for (int i = 0; i < count; i++) {
3535aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank            GalData galDataRow = galResult.galData.get(i);
354d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            String firstName = galDataRow.get(GalData.FIRST_NAME);
355d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            String lastName = galDataRow.get(GalData.LAST_NAME);
356d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            String displayName = galDataRow.get(GalData.DISPLAY_NAME);
357d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            // If we don't have a display name, try to create one using first and last name
358d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            if (displayName == null) {
359d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                if (firstName != null && lastName != null) {
360d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                    displayName = firstName + " " + lastName;
361d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                } else if (firstName != null) {
362d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                    displayName = firstName;
363d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                } else if (lastName != null) {
364d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                    displayName = lastName;
365d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                }
366d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            }
367d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            galDataRow.put(GalData.DISPLAY_NAME, displayName);
368d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov
3695aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank            if (displayNameIndex != -1) {
370d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                row[displayNameIndex] = displayName;
371d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            }
372d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            if (alternateDisplayNameIndex != -1) {
373d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                // Try to create an alternate display name, using first and last name
374d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                // TODO: Check with Contacts team to make sure we're using this properly
375d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                if (firstName != null && lastName != null) {
376d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                    row[alternateDisplayNameIndex] = lastName + " " + firstName;
377d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                } else {
378d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                    row[alternateDisplayNameIndex] = displayName;
379d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                }
3805aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank            }
3815aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank            if (emailIndex != -1) {
382d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                row[emailIndex] = galDataRow.get(GalData.EMAIL_ADDRESS);
383d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            }
384d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            if (idIndex != -1) {
385d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                row[idIndex] = i + 1;  // Let's be 1 based
386d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            }
387d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov            if (lookupIndex != -1) {
388d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                // We use the packed string as our lookup key; it contains ALL of the gal data
389d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                // We do this because we are not able to provide a stable id to ContactsProvider
390d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov                row[lookupIndex] = Uri.encode(galDataRow.toPackedString());
3915aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank            }
3925aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank            cursor.addRow(row);
3935aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank        }
3945aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank        return cursor;
3955aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank    }
3965aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank
3975aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank    @Override
3985aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank    public String getType(Uri uri) {
3995aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank        int match = sURIMatcher.match(uri);
4005aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank        switch (match) {
4015aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank            case GAL_FILTER:
4025aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank                return Contacts.CONTENT_ITEM_TYPE;
4035aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank        }
4045aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank        return null;
4055aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank    }
4065aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank
4075aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank    @Override
4085aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank    public int delete(Uri uri, String selection, String[] selectionArgs) {
4095aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank        throw new UnsupportedOperationException();
4105aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank    }
4115aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank
4125aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank    @Override
4135aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank    public Uri insert(Uri uri, ContentValues values) {
4145aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank        throw new UnsupportedOperationException();
4155aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank    }
4165aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank
4175aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank    @Override
4185aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
4195aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank        throw new UnsupportedOperationException();
4205aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank    }
4215aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank}
422