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 19c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blankimport com.android.emailcommon.Configuration; 20c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blankimport com.android.emailcommon.mail.PackedString; 217372782488977df778a33d990401ce9e397f646bMarc Blankimport com.android.emailcommon.provider.Account; 22c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blankimport com.android.emailcommon.provider.EmailContent; 23c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blankimport com.android.emailcommon.provider.EmailContent.AccountColumns; 24c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blankimport com.android.emailcommon.service.AccountServiceProxy; 25c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blankimport com.android.emailcommon.utility.Utility; 26c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blankimport com.android.exchange.Eas; 275aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blankimport com.android.exchange.EasSyncService; 28c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blankimport com.android.exchange.R; 295aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blankimport com.android.exchange.provider.GalResult.GalData; 305aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank 311f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikovimport android.accounts.AccountManager; 325aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blankimport android.content.ContentProvider; 335aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blankimport android.content.ContentValues; 347307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blankimport android.content.Context; 355aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blankimport android.content.UriMatcher; 365aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blankimport android.database.Cursor; 375aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blankimport android.database.MatrixCursor; 385aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blankimport android.net.Uri; 395aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blankimport android.os.Binder; 40c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blankimport android.os.Bundle; 41c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blankimport android.os.RemoteException; 42469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blankimport android.provider.ContactsContract; 435aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blankimport android.provider.ContactsContract.CommonDataKinds; 44d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Email; 45d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.Phone; 46d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikovimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 47c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blankimport android.provider.ContactsContract.Contacts; 48d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikovimport android.provider.ContactsContract.Contacts.Data; 49c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blankimport android.provider.ContactsContract.Directory; 50c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blankimport android.provider.ContactsContract.RawContacts; 51d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikovimport android.text.TextUtils; 52d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov 53d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikovimport java.util.HashMap; 54d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikovimport java.util.List; 555aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank 565aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank/** 575aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank * ExchangeDirectoryProvider provides real-time data from the Exchange server; at the moment, it is 585aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank * used solely to provide GAL (Global Address Lookup) service to email address adapters 595aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank */ 605aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blankpublic class ExchangeDirectoryProvider extends ContentProvider { 61eb9cccf5c94b043baecb03d06738f7eedef03378Marc Blank public static final String EXCHANGE_GAL_AUTHORITY = "com.android.exchange.directory.provider"; 625aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank 63d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov private static final int DEFAULT_CONTACT_ID = 1; 64469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank private static final int DEFAULT_LOOKUP_LIMIT = 20; 65d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov 665aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank private static final int GAL_BASE = 0; 671f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov private static final int GAL_DIRECTORIES = GAL_BASE; 681f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov private static final int GAL_FILTER = GAL_BASE + 1; 691f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov private static final int GAL_CONTACT = GAL_BASE + 2; 701f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov private static final int GAL_CONTACT_WITH_ID = GAL_BASE + 3; 71f6e831704c7df2b841760931469b1e995b957cd9Dmitri Plotnikov private static final int GAL_EMAIL_FILTER = GAL_BASE + 4; 725aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank 735aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH); 747307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank /*package*/ final HashMap<String, Long> mAccountIdMap = new HashMap<String, Long>(); 755aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank 765aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank static { 771f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov sURIMatcher.addURI(EXCHANGE_GAL_AUTHORITY, "directories", GAL_DIRECTORIES); 785aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank sURIMatcher.addURI(EXCHANGE_GAL_AUTHORITY, "contacts/filter/*", GAL_FILTER); 791f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov sURIMatcher.addURI(EXCHANGE_GAL_AUTHORITY, "contacts/lookup/*/entities", GAL_CONTACT); 80d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov sURIMatcher.addURI(EXCHANGE_GAL_AUTHORITY, "contacts/lookup/*/#/entities", 81d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov GAL_CONTACT_WITH_ID); 82f6e831704c7df2b841760931469b1e995b957cd9Dmitri Plotnikov sURIMatcher.addURI(EXCHANGE_GAL_AUTHORITY, "data/emails/filter/*", GAL_EMAIL_FILTER); 835aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank } 845aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank 855aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank @Override 865aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank public boolean onCreate() { 875aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank return true; 885aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank } 895aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank 90d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov static class GalProjection { 91d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov final int size; 92d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov final HashMap<String, Integer> columnMap = new HashMap<String, Integer>(); 93d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov 94d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov GalProjection(String[] projection) { 95d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov size = projection.length; 96d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov for (int i = 0; i < projection.length; i++) { 97d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov columnMap.put(projection[i], i); 98d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov } 99d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov } 100d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov } 101d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov 102d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov static class GalContactRow { 103d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov private final GalProjection mProjection; 104d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov private Object[] row; 105d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov static long dataId = 1; 106d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov 107d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov GalContactRow(GalProjection projection, long contactId, String lookupKey, 108d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov String accountName, String displayName) { 109d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov this.mProjection = projection; 110d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov row = new Object[projection.size]; 111d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov 112d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov put(Contacts.Entity.CONTACT_ID, contactId); 113d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov 114d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov // We only have one raw contact per aggregate, so they can have the same ID 115d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov put(Contacts.Entity.RAW_CONTACT_ID, contactId); 116d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov put(Contacts.Entity.DATA_ID, dataId++); 117d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov 118d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov put(Contacts.DISPLAY_NAME, displayName); 119d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov 120d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov // TODO alternative display name 121d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov put(Contacts.DISPLAY_NAME_ALTERNATIVE, displayName); 122d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov 123c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blank put(RawContacts.ACCOUNT_TYPE, Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE); 124d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov put(RawContacts.ACCOUNT_NAME, accountName); 125d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov put(RawContacts.RAW_CONTACT_IS_READ_ONLY, 1); 126d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov put(Data.IS_READ_ONLY, 1); 127d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov } 128d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov 129d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov Object[] getRow () { 130d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov return row; 131d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov } 132d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov 133d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov void put(String columnName, Object value) { 134d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov Integer integer = mProjection.columnMap.get(columnName); 135d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov if (integer != null) { 136d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov row[integer] = value; 137d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov } else { 138d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov System.out.println("Unsupported column: " + columnName); 139d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov } 140d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov } 141d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov 142d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov static void addEmailAddress(MatrixCursor cursor, GalProjection galProjection, 143d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov long contactId, String lookupKey, String accountName, String displayName, 144d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov String address) { 145d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov if (!TextUtils.isEmpty(address)) { 146d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov GalContactRow r = new GalContactRow( 147d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov galProjection, contactId, lookupKey, accountName, displayName); 148d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov r.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE); 149d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov r.put(Email.TYPE, Email.TYPE_WORK); 150d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov r.put(Email.ADDRESS, address); 151d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov cursor.addRow(r.getRow()); 152d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov } 153d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov } 154d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov 155d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov static void addPhoneRow(MatrixCursor cursor, GalProjection projection, long contactId, 156d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov String lookupKey, String accountName, String displayName, int type, String number) { 157d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov if (!TextUtils.isEmpty(number)) { 158d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov GalContactRow r = new GalContactRow( 159d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov projection, contactId, lookupKey, accountName, displayName); 160d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov r.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); 161d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov r.put(Phone.TYPE, type); 162d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov r.put(Phone.NUMBER, number); 163d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov cursor.addRow(r.getRow()); 164d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov } 165d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov } 166d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov 167d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov public static void addNameRow(MatrixCursor cursor, GalProjection galProjection, 168d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov long contactId, String lookupKey, String accountName, String displayName, 169d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov String firstName, String lastName) { 170d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov GalContactRow r = new GalContactRow( 171d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov galProjection, contactId, lookupKey, accountName, displayName); 172d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov r.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE); 173d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov r.put(StructuredName.GIVEN_NAME, firstName); 174d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov r.put(StructuredName.FAMILY_NAME, lastName); 175d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov r.put(StructuredName.DISPLAY_NAME, displayName); 176d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov cursor.addRow(r.getRow()); 177d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov } 178d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov } 179d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov 1807307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank /** 1817307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank * Find the record id of an Account, given its name (email address) 1827307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank * @param accountName the name of the account 1837307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank * @return the record id of the Account, or -1 if not found 1847307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank */ 1857307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank /*package*/ long getAccountIdByName(Context context, String accountName) { 1867307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank Long accountId = mAccountIdMap.get(accountName); 1877307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank if (accountId == null) { 1887307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank accountId = Utility.getFirstRowLong(context, Account.CONTENT_URI, 1897307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank EmailContent.ID_PROJECTION, AccountColumns.EMAIL_ADDRESS + "=?", 1907307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank new String[] {accountName}, null, EmailContent.ID_PROJECTION_COLUMN , -1L); 1917307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank if (accountId != -1) { 1927307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank mAccountIdMap.put(accountName, accountId); 1937307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank } 1947307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank } 1957307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank return accountId; 1967307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank } 1977307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank 1985aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank @Override 1995aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 2005aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank String sortOrder) { 2015aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank int match = sURIMatcher.match(uri); 202d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov MatrixCursor cursor; 203d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov Object[] row; 204d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov PackedString ps; 205d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov String lookupKey; 206d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov 2075aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank switch (match) { 2081f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov case GAL_DIRECTORIES: { 2091f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov // Assuming that GAL can be used with all exchange accounts 2101f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov android.accounts.Account[] accounts = AccountManager.get(getContext()) 211c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blank .getAccountsByType(Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE); 2121f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov cursor = new MatrixCursor(projection); 2131f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov if (accounts != null) { 2141f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov for (android.accounts.Account account : accounts) { 2151f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov row = new Object[projection.length]; 2161f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov 2171f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov for (int i = 0; i < projection.length; i++) { 2181f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov String column = projection[i]; 2191f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov if (column.equals(Directory.ACCOUNT_NAME)) { 2201f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov row[i] = account.name; 2211f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov } else if (column.equals(Directory.ACCOUNT_TYPE)) { 2221f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov row[i] = account.type; 2231f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov } else if (column.equals(Directory.TYPE_RESOURCE_ID)) { 224c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blank Bundle bundle = null; 225d1771c4473a98c032c95ff66fa816043e08976f1Todd Kennedy String accountType = Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE; 226d1771c4473a98c032c95ff66fa816043e08976f1Todd Kennedy bundle = new AccountServiceProxy(getContext()) 227d1771c4473a98c032c95ff66fa816043e08976f1Todd Kennedy .getConfigurationData(accountType); 228c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blank // Default to the alternative name, erring on the conservative side 229c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blank int exchangeName = R.string.exchange_name_alternate; 230c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blank if (bundle != null && !bundle.getBoolean( 231c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blank Configuration.EXCHANGE_CONFIGURATION_USE_ALTERNATE_STRINGS, 232c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blank true)) { 233c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blank exchangeName = R.string.exchange_name; 2341f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov } 235c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blank row[i] = exchangeName; 2361f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov } else if (column.equals(Directory.DISPLAY_NAME)) { 237aa408e086ac013cd822c4f6b5f4ad91ae442d02fDmitri Plotnikov // If the account name is an email address, extract 238aa408e086ac013cd822c4f6b5f4ad91ae442d02fDmitri Plotnikov // the domain name and use it as the directory display name 239aa408e086ac013cd822c4f6b5f4ad91ae442d02fDmitri Plotnikov final String accountName = account.name; 240aa408e086ac013cd822c4f6b5f4ad91ae442d02fDmitri Plotnikov int atIndex = accountName.indexOf('@'); 241aa408e086ac013cd822c4f6b5f4ad91ae442d02fDmitri Plotnikov if (atIndex != -1 && atIndex < accountName.length() - 2) { 242aa408e086ac013cd822c4f6b5f4ad91ae442d02fDmitri Plotnikov final char firstLetter = Character.toUpperCase( 243aa408e086ac013cd822c4f6b5f4ad91ae442d02fDmitri Plotnikov accountName.charAt(atIndex + 1)); 244aa408e086ac013cd822c4f6b5f4ad91ae442d02fDmitri Plotnikov row[i] = firstLetter + accountName.substring(atIndex + 2); 245aa408e086ac013cd822c4f6b5f4ad91ae442d02fDmitri Plotnikov } else { 246aa408e086ac013cd822c4f6b5f4ad91ae442d02fDmitri Plotnikov row[i] = account.name; 247aa408e086ac013cd822c4f6b5f4ad91ae442d02fDmitri Plotnikov } 2481f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov } else if (column.equals(Directory.EXPORT_SUPPORT)) { 2491f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov row[i] = Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY; 2501f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov } else if (column.equals(Directory.SHORTCUT_SUPPORT)) { 251831936a7ee4cbf93c847a66d7cd3062680676f22Dmitri Plotnikov row[i] = Directory.SHORTCUT_SUPPORT_NONE; 2521f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov } 2531f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov } 2541f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov cursor.addRow(row); 2551f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov } 2561f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov } 2571f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov return cursor; 2581f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov } 2591f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov 260f6e831704c7df2b841760931469b1e995b957cd9Dmitri Plotnikov case GAL_FILTER: 261f6e831704c7df2b841760931469b1e995b957cd9Dmitri Plotnikov case GAL_EMAIL_FILTER: { 2625aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank String filter = uri.getLastPathSegment(); 2635aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank // We should have at least two characters before doing a GAL search 2645aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank if (filter == null || filter.length() < 2) { 2655aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank return null; 2665aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank } 2671f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov 2681f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 2691f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov if (accountName == null) { 2701f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov return null; 2711f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov } 2721f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov 273469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank // Enforce a limit on the number of lookup responses 274469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank String limitString = uri.getQueryParameter(ContactsContract.LIMIT_PARAM_KEY); 275469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank int limit = DEFAULT_LOOKUP_LIMIT; 276469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank if (limitString != null) { 277469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank try { 278469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank limit = Integer.parseInt(limitString); 279469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank } catch (NumberFormatException e) { 280469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank limit = 0; 281469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank } 282469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank if (limit <= 0) { 283469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank throw new IllegalArgumentException("Limit not valid: " + limitString); 284469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank } 285469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank } 286469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank 2875aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank long callingId = Binder.clearCallingIdentity(); 2885aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank try { 2897307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank // Find the account id to pass along to EasSyncService 2907307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank long accountId = getAccountIdByName(getContext(), accountName); 2917307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank if (accountId == -1) { 2927307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank // The account was deleted? 2937307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank return null; 2947307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank } 2957307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank 2965aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank // Get results from the Exchange account 2977307f7e5c2c4f85f6f3e0ebaf5775f65cba4b20cMarc Blank GalResult galResult = EasSyncService.searchGal(getContext(), accountId, 298469544cd1b9652c446c96b97f4abbdb65d7e06aaMarc Blank filter, limit); 2995aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank if (galResult != null) { 3005aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank return buildGalResultCursor(projection, galResult); 3015aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank } 3025aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank } finally { 3035aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank Binder.restoreCallingIdentity(callingId); 3045aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank } 3055aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank break; 306d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov } 307d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov 308d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov case GAL_CONTACT: 309d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov case GAL_CONTACT_WITH_ID: { 3101f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME); 3111f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov if (accountName == null) { 3121f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov return null; 3131f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov } 3141f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov 315d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov GalProjection galProjection = new GalProjection(projection); 316d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov cursor = new MatrixCursor(projection); 317d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov // Handle the decomposition of the key into rows suitable for CP2 3181f4b000ebe72fe9e71082031f48d0133914bda2dDmitri Plotnikov List<String> pathSegments = uri.getPathSegments(); 319d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov lookupKey = pathSegments.get(2); 320d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov long contactId = (match == GAL_CONTACT_WITH_ID) 321d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov ? Long.parseLong(pathSegments.get(3)) 322d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov : DEFAULT_CONTACT_ID; 323d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov ps = new PackedString(lookupKey); 324d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov String displayName = ps.get(GalData.DISPLAY_NAME); 325d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov GalContactRow.addEmailAddress(cursor, galProjection, contactId, lookupKey, 326d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov accountName, displayName, ps.get(GalData.EMAIL_ADDRESS)); 327d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov GalContactRow.addPhoneRow(cursor, galProjection, contactId, accountName, 328d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov displayName, displayName, Phone.TYPE_HOME, ps.get(GalData.HOME_PHONE)); 329d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov GalContactRow.addPhoneRow(cursor, galProjection, contactId, accountName, 330d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov displayName, displayName, Phone.TYPE_WORK, ps.get(GalData.WORK_PHONE)); 331d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov GalContactRow.addPhoneRow(cursor, galProjection, contactId, accountName, 332d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov displayName, displayName, Phone.TYPE_MOBILE, ps.get(GalData.MOBILE_PHONE)); 333d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov GalContactRow.addNameRow(cursor, galProjection, contactId, accountName, displayName, 334d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov ps.get(GalData.FIRST_NAME), ps.get(GalData.LAST_NAME), displayName); 335d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov return cursor; 336d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov } 3375aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank } 3385aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank 3395aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank return null; 3405aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank } 3415aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank 3425aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank /*package*/ Cursor buildGalResultCursor(String[] projection, GalResult galResult) { 3435aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank int displayNameIndex = -1; 344d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov int alternateDisplayNameIndex = -1;; 3455aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank int emailIndex = -1; 346d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov int idIndex = -1; 347d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov int lookupIndex = -1; 3485aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank 3495aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank for (int i = 0; i < projection.length; i++) { 3505aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank String column = projection[i]; 3515aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank if (Contacts.DISPLAY_NAME.equals(column) || 3525aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank Contacts.DISPLAY_NAME_PRIMARY.equals(column)) { 3535aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank displayNameIndex = i; 3545aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank } else if (Contacts.DISPLAY_NAME_ALTERNATIVE.equals(column)) { 355d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov alternateDisplayNameIndex = i; 3565aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank } else if (CommonDataKinds.Email.ADDRESS.equals(column)) { 3575aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank emailIndex = i; 358d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov } else if (Contacts._ID.equals(column)) { 359d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov idIndex = i; 360d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov } else if (Contacts.LOOKUP_KEY.equals(column)) { 361d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov lookupIndex = i; 3625aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank } 3635aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank } 3645aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank 3655aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank Object[] row = new Object[projection.length]; 3665aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank 3675aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank /* 3685aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank * ContactsProvider will ensure that every request has a non-null projection. 3695aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank */ 3705aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank MatrixCursor cursor = new MatrixCursor(projection); 3715aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank int count = galResult.galData.size(); 3725aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank for (int i = 0; i < count; i++) { 3735aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank GalData galDataRow = galResult.galData.get(i); 374d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov String firstName = galDataRow.get(GalData.FIRST_NAME); 375d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov String lastName = galDataRow.get(GalData.LAST_NAME); 376d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov String displayName = galDataRow.get(GalData.DISPLAY_NAME); 377d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov // If we don't have a display name, try to create one using first and last name 378d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov if (displayName == null) { 379d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov if (firstName != null && lastName != null) { 380d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov displayName = firstName + " " + lastName; 381d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov } else if (firstName != null) { 382d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov displayName = firstName; 383d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov } else if (lastName != null) { 384d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov displayName = lastName; 385d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov } 386d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov } 387d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov galDataRow.put(GalData.DISPLAY_NAME, displayName); 388d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov 3895aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank if (displayNameIndex != -1) { 390d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov row[displayNameIndex] = displayName; 391d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov } 392d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov if (alternateDisplayNameIndex != -1) { 393d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov // Try to create an alternate display name, using first and last name 394d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov // TODO: Check with Contacts team to make sure we're using this properly 395d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov if (firstName != null && lastName != null) { 396d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov row[alternateDisplayNameIndex] = lastName + " " + firstName; 397d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov } else { 398d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov row[alternateDisplayNameIndex] = displayName; 399d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov } 4005aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank } 4015aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank if (emailIndex != -1) { 402d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov row[emailIndex] = galDataRow.get(GalData.EMAIL_ADDRESS); 403d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov } 404d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov if (idIndex != -1) { 405d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov row[idIndex] = i + 1; // Let's be 1 based 406d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov } 407d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov if (lookupIndex != -1) { 408d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov // We use the packed string as our lookup key; it contains ALL of the gal data 409d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov // We do this because we are not able to provide a stable id to ContactsProvider 410d41eaba645dcb4573c5dc33077fc87799ef06195Dmitri Plotnikov row[lookupIndex] = Uri.encode(galDataRow.toPackedString()); 4115aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank } 4125aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank cursor.addRow(row); 4135aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank } 4145aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank return cursor; 4155aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank } 4165aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank 4175aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank @Override 4185aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank public String getType(Uri uri) { 4195aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank int match = sURIMatcher.match(uri); 4205aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank switch (match) { 4215aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank case GAL_FILTER: 4225aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank return Contacts.CONTENT_ITEM_TYPE; 4235aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank } 4245aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank return null; 4255aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank } 4265aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank 4275aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank @Override 4285aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank public int delete(Uri uri, String selection, String[] selectionArgs) { 4295aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank throw new UnsupportedOperationException(); 4305aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank } 4315aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank 4325aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank @Override 4335aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank public Uri insert(Uri uri, ContentValues values) { 4345aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank throw new UnsupportedOperationException(); 4355aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank } 4365aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank 4375aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank @Override 4385aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 4395aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank throw new UnsupportedOperationException(); 4405aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank } 4415aec61dc15c62cff0cf55a3d6cb483f9e338230aMarc Blank} 442