BluetoothPbapVcardManager.java revision 5006c8597521a7652eafa89a6fb5483b5cb567b6
1b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh/* 2b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * Copyright (c) 2008-2009, Motorola, Inc. 3c7a57f31515107366589bd6875c3cc4af1fc806efredc * Copyright (C) 2009-2012, Broadcom Corporation 4b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * 5b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * All rights reserved. 6b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * 7b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * Redistribution and use in source and binary forms, with or without 8b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * modification, are permitted provided that the following conditions are met: 9b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * 10b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * - Redistributions of source code must retain the above copyright notice, 11b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * this list of conditions and the following disclaimer. 12b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * 13b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * - Redistributions in binary form must reproduce the above copyright notice, 14b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * this list of conditions and the following disclaimer in the documentation 15b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * and/or other materials provided with the distribution. 16b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * 17b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * - Neither the name of the Motorola, Inc. nor the names of its contributors 18b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * may be used to endorse or promote products derived from this software 19b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * without specific prior written permission. 20b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * 21b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 25b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh * POSSIBILITY OF SUCH DAMAGE. 32b9cd7fee03a41e56a0cea9aa2e1af3b28c5be590Jaikumar Ganesh */ 332c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan 342c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanpackage com.android.bluetooth.pbap; 352c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan 362f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yueimport android.content.ContentResolver; 372f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yueimport android.content.Context; 38c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Guptaimport android.database.CursorWindowAllocationException; 39198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport android.database.Cursor; 405006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Waiimport android.database.MatrixCursor; 41198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport android.net.Uri; 42198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport android.provider.CallLog; 435006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Waiimport android.provider.ContactsContract; 44198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport android.provider.CallLog.Calls; 452f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yueimport android.provider.ContactsContract.CommonDataKinds; 462f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yueimport android.provider.ContactsContract.Contacts; 472f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yueimport android.provider.ContactsContract.Data; 482f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yueimport android.provider.ContactsContract.CommonDataKinds.Phone; 490dcd2262d853c2011e11617a8efba6758370c41fLiejun Taoimport android.provider.ContactsContract.PhoneLookup; 505006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Waiimport android.provider.ContactsContract.RawContactsEntity; 51d956b40b2f59599447ae0fa0762e055c0c0ce1a3Daisuke Miyakawaimport android.telephony.PhoneNumberUtils; 52198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport android.text.TextUtils; 53198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport android.util.Log; 54198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa 55198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport com.android.bluetooth.R; 5612cb33f6d9fd269944a5618661e3880beea58b6eDaisuke Miyakawaimport com.android.vcard.VCardComposer; 5712cb33f6d9fd269944a5618661e3880beea58b6eDaisuke Miyakawaimport com.android.vcard.VCardConfig; 58d956b40b2f59599447ae0fa0762e055c0c0ce1a3Daisuke Miyakawaimport com.android.vcard.VCardPhoneNumberTranslationCallback; 592f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue 602f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yueimport java.io.IOException; 612f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yueimport java.io.OutputStream; 622c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport java.util.ArrayList; 635006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Waiimport java.util.Collections; 642c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan 650b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yueimport javax.obex.ServerOperation; 66198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport javax.obex.Operation; 67198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport javax.obex.ResponseCodes; 68198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa 69c7a57f31515107366589bd6875c3cc4af1fc806efredcimport com.android.bluetooth.Utils; 70c7a57f31515107366589bd6875c3cc4af1fc806efredc 712c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanpublic class BluetoothPbapVcardManager { 722f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue private static final String TAG = "BluetoothPbapVcardManager"; 732c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan 744446eaa935994bc91d6d308303e8d27526b4590dLixin Yue private static final boolean V = BluetoothPbapService.VERBOSE; 754446eaa935994bc91d6d308303e8d27526b4590dLixin Yue 762c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan private ContentResolver mResolver; 772c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan 782c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan private Context mContext; 792c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan 80e10881ae39eb4affb7a78827f2060964e8534515Daisuke Miyakawa private static final int PHONE_NUMBER_COLUMN_INDEX = 3; 812c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan 822f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue static final String SORT_ORDER_PHONE_NUMBER = CommonDataKinds.Phone.NUMBER + " ASC"; 834446eaa935994bc91d6d308303e8d27526b4590dLixin Yue 845006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai static final String[] PHONES_CONTACTS_PROJECTION = new String[] { 855006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai Phone.CONTACT_ID, // 0 865006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai Phone.DISPLAY_NAME, // 1 875006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai }; 885006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai 895006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai static final String[] PHONE_LOOKUP_PROJECTION = new String[] { 905006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai PhoneLookup._ID, PhoneLookup.DISPLAY_NAME 912b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh }; 922b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh 932b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh static final int CONTACTS_ID_COLUMN_INDEX = 0; 942b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh 952b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh static final int CONTACTS_NAME_COLUMN_INDEX = 1; 962b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh 972b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh // call histories use dynamic handles, and handles should order by date; the 982b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh // most recently one should be the first handle. In table "calls", _id and 992b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh // date are consistent in ordering, to implement simply, we sort by _id 1002b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh // here. 1012b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh static final String CALLLOG_SORT_ORDER = Calls._ID + " DESC"; 1022b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh 103cd5ed0c7d04119e508fbddfd9656ef8559e3e524Lixin Yue private static final String CLAUSE_ONLY_VISIBLE = Contacts.IN_VISIBLE_GROUP + "=1"; 104cd5ed0c7d04119e508fbddfd9656ef8559e3e524Lixin Yue 1052c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan public BluetoothPbapVcardManager(final Context context) { 1062c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan mContext = context; 1072c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan mResolver = mContext.getContentResolver(); 1082c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan } 1092c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan 110c7a57f31515107366589bd6875c3cc4af1fc806efredc /** 111c7a57f31515107366589bd6875c3cc4af1fc806efredc * Create an owner vcard from the configured profile 112c7a57f31515107366589bd6875c3cc4af1fc806efredc * @param vcardType21 113c7a57f31515107366589bd6875c3cc4af1fc806efredc * @return 114c7a57f31515107366589bd6875c3cc4af1fc806efredc */ 115c7a57f31515107366589bd6875c3cc4af1fc806efredc private final String getOwnerPhoneNumberVcardFromProfile(final boolean vcardType21, final byte[] filter) { 116c7a57f31515107366589bd6875c3cc4af1fc806efredc // Currently only support Generic Vcard 2.1 and 3.0 117c7a57f31515107366589bd6875c3cc4af1fc806efredc int vcardType; 118c7a57f31515107366589bd6875c3cc4af1fc806efredc if (vcardType21) { 119c7a57f31515107366589bd6875c3cc4af1fc806efredc vcardType = VCardConfig.VCARD_TYPE_V21_GENERIC; 120c7a57f31515107366589bd6875c3cc4af1fc806efredc } else { 121c7a57f31515107366589bd6875c3cc4af1fc806efredc vcardType = VCardConfig.VCARD_TYPE_V30_GENERIC; 122c7a57f31515107366589bd6875c3cc4af1fc806efredc } 1234a53a55dc10d3a26c94e5844f7d4a2565a67142cfredc 1244a53a55dc10d3a26c94e5844f7d4a2565a67142cfredc if (!BluetoothPbapConfig.includePhotosInVcard()) { 1254a53a55dc10d3a26c94e5844f7d4a2565a67142cfredc vcardType |= VCardConfig.FLAG_REFRAIN_IMAGE_EXPORT; 1264a53a55dc10d3a26c94e5844f7d4a2565a67142cfredc } 1274a53a55dc10d3a26c94e5844f7d4a2565a67142cfredc 128c7a57f31515107366589bd6875c3cc4af1fc806efredc return BluetoothPbapUtils.createProfileVCard(mContext, vcardType,filter); 129c7a57f31515107366589bd6875c3cc4af1fc806efredc } 130c7a57f31515107366589bd6875c3cc4af1fc806efredc 131c7a57f31515107366589bd6875c3cc4af1fc806efredc public final String getOwnerPhoneNumberVcard(final boolean vcardType21, final byte[] filter) { 132c7a57f31515107366589bd6875c3cc4af1fc806efredc //Owner vCard enhancement: Use "ME" profile if configured 133c7a57f31515107366589bd6875c3cc4af1fc806efredc if (BluetoothPbapConfig.useProfileForOwnerVcard()) { 134c7a57f31515107366589bd6875c3cc4af1fc806efredc String vcard = getOwnerPhoneNumberVcardFromProfile(vcardType21, filter); 135c7a57f31515107366589bd6875c3cc4af1fc806efredc if (vcard != null && vcard.length() != 0) { 136c7a57f31515107366589bd6875c3cc4af1fc806efredc return vcard; 137c7a57f31515107366589bd6875c3cc4af1fc806efredc } 138c7a57f31515107366589bd6875c3cc4af1fc806efredc } 139c7a57f31515107366589bd6875c3cc4af1fc806efredc //End enhancement 140c7a57f31515107366589bd6875c3cc4af1fc806efredc 1413c4d2c77c2fffe675fbe89ba58856686b6873d2fDaisuke Miyakawa BluetoothPbapCallLogComposer composer = new BluetoothPbapCallLogComposer(mContext); 1422f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue String name = BluetoothPbapService.getLocalPhoneName(); 1432f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue String number = BluetoothPbapService.getLocalPhoneNum(); 1442f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue String vcard = composer.composeVCardForPhoneOwnNumber(Phone.TYPE_MOBILE, name, number, 1452f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue vcardType21); 1462f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue return vcard; 1472c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan } 1482c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan 1492f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue public final int getPhonebookSize(final int type) { 1502f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue int size; 1512f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue switch (type) { 1522f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue case BluetoothPbapObexServer.ContentType.PHONEBOOK: 1532f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue size = getContactsSize(); 1542f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue break; 1552f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue default: 1562f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue size = getCallHistorySize(type); 1572f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue break; 1582c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan } 159c7a57f31515107366589bd6875c3cc4af1fc806efredc if (V) Log.v(TAG, "getPhonebookSize size = " + size + " type = " + type); 1602f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue return size; 1612c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan } 1622c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan 1632f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue public final int getContactsSize() { 1645006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai final Uri myUri = getPhoneUri(); 1652f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue Cursor contactCursor = null; 1662f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue try { 1675006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai contactCursor = mResolver.query(myUri, new String[] {Phone.CONTACT_ID}, 1685006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai CLAUSE_ONLY_VISIBLE, null, Phone.CONTACT_ID); 1695006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (contactCursor == null) { 1705006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai return 0; 1712f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue } 1725006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai return getDistinctContactIdSize(contactCursor) + 1; // always has the 0.vcf 173c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta } catch (CursorWindowAllocationException e) { 174c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta Log.e(TAG, "CursorWindowAllocationException while getting Contacts size"); 1752f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue } finally { 1762f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue if (contactCursor != null) { 1772f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue contactCursor.close(); 1782f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue } 1792c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan } 1805006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai return 0; 1812c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan } 1822c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan 1832f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue public final int getCallHistorySize(final int type) { 1842b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh final Uri myUri = CallLog.Calls.CONTENT_URI; 1852f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue String selection = BluetoothPbapObexServer.createSelectionPara(type); 1862f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue int size = 0; 1872f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue Cursor callCursor = null; 1882f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue try { 1892f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue callCursor = mResolver.query(myUri, null, selection, null, 1902f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue CallLog.Calls.DEFAULT_SORT_ORDER); 1912f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue if (callCursor != null) { 1922f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue size = callCursor.getCount(); 1934446eaa935994bc91d6d308303e8d27526b4590dLixin Yue } 194c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta } catch (CursorWindowAllocationException e) { 195c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta Log.e(TAG, "CursorWindowAllocationException while getting CallHistory size"); 1962f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue } finally { 1972f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue if (callCursor != null) { 1982f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue callCursor.close(); 199c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta callCursor = null; 2004446eaa935994bc91d6d308303e8d27526b4590dLixin Yue } 2012f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue } 2022f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue return size; 2032f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue } 2044446eaa935994bc91d6d308303e8d27526b4590dLixin Yue 2052f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue public final ArrayList<String> loadCallHistoryList(final int type) { 2062b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh final Uri myUri = CallLog.Calls.CONTENT_URI; 2072f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue String selection = BluetoothPbapObexServer.createSelectionPara(type); 2082f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue String[] projection = new String[] { 2099674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner Calls.NUMBER, Calls.CACHED_NAME, Calls.NUMBER_PRESENTATION 2102f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue }; 2112f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue final int CALLS_NUMBER_COLUMN_INDEX = 0; 2122f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue final int CALLS_NAME_COLUMN_INDEX = 1; 2139674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner final int CALLS_NUMBER_PRESENTATION_COLUMN_INDEX = 2; 2142f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue 2152f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue Cursor callCursor = null; 2162f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue ArrayList<String> list = new ArrayList<String>(); 2172f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue try { 2182f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue callCursor = mResolver.query(myUri, projection, selection, null, 2192b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh CALLLOG_SORT_ORDER); 2202f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue if (callCursor != null) { 2212f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue for (callCursor.moveToFirst(); !callCursor.isAfterLast(); 2222f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue callCursor.moveToNext()) { 2232f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue String name = callCursor.getString(CALLS_NAME_COLUMN_INDEX); 2242f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue if (TextUtils.isEmpty(name)) { 22577ba5f6684f4dd7e4b7fc37982271da5654aec07Staffan Lindvall // name not found, use number instead 2269674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner final int numberPresentation = callCursor.getInt( 2279674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner CALLS_NUMBER_PRESENTATION_COLUMN_INDEX); 2289674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner if (numberPresentation != Calls.PRESENTATION_ALLOWED) { 22977ba5f6684f4dd7e4b7fc37982271da5654aec07Staffan Lindvall name = mContext.getString(R.string.unknownNumber); 2309674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner } else { 2319674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner name = callCursor.getString(CALLS_NUMBER_COLUMN_INDEX); 23277ba5f6684f4dd7e4b7fc37982271da5654aec07Staffan Lindvall } 2332f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue } 2342f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue list.add(name); 2352f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue } 2362f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue } 237c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta } catch (CursorWindowAllocationException e) { 238c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta Log.e(TAG, "CursorWindowAllocationException while loading CallHistory"); 2392f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue } finally { 2402f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue if (callCursor != null) { 2412f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue callCursor.close(); 242c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta callCursor = null; 2432c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan } 2442c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan } 2452f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue return list; 2462c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan } 2472c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan 2482b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh public final ArrayList<String> getPhonebookNameList(final int orderByWhat) { 2492f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue ArrayList<String> nameList = new ArrayList<String>(); 250c7a57f31515107366589bd6875c3cc4af1fc806efredc //Owner vCard enhancement. Use "ME" profile if configured 251c7a57f31515107366589bd6875c3cc4af1fc806efredc String ownerName = null; 252c7a57f31515107366589bd6875c3cc4af1fc806efredc if (BluetoothPbapConfig.useProfileForOwnerVcard()) { 253c7a57f31515107366589bd6875c3cc4af1fc806efredc ownerName = BluetoothPbapUtils.getProfileName(mContext); 254c7a57f31515107366589bd6875c3cc4af1fc806efredc } 255c7a57f31515107366589bd6875c3cc4af1fc806efredc if (ownerName == null || ownerName.length()==0) { 256c7a57f31515107366589bd6875c3cc4af1fc806efredc ownerName = BluetoothPbapService.getLocalPhoneName(); 257c7a57f31515107366589bd6875c3cc4af1fc806efredc } 258c7a57f31515107366589bd6875c3cc4af1fc806efredc nameList.add(ownerName); 259c7a57f31515107366589bd6875c3cc4af1fc806efredc //End enhancement 2604446eaa935994bc91d6d308303e8d27526b4590dLixin Yue 2615006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai final Uri myUri = getPhoneUri(); 2622b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh Cursor contactCursor = null; 2632f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue try { 2645006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai contactCursor = mResolver.query(myUri, PHONES_CONTACTS_PROJECTION, CLAUSE_ONLY_VISIBLE, 2655006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai null, Phone.CONTACT_ID); 2662b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh if (contactCursor != null) { 2675006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai appendDistinctNameIdList(nameList, 2685006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai mContext.getString(android.R.string.unknownName), 2695006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai contactCursor); 2705006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_INDEXED) { 2715006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (V) Log.v(TAG, "getPhonebookNameList, order by index"); 2725006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai // Do not need to do anything, as we sort it by index already 2735006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } else if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_ALPHABETICAL) { 2745006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (V) Log.v(TAG, "getPhonebookNameList, order by alpha"); 2755006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai Collections.sort(nameList); 2762f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue } 2772f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue } 278c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta } catch (CursorWindowAllocationException e) { 279c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta Log.e(TAG, "CursorWindowAllocationException while getting Phonebook name list"); 2802f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue } finally { 2812b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh if (contactCursor != null) { 2822b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh contactCursor.close(); 283c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta contactCursor = null; 2842f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue } 2852f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue } 2862f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue return nameList; 2874446eaa935994bc91d6d308303e8d27526b4590dLixin Yue } 2884446eaa935994bc91d6d308303e8d27526b4590dLixin Yue 2890dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao public final ArrayList<String> getContactNamesByNumber(final String phoneNumber) { 2900dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao ArrayList<String> nameList = new ArrayList<String>(); 2911321cd814a7406260ba6282d9c71e1a2d8925262Hemant Gupta ArrayList<String> tempNameList = new ArrayList<String>(); 2920dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao 2930dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao Cursor contactCursor = null; 2944bba23a751f042596561eab0e677135d5267bcdfStaffan Lindvall Uri uri = null; 2955006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai String[] projection = null; 2964bba23a751f042596561eab0e677135d5267bcdfStaffan Lindvall 2975006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (TextUtils.isEmpty(phoneNumber)) { 2985006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai uri = getPhoneUri(); 2995006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai projection = PHONES_CONTACTS_PROJECTION; 3004bba23a751f042596561eab0e677135d5267bcdfStaffan Lindvall } else { 3015006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai uri = Uri.withAppendedPath(getPhoneLookupFilterUri(), 3020dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao Uri.encode(phoneNumber)); 3035006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai projection = PHONE_LOOKUP_PROJECTION; 3044bba23a751f042596561eab0e677135d5267bcdfStaffan Lindvall } 3054446eaa935994bc91d6d308303e8d27526b4590dLixin Yue 3062f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue try { 3075006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai contactCursor = mResolver.query(uri, projection, CLAUSE_ONLY_VISIBLE, null, 3085006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai Phone.CONTACT_ID); 3090dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao 3100dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao if (contactCursor != null) { 3115006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai appendDistinctNameIdList(nameList, 3125006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai mContext.getString(android.R.string.unknownName), 3135006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai contactCursor); 3145006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (V) { 3155006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai for (String nameIdStr : nameList) { 3165006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai Log.v(TAG, "got name " + nameIdStr + " by number " + phoneNumber); 3172f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue } 3182f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue } 3192f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue } 320c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta } catch (CursorWindowAllocationException e) { 321c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta Log.e(TAG, "CursorWindowAllocationException while getting contact names"); 3222f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue } finally { 3230dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao if (contactCursor != null) { 3240dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao contactCursor.close(); 325c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta contactCursor = null; 3262f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue } 3272c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan } 3281321cd814a7406260ba6282d9c71e1a2d8925262Hemant Gupta int tempListSize = tempNameList.size(); 3291321cd814a7406260ba6282d9c71e1a2d8925262Hemant Gupta for (int index = 0; index < tempListSize; index++) { 3301321cd814a7406260ba6282d9c71e1a2d8925262Hemant Gupta String object = tempNameList.get(index); 3311321cd814a7406260ba6282d9c71e1a2d8925262Hemant Gupta if (!nameList.contains(object)) 3321321cd814a7406260ba6282d9c71e1a2d8925262Hemant Gupta nameList.add(object); 3331321cd814a7406260ba6282d9c71e1a2d8925262Hemant Gupta } 3341321cd814a7406260ba6282d9c71e1a2d8925262Hemant Gupta 3350dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao return nameList; 3362c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan } 3372c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan 3380b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue public final int composeAndSendCallLogVcards(final int type, Operation op, 3396db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta final int startPoint, final int endPoint, final boolean vcardType21, 3406db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta boolean ignorefilter, byte[] filter) { 34159256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh if (startPoint < 1 || startPoint > endPoint) { 34259256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh Log.e(TAG, "internal error: startPoint or endPoint is not correct."); 34359256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; 34459256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh } 3452f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue String typeSelection = BluetoothPbapObexServer.createSelectionPara(type); 34659256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh 3472b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh final Uri myUri = CallLog.Calls.CONTENT_URI; 34859256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh final String[] CALLLOG_PROJECTION = new String[] { 34959256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh CallLog.Calls._ID, // 0 35059256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh }; 35159256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh final int ID_COLUMN_INDEX = 0; 35259256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh 35359256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh Cursor callsCursor = null; 35459256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh long startPointId = 0; 35559256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh long endPointId = 0; 35659256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh try { 35759256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh // Need test to see if order by _ID is ok here, or by date? 35859256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh callsCursor = mResolver.query(myUri, CALLLOG_PROJECTION, typeSelection, null, 3592b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh CALLLOG_SORT_ORDER); 36059256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh if (callsCursor != null) { 36159256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh callsCursor.moveToPosition(startPoint - 1); 36259256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh startPointId = callsCursor.getLong(ID_COLUMN_INDEX); 36359256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh if (V) Log.v(TAG, "Call Log query startPointId = " + startPointId); 36459256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh if (startPoint == endPoint) { 36559256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh endPointId = startPointId; 36659256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh } else { 36759256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh callsCursor.moveToPosition(endPoint - 1); 36859256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh endPointId = callsCursor.getLong(ID_COLUMN_INDEX); 36959256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh } 37059256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh if (V) Log.v(TAG, "Call log query endPointId = " + endPointId); 37159256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh } 372c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta } catch (CursorWindowAllocationException e) { 373c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta Log.e(TAG, "CursorWindowAllocationException while composing calllog vcards"); 37459256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh } finally { 37559256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh if (callsCursor != null) { 37659256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh callsCursor.close(); 377c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta callsCursor = null; 37859256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh } 37959256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh } 38059256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh 3812f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue String recordSelection; 3822f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue if (startPoint == endPoint) { 38359256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh recordSelection = Calls._ID + "=" + startPointId; 3842f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue } else { 3852b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh // The query to call table is by "_id DESC" order, so change 3862b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh // correspondingly. 3872b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh recordSelection = Calls._ID + ">=" + endPointId + " AND " + Calls._ID + "<=" 3882b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh + startPointId; 3894446eaa935994bc91d6d308303e8d27526b4590dLixin Yue } 3904446eaa935994bc91d6d308303e8d27526b4590dLixin Yue 3912f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue String selection; 3922f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue if (typeSelection == null) { 3932f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue selection = recordSelection; 3942f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue } else { 3952f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue selection = "(" + typeSelection + ") AND (" + recordSelection + ")"; 3964446eaa935994bc91d6d308303e8d27526b4590dLixin Yue } 3974446eaa935994bc91d6d308303e8d27526b4590dLixin Yue 39859256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh if (V) Log.v(TAG, "Call log query selection is: " + selection); 3994446eaa935994bc91d6d308303e8d27526b4590dLixin Yue 4005006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai return composeCallLogsAndSendVCards(op, selection, vcardType21, null, ignorefilter, filter); 4014446eaa935994bc91d6d308303e8d27526b4590dLixin Yue } 4024446eaa935994bc91d6d308303e8d27526b4590dLixin Yue 4030b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue public final int composeAndSendPhonebookVcards(Operation op, final int startPoint, 4046db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta final int endPoint, final boolean vcardType21, String ownerVCard, 4056db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta boolean ignorefilter, byte[] filter) { 40659256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh if (startPoint < 1 || startPoint > endPoint) { 40759256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh Log.e(TAG, "internal error: startPoint or endPoint is not correct."); 40859256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; 40959256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh } 41059256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh 4115006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai final MatrixCursor selectionCursor = new MatrixCursor(new String[] { 4125006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai Phone.CONTACT_ID 4135006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai }); 4145006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai 4155006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai final Uri myUri = getPhoneUri(); 41659256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh Cursor contactCursor = null; 41759256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh try { 4185006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai contactCursor = mResolver.query(myUri, PHONES_CONTACTS_PROJECTION, CLAUSE_ONLY_VISIBLE, 4195006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai null, Phone.CONTACT_ID); 42059256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh if (contactCursor != null) { 4215006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai final int contactIdColumn = contactCursor.getColumnIndex(Data.CONTACT_ID); 4225006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai long previousContactId = -1; 4235006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai // As startPoint, endPoint index starts from 1 to n, we set 4245006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai // currentPoint base as 1 not 0 4255006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai int currentPoint = 1; 4265006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai while(contactCursor.moveToNext() && currentPoint <= endPoint) { 4275006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai long currentContactId = contactCursor.getLong(contactIdColumn); 4285006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (previousContactId != currentContactId) { 4295006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai previousContactId = currentContactId; 4305006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (currentPoint >= startPoint) { 4315006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai selectionCursor.addRow(new Long[] {currentContactId}); 4325006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (V) Log.v(TAG, "SelectionCursor addrow: " + currentContactId); 4335006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 4345006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai currentPoint++; 4355006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 43659256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh } 43759256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh } 438c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta } catch (CursorWindowAllocationException e) { 439c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta Log.e(TAG, "CursorWindowAllocationException while composing phonebook vcards"); 44059256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh } finally { 44159256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh if (contactCursor != null) { 44259256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh contactCursor.close(); 443c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta contactCursor = null; 44459256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh } 44559256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh } 4465006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai return composeContactsAndSendVCards(op, selectionCursor, vcardType21, ownerVCard, 4476db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta ignorefilter, filter); 4484446eaa935994bc91d6d308303e8d27526b4590dLixin Yue } 4494446eaa935994bc91d6d308303e8d27526b4590dLixin Yue 4500b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue public final int composeAndSendPhonebookOneVcard(Operation op, final int offset, 4516db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta final boolean vcardType21, String ownerVCard, int orderByWhat, 4526db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta boolean ignorefilter, byte[] filter) { 4532b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh if (offset < 1) { 4542b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh Log.e(TAG, "Internal error: offset is not correct."); 4552b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; 4562b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh } 4575006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai final Uri myUri = getPhoneUri(); 4582b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh Cursor contactCursor = null; 4595006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai try { 4605006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai contactCursor = mResolver.query(myUri, PHONES_CONTACTS_PROJECTION, 4615006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai CLAUSE_ONLY_VISIBLE, null, Phone.CONTACT_ID); 4625006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } catch (CursorWindowAllocationException e) { 4635006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai Log.e(TAG, 4645006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai "CursorWindowAllocationException while composing phonebook one vcard"); 4655006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } finally { 4665006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (contactCursor != null) { 4675006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai contactCursor.close(); 4685006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai contactCursor = null; 4692b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh } 4705006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 4715006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai long targetContactId = 0; 4725006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai long previousContactId = -1; 4735006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai // As offset starts from 1, currentOffset's base is 1 also 4745006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai int currentOffset = 1; 4755006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai final int contactIdColumn = contactCursor.getColumnIndex(Data.CONTACT_ID); 4765006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai 4775006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai while(contactCursor.moveToNext()) { 4785006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai long currentContactId = contactCursor.getLong(contactIdColumn); 4795006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (previousContactId != currentContactId) { 4805006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (currentOffset == offset) { 4815006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai targetContactId = currentContactId; 4825006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai break; 4832b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh } 4845006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai currentOffset++; 4855006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai previousContactId = currentContactId; 4862b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh } 4872b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh } 4882b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh 4895006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai MatrixCursor contactIdCursor = new MatrixCursor(new String[] { 4905006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai Phone.CONTACT_ID 4915006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai }); 4925006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai contactIdCursor.addRow(new Long[] { 4935006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai targetContactId 4945006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai }); 4952b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh 4965006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai return composeContactsAndSendVCards(op, contactIdCursor, vcardType21, ownerVCard, 4976db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta ignorefilter, filter); 4982b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh } 4992b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh 5005006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai /** 5015006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai * Handler enterprise contact id in VCardComposer 5025006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai */ 5035006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai private static class EnterpriseRawContactEntitlesInfoCallback implements 5045006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai VCardComposer.RawContactEntitlesInfoCallback { 5055006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai @Override 5065006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai public VCardComposer.RawContactEntitlesInfo getRawContactEntitlesInfo(long contactId) { 5075006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (Contacts.isEnterpriseContactId(contactId)) { 5085006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai return new VCardComposer.RawContactEntitlesInfo(RawContactsEntity.CORP_CONTENT_URI, 5095006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai contactId - Contacts.ENTERPRISE_CONTACT_ID_BASE); 5105006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } else { 5115006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai return new VCardComposer.RawContactEntitlesInfo(RawContactsEntity.CONTENT_URI, contactId); 5125006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 5135006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai 5145006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 5155006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 5165006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai 5175006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai public final int composeContactsAndSendVCards(Operation op, final Cursor contactIdCursor, 5185006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai final boolean vcardType21, String ownerVCard, boolean ignorefilter, byte[] filter) { 5192f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue long timestamp = 0; 5202f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue if (V) timestamp = System.currentTimeMillis(); 5214446eaa935994bc91d6d308303e8d27526b4590dLixin Yue 5225006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai VCardComposer composer = null; 5235006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai VCardFilter vcardfilter = new VCardFilter(ignorefilter ? null : filter); 5245f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach 5255006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai HandlerForStringBuffer buffer = null; 5265006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai try { 5275006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai // Currently only support Generic Vcard 2.1 and 3.0 5285006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai int vcardType; 5295006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (vcardType21) { 5305006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai vcardType = VCardConfig.VCARD_TYPE_V21_GENERIC; 5315006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } else { 5325006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai vcardType = VCardConfig.VCARD_TYPE_V30_GENERIC; 5335006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 5345006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (!vcardfilter.isPhotoEnabled()) { 5355006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai vcardType |= VCardConfig.FLAG_REFRAIN_IMAGE_EXPORT; 5365006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 5375006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai 5385006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai // Enhancement: customize Vcard based on preferences/settings and 5395006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai // input from caller 5405006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai composer = BluetoothPbapUtils.createFilteredVCardComposer(mContext, vcardType, null); 5415006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai // End enhancement 5425006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai 5435006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai // BT does want PAUSE/WAIT conversion while it doesn't want the 5445006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai // other formatting 5455006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai // done by vCard library by default. 5465006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai composer.setPhoneNumberTranslationCallback(new VCardPhoneNumberTranslationCallback() { 5475006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai public String onValueReceived(String rawValue, int type, String label, 5485006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai boolean isPrimary) { 5495006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai // 'p' and 'w' are the standard characters for pause and 5505006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai // wait 5515006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai // (see RFC 3601) 5525006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai // so use those when exporting phone numbers via vCard. 5535006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai String numberWithControlSequence = rawValue 5545006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai .replace(PhoneNumberUtils.PAUSE, 'p').replace(PhoneNumberUtils.WAIT, 5555006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai 'w'); 5565006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai return numberWithControlSequence; 5574a53a55dc10d3a26c94e5844f7d4a2565a67142cfredc } 5585006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai }); 5595006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai buffer = new HandlerForStringBuffer(op, ownerVCard); 5605006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai Log.v(TAG, "contactIdCursor size: " + contactIdCursor.getCount()); 5615006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (!composer.initWithCallback(contactIdCursor, 5625006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai new EnterpriseRawContactEntitlesInfoCallback()) 5635006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai || !buffer.onInit(mContext)) { 5645006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; 5655006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 5664446eaa935994bc91d6d308303e8d27526b4590dLixin Yue 5675006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai while (!composer.isAfterLast()) { 5685006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (BluetoothPbapObexServer.sIsAborted) { 5695006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai ((ServerOperation) op).isAborted = true; 5705006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai BluetoothPbapObexServer.sIsAborted = false; 5715006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai break; 5725006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 5735006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai String vcard = composer.createOneEntry(); 5745006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (vcard == null) { 5755006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai Log.e(TAG, 5765006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai "Failed to read a contact. Error reason: " + composer.getErrorReason()); 5772f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; 5784446eaa935994bc91d6d308303e8d27526b4590dLixin Yue } 5795006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (V) Log.v(TAG, "vCard from composer: " + vcard); 580198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa 5815006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai vcard = vcardfilter.apply(vcard, vcardType21); 5825006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai vcard = StripTelephoneNumber(vcard); 5835f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach 5845006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (V) Log.v(TAG, "vCard after cleanup: " + vcard); 585c7a57f31515107366589bd6875c3cc4af1fc806efredc 5865006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (!buffer.onEntryCreated(vcard)) { 5875006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai // onEntryCreate() already emits error. 5885006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; 5893c4d2c77c2fffe675fbe89ba58856686b6873d2fDaisuke Miyakawa } 5904446eaa935994bc91d6d308303e8d27526b4590dLixin Yue } 5915006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } finally { 5925006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (composer != null) { 5935006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai composer.terminate(); 5945006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 5955006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (buffer != null) { 5965006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai buffer.onTerminate(); 5975006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 5985006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 5993c4d2c77c2fffe675fbe89ba58856686b6873d2fDaisuke Miyakawa 6005006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (V) Log.v(TAG, "Total vcard composing and sending out takes " 6015006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai + (System.currentTimeMillis() - timestamp) + " ms"); 602198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa 6035006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai return ResponseCodes.OBEX_HTTP_OK; 6045006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 6055006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai 6065006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai public final int composeCallLogsAndSendVCards(Operation op, final String selection, 6075006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai final boolean vcardType21, String ownerVCard, boolean ignorefilter, 6085006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai byte[] filter) { 6095006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai long timestamp = 0; 6105006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (V) timestamp = System.currentTimeMillis(); 6115006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai 6125006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai BluetoothPbapCallLogComposer composer = null; 6135006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai HandlerForStringBuffer buffer = null; 6145006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai try { 6155006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai 6165006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai composer = new BluetoothPbapCallLogComposer(mContext); 6175006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai buffer = new HandlerForStringBuffer(op, ownerVCard); 6185006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (!composer.init(CallLog.Calls.CONTENT_URI, selection, null, CALLLOG_SORT_ORDER) 6195006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai || !buffer.onInit(mContext)) { 6205006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; 6215006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 622c7a57f31515107366589bd6875c3cc4af1fc806efredc 6235006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai while (!composer.isAfterLast()) { 6245006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (BluetoothPbapObexServer.sIsAborted) { 6255006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai ((ServerOperation) op).isAborted = true; 6265006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai BluetoothPbapObexServer.sIsAborted = false; 6275006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai break; 628198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa } 6295006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai String vcard = composer.createOneEntry(vcardType21); 6305006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (vcard == null) { 6315006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai Log.e(TAG, 6325006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai "Failed to read a contact. Error reason: " + composer.getErrorReason()); 6335006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; 634198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa } 6355006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (V) { 6365006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai Log.v(TAG, "Vcard Entry:"); 6375006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai Log.v(TAG, vcard); 6383c4d2c77c2fffe675fbe89ba58856686b6873d2fDaisuke Miyakawa } 6395006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai 6405006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai buffer.onEntryCreated(vcard); 6415006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 6425006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } finally { 6435006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (composer != null) { 6445006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai composer.terminate(); 6455006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 6465006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (buffer != null) { 6475006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai buffer.onTerminate(); 6484446eaa935994bc91d6d308303e8d27526b4590dLixin Yue } 6494446eaa935994bc91d6d308303e8d27526b4590dLixin Yue } 6504446eaa935994bc91d6d308303e8d27526b4590dLixin Yue 6512f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue if (V) Log.v(TAG, "Total vcard composing and sending out takes " 6525006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai + (System.currentTimeMillis() - timestamp) + " ms"); 6532f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue return ResponseCodes.OBEX_HTTP_OK; 6544446eaa935994bc91d6d308303e8d27526b4590dLixin Yue } 6554446eaa935994bc91d6d308303e8d27526b4590dLixin Yue 65629ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta public String StripTelephoneNumber (String vCard){ 65729ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta String attr [] = vCard.split(System.getProperty("line.separator")); 65829ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta String Vcard = ""; 65929ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta for (int i=0; i < attr.length; i++) { 66029ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta if(attr[i].startsWith("TEL")) { 66129ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta attr[i] = attr[i].replace("(", ""); 66229ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta attr[i] = attr[i].replace(")", ""); 66329ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta attr[i] = attr[i].replace("-", ""); 66429ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta attr[i] = attr[i].replace(" ", ""); 66529ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta } 66629ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta } 66729ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta 66829ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta for (int i=0; i < attr.length; i++) { 66929ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta if(!attr[i].equals("")){ 67029ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta Vcard = Vcard.concat(attr[i] + "\n"); 67129ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta } 67229ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta } 67302fc1acb99dbf3ae0a710ee7e4b6de8dd779e84eRakesh Iyer if (V) Log.v(TAG, "Vcard with stripped telephone no.: " + Vcard); 67429ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta return Vcard; 67529ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta } 67629ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta 6772f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue /** 678ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita * Handler to emit vCards to PCE. 6792f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue */ 6803c4d2c77c2fffe675fbe89ba58856686b6873d2fDaisuke Miyakawa public class HandlerForStringBuffer { 6812f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue private Operation operation; 6824446eaa935994bc91d6d308303e8d27526b4590dLixin Yue 6832f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue private OutputStream outputStream; 6842f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue 6852f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue private String phoneOwnVCard = null; 6862f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue 6872f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue public HandlerForStringBuffer(Operation op, String ownerVCard) { 6882f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue operation = op; 6892f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue if (ownerVCard != null) { 6902f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue phoneOwnVCard = ownerVCard; 6912f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue if (V) Log.v(TAG, "phone own number vcard:"); 6922f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue if (V) Log.v(TAG, phoneOwnVCard); 6932c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan } 6942c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan } 6952c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan 696ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita private boolean write(String vCard) { 697ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita try { 698ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita if (vCard != null) { 699ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita outputStream.write(vCard.getBytes()); 700ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita return true; 701ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita } 702ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita } catch (IOException e) { 703ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita Log.e(TAG, "write outputstrem failed" + e.toString()); 704ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita } 705ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita return false; 706ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita } 707ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita 7082f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue public boolean onInit(Context context) { 7092f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue try { 7102f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue outputStream = operation.openOutputStream(); 7112f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue if (phoneOwnVCard != null) { 712ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita return write(phoneOwnVCard); 7132c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan } 714ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita return true; 7152f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue } catch (IOException e) { 7162f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue Log.e(TAG, "open outputstrem failed" + e.toString()); 7172c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan } 718ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita return false; 7192c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan } 7202c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan 7212f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue public boolean onEntryCreated(String vcard) { 722ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita return write(vcard); 7232c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan } 7242c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan 7252f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue public void onTerminate() { 7262f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue if (!BluetoothPbapObexServer.closeStream(outputStream, operation)) { 7272f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue if (V) Log.v(TAG, "CloseStream failed!"); 7282c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan } else { 7292f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue if (V) Log.v(TAG, "CloseStream ok!"); 7302c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan } 7312c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan } 7322c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan } 7336db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta 7345f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach public static class VCardFilter { 7355f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach private static enum FilterBit { 7365f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach // bit property onlyCheckV21 excludeForV21 7375f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach FN ( 1, "FN", true, false), 7385f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach PHOTO( 3, "PHOTO", false, false), 7395f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach BDAY( 4, "BDAY", false, false), 7405f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach ADR( 5, "ADR", false, false), 7415f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach EMAIL( 8, "EMAIL", false, false), 7425f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach TITLE( 12, "TITLE", false, false), 7435f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach ORG( 16, "ORG", false, false), 7445f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach NOTES( 17, "NOTES", false, false), 7455f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach URL( 20, "URL", false, false), 7465f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach NICKNAME( 23, "NICKNAME", false, true); 7475f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach 7485f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach public final int pos; 7495f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach public final String prop; 7505f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach public final boolean onlyCheckV21; 7515f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach public final boolean excludeForV21; 7525f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach 7535f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach FilterBit(int pos, String prop, boolean onlyCheckV21, boolean excludeForV21) { 7545f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach this.pos = pos; 7555f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach this.prop = prop; 7565f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach this.onlyCheckV21 = onlyCheckV21; 7575f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach this.excludeForV21 = excludeForV21; 7585f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach } 7595f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach } 7605f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach 7615f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach private static final String SEPARATOR = System.getProperty("line.separator"); 7625f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach private final byte[] filter; 7635f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach 7645f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach private boolean isFilteredOut(FilterBit bit, boolean vCardType21) { 7655f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach final int offset = (bit.pos / 8) + 1; 7665f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach final int bit_pos = bit.pos % 8; 7675f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach if (!vCardType21 && bit.onlyCheckV21) return false; 7685f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach if (vCardType21 && bit.excludeForV21) return true; 7695f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach if (filter == null || offset >= filter.length) return false; 7705f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach return ((filter[filter.length - offset] >> bit_pos) & 0x01) != 0; 7715f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach } 7725f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach 7735f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach VCardFilter(byte[] filter) { 7745f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach this.filter = filter; 7755f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach } 7765f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach 7775f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach public boolean isPhotoEnabled() { 7785f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach return !isFilteredOut(FilterBit.PHOTO, false); 7795f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach } 7805f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach 7815f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach public String apply(String vCard, boolean vCardType21){ 7825f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach if (filter == null) return vCard; 7835f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach String lines[] = vCard.split(SEPARATOR); 7845f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach StringBuilder filteredVCard = new StringBuilder(); 7855f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach boolean filteredOut = false; 7865f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach 7875f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach for (String line : lines) { 7885f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach // Check whether the current property is changing (ignoring multi-line properties) 7895f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach // and determine if the current property is filtered in. 7905f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach if (!Character.isWhitespace(line.charAt(0)) && !line.startsWith("=")) { 7915f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach String currentProp = line.split("[;:]")[0]; 7925f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach filteredOut = false; 7935f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach 7945f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach for (FilterBit bit : FilterBit.values()) { 7955f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach if (bit.prop.equals(currentProp)) { 7965f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach filteredOut = isFilteredOut(bit, vCardType21); 7975f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach break; 7986db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta } 7996db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta } 8006db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta 8015f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach // Since PBAP does not have filter bits for IM and SIP, 8025f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach // exclude them by default. Easiest way is to exclude all 8035f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach // X- fields.... 8045f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach if (currentProp.startsWith("X-")) filteredOut = true; 8056db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta } 8066db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta 8075f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach // Build filtered vCard 8085f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach if (!filteredOut) filteredVCard.append(line + SEPARATOR); 8096db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta } 8106db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta 8115f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach return filteredVCard.toString(); 8126db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta } 8136db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta } 8145006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai 8155006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai private static final Uri getPhoneUri() { 8165006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai return Phone.ENTERPRISE_CONTENT_URI; 8175006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 8185006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai 8195006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai private static final Uri getPhoneLookupFilterUri() { 8205006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai return PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI; 8215006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 8225006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai 8235006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai /** 8245006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai * Get size of the cursor without duplicated contact id. This assumes the 8255006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai * given cursor is sorted by CONATCT_ID. 8265006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai */ 8275006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai private static final int getDistinctContactIdSize(Cursor cursor) { 8285006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai final int contactIdColumn = cursor.getColumnIndex(Data.CONTACT_ID); 8295006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai long previousContactId = -1; 8305006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai int count = 0; 8315006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai cursor.moveToPosition(-1); 8325006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai while (cursor.moveToNext()) { 8335006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai final long contactId = cursor.getLong(contactIdColumn); 8345006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (previousContactId != contactId) { 8355006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai count++; 8365006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai previousContactId = contactId; 8375006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 8385006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 8395006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (V) { 8405006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai Log.i(TAG, "getDistinctContactIdSize result: " + count); 8415006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 8425006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai return count; 8435006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 8445006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai 8455006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai /** 8465006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai * Append "display_name,contact_id" string array from cursor to ArrayList. 8475006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai * This assumes the given cursor is sorted by CONATCT_ID. 8485006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai */ 8495006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai private static void appendDistinctNameIdList(ArrayList<String> resultList, 8505006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai String defaultName, Cursor cursor) { 8515006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai final int contactIdColumn = cursor.getColumnIndex(Data.CONTACT_ID); 8525006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai final int nameColumn = cursor.getColumnIndex(Data.DISPLAY_NAME); 8535006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai long previousContactId = -1; 8545006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai cursor.moveToPosition(-1); 8555006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai while (cursor.moveToNext()) { 8565006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai final long contactId = cursor.getLong(contactIdColumn); 8575006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai String displayName = nameColumn != -1 ? cursor.getString(nameColumn) : defaultName; 8585006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (TextUtils.isEmpty(displayName)) { 8595006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai displayName = defaultName; 8605006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 8615006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai 8625006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (previousContactId != contactId) { 8635006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai previousContactId = contactId; 8645006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai resultList.add(displayName + "," + contactId); 8655006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 8665006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 8675006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai if (V) { 8685006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai for (String nameId : resultList) { 8695006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai Log.i(TAG, "appendDistinctNameIdList result: " + nameId); 8705006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 8715006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 8725006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai } 8732c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan} 874