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