BluetoothPbapVcardManager.java revision 6a50944dff2081fc161974cfae7d85d834b123cf
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
369d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Makimport com.android.bluetooth.R;
379d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Makimport com.android.bluetooth.util.DevicePolicyUtils;
389d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Makimport com.android.vcard.VCardComposer;
399d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Makimport com.android.vcard.VCardConfig;
409d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Makimport com.android.vcard.VCardPhoneNumberTranslationCallback;
419d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak
422f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yueimport android.content.ContentResolver;
432f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yueimport android.content.Context;
44198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport android.database.Cursor;
459d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Makimport android.database.CursorWindowAllocationException;
465006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Waiimport android.database.MatrixCursor;
47198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport android.net.Uri;
48198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport android.provider.CallLog;
49198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport android.provider.CallLog.Calls;
502f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yueimport android.provider.ContactsContract.CommonDataKinds;
519d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Makimport android.provider.ContactsContract.CommonDataKinds.Phone;
522f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yueimport android.provider.ContactsContract.Contacts;
532f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yueimport android.provider.ContactsContract.Data;
540dcd2262d853c2011e11617a8efba6758370c41fLiejun Taoimport android.provider.ContactsContract.PhoneLookup;
555006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Waiimport android.provider.ContactsContract.RawContactsEntity;
56d956b40b2f59599447ae0fa0762e055c0c0ce1a3Daisuke Miyakawaimport android.telephony.PhoneNumberUtils;
57198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport android.text.TextUtils;
58198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport android.util.Log;
59198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
602f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yueimport java.io.IOException;
612f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yueimport java.io.OutputStream;
622c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanimport java.util.ArrayList;
635006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Waiimport java.util.Collections;
642c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
65198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport javax.obex.Operation;
66198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport javax.obex.ResponseCodes;
679d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Makimport javax.obex.ServerOperation;
68c7a57f31515107366589bd6875c3cc4af1fc806efredc
692c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fanpublic class BluetoothPbapVcardManager {
702f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    private static final String TAG = "BluetoothPbapVcardManager";
712c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
724446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    private static final boolean V = BluetoothPbapService.VERBOSE;
734446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
742c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private ContentResolver mResolver;
752c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
762c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    private Context mContext;
772c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
78e10881ae39eb4affb7a78827f2060964e8534515Daisuke Miyakawa    private static final int PHONE_NUMBER_COLUMN_INDEX = 3;
792c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
802f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    static final String SORT_ORDER_PHONE_NUMBER = CommonDataKinds.Phone.NUMBER + " ASC";
814446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
825006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    static final String[] PHONES_CONTACTS_PROJECTION = new String[] {
835006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            Phone.CONTACT_ID, // 0
845006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            Phone.DISPLAY_NAME, // 1
855006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    };
865006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai
875006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    static final String[] PHONE_LOOKUP_PROJECTION = new String[] {
885006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            PhoneLookup._ID, PhoneLookup.DISPLAY_NAME
892b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh    };
902b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh
912b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh    static final int CONTACTS_ID_COLUMN_INDEX = 0;
922b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh
932b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh    static final int CONTACTS_NAME_COLUMN_INDEX = 1;
942b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh
952b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh    // call histories use dynamic handles, and handles should order by date; the
962b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh    // most recently one should be the first handle. In table "calls", _id and
972b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh    // date are consistent in ordering, to implement simply, we sort by _id
982b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh    // here.
992b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh    static final String CALLLOG_SORT_ORDER = Calls._ID + " DESC";
1002b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh
101cd5ed0c7d04119e508fbddfd9656ef8559e3e524Lixin Yue    private static final String CLAUSE_ONLY_VISIBLE = Contacts.IN_VISIBLE_GROUP + "=1";
102cd5ed0c7d04119e508fbddfd9656ef8559e3e524Lixin Yue
1032c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    public BluetoothPbapVcardManager(final Context context) {
1042c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        mContext = context;
1052c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        mResolver = mContext.getContentResolver();
1062c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
1072c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
108c7a57f31515107366589bd6875c3cc4af1fc806efredc    /**
109c7a57f31515107366589bd6875c3cc4af1fc806efredc     * Create an owner vcard from the configured profile
110c7a57f31515107366589bd6875c3cc4af1fc806efredc     * @param vcardType21
111c7a57f31515107366589bd6875c3cc4af1fc806efredc     * @return
112c7a57f31515107366589bd6875c3cc4af1fc806efredc     */
113c7a57f31515107366589bd6875c3cc4af1fc806efredc    private final String getOwnerPhoneNumberVcardFromProfile(final boolean vcardType21, final byte[] filter) {
114c7a57f31515107366589bd6875c3cc4af1fc806efredc        // Currently only support Generic Vcard 2.1 and 3.0
115c7a57f31515107366589bd6875c3cc4af1fc806efredc        int vcardType;
116c7a57f31515107366589bd6875c3cc4af1fc806efredc        if (vcardType21) {
117c7a57f31515107366589bd6875c3cc4af1fc806efredc            vcardType = VCardConfig.VCARD_TYPE_V21_GENERIC;
118c7a57f31515107366589bd6875c3cc4af1fc806efredc        } else {
119c7a57f31515107366589bd6875c3cc4af1fc806efredc            vcardType = VCardConfig.VCARD_TYPE_V30_GENERIC;
120c7a57f31515107366589bd6875c3cc4af1fc806efredc        }
1214a53a55dc10d3a26c94e5844f7d4a2565a67142cfredc
1224a53a55dc10d3a26c94e5844f7d4a2565a67142cfredc        if (!BluetoothPbapConfig.includePhotosInVcard()) {
1234a53a55dc10d3a26c94e5844f7d4a2565a67142cfredc            vcardType |= VCardConfig.FLAG_REFRAIN_IMAGE_EXPORT;
1244a53a55dc10d3a26c94e5844f7d4a2565a67142cfredc        }
1254a53a55dc10d3a26c94e5844f7d4a2565a67142cfredc
126c7a57f31515107366589bd6875c3cc4af1fc806efredc        return BluetoothPbapUtils.createProfileVCard(mContext, vcardType,filter);
127c7a57f31515107366589bd6875c3cc4af1fc806efredc    }
128c7a57f31515107366589bd6875c3cc4af1fc806efredc
129c7a57f31515107366589bd6875c3cc4af1fc806efredc    public final String getOwnerPhoneNumberVcard(final boolean vcardType21, final byte[] filter) {
130c7a57f31515107366589bd6875c3cc4af1fc806efredc        //Owner vCard enhancement: Use "ME" profile if configured
131c7a57f31515107366589bd6875c3cc4af1fc806efredc        if (BluetoothPbapConfig.useProfileForOwnerVcard()) {
132c7a57f31515107366589bd6875c3cc4af1fc806efredc            String vcard = getOwnerPhoneNumberVcardFromProfile(vcardType21, filter);
133c7a57f31515107366589bd6875c3cc4af1fc806efredc            if (vcard != null && vcard.length() != 0) {
134c7a57f31515107366589bd6875c3cc4af1fc806efredc                return vcard;
135c7a57f31515107366589bd6875c3cc4af1fc806efredc            }
136c7a57f31515107366589bd6875c3cc4af1fc806efredc        }
137c7a57f31515107366589bd6875c3cc4af1fc806efredc        //End enhancement
138c7a57f31515107366589bd6875c3cc4af1fc806efredc
1393c4d2c77c2fffe675fbe89ba58856686b6873d2fDaisuke Miyakawa        BluetoothPbapCallLogComposer composer = new BluetoothPbapCallLogComposer(mContext);
1402f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        String name = BluetoothPbapService.getLocalPhoneName();
1412f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        String number = BluetoothPbapService.getLocalPhoneNum();
1422f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        String vcard = composer.composeVCardForPhoneOwnNumber(Phone.TYPE_MOBILE, name, number,
1432f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                vcardType21);
1442f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        return vcard;
1452c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
1462c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1472f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    public final int getPhonebookSize(final int type) {
1482f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        int size;
1492f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        switch (type) {
1502f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            case BluetoothPbapObexServer.ContentType.PHONEBOOK:
1512f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                size = getContactsSize();
1522f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                break;
1532f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            default:
1542f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                size = getCallHistorySize(type);
1552f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                break;
1562c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
157c7a57f31515107366589bd6875c3cc4af1fc806efredc        if (V) Log.v(TAG, "getPhonebookSize size = " + size + " type = " + type);
1582f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        return size;
1592c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
1602c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1612f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    public final int getContactsSize() {
1623178b08c6823899dbb58513673bf2a80f637be7cRicky Wai        final Uri myUri = DevicePolicyUtils.getEnterprisePhoneUri(mContext);
1632f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        Cursor contactCursor = null;
1642f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        try {
1655006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            contactCursor = mResolver.query(myUri, new String[] {Phone.CONTACT_ID},
1665006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    CLAUSE_ONLY_VISIBLE, null, Phone.CONTACT_ID);
1675006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            if (contactCursor == null) {
1685006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                return 0;
1692f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            }
1709d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak            return getDistinctContactIdSize(contactCursor, Phone.CONTACT_ID)
1719d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak                    + 1; // always has the 0.vcf
172c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta        } catch (CursorWindowAllocationException e) {
173c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta            Log.e(TAG, "CursorWindowAllocationException while getting Contacts size");
1742f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        } finally {
1752f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (contactCursor != null) {
1762f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                contactCursor.close();
1772f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            }
1782c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
1795006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        return 0;
1802c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
1812c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
1822f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    public final int getCallHistorySize(final int type) {
1832b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        final Uri myUri = CallLog.Calls.CONTENT_URI;
1842f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        String selection = BluetoothPbapObexServer.createSelectionPara(type);
1852f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        int size = 0;
1862f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        Cursor callCursor = null;
1872f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        try {
1882f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            callCursor = mResolver.query(myUri, null, selection, null,
1892f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                    CallLog.Calls.DEFAULT_SORT_ORDER);
1902f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (callCursor != null) {
1912f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                size = callCursor.getCount();
1924446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            }
193c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta        } catch (CursorWindowAllocationException e) {
194c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta            Log.e(TAG, "CursorWindowAllocationException while getting CallHistory size");
1952f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        } finally {
1962f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (callCursor != null) {
1972f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                callCursor.close();
198c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta                callCursor = null;
1994446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            }
2002f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        }
2012f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        return size;
2022f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    }
2034446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
2042f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    public final ArrayList<String> loadCallHistoryList(final int type) {
2052b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        final Uri myUri = CallLog.Calls.CONTENT_URI;
2062f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        String selection = BluetoothPbapObexServer.createSelectionPara(type);
2072f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        String[] projection = new String[] {
2089674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner                Calls.NUMBER, Calls.CACHED_NAME, Calls.NUMBER_PRESENTATION
2092f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        };
2102f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        final int CALLS_NUMBER_COLUMN_INDEX = 0;
2112f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        final int CALLS_NAME_COLUMN_INDEX = 1;
2129674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner        final int CALLS_NUMBER_PRESENTATION_COLUMN_INDEX = 2;
2132f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue
2142f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        Cursor callCursor = null;
2152f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        ArrayList<String> list = new ArrayList<String>();
2162f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        try {
2172f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            callCursor = mResolver.query(myUri, projection, selection, null,
2182b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh                    CALLLOG_SORT_ORDER);
2192f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (callCursor != null) {
2202f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                for (callCursor.moveToFirst(); !callCursor.isAfterLast();
2212f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                        callCursor.moveToNext()) {
2222f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                    String name = callCursor.getString(CALLS_NAME_COLUMN_INDEX);
2232f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                    if (TextUtils.isEmpty(name)) {
22477ba5f6684f4dd7e4b7fc37982271da5654aec07Staffan Lindvall                        // name not found, use number instead
2259674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner                        final int numberPresentation = callCursor.getInt(
2269674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner                                CALLS_NUMBER_PRESENTATION_COLUMN_INDEX);
2279674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner                        if (numberPresentation != Calls.PRESENTATION_ALLOWED) {
22877ba5f6684f4dd7e4b7fc37982271da5654aec07Staffan Lindvall                            name = mContext.getString(R.string.unknownNumber);
2299674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner                        } else {
2309674eb043aeb1474aa23ddd0739e3b8f05432630Jay Shrauner                            name = callCursor.getString(CALLS_NUMBER_COLUMN_INDEX);
23177ba5f6684f4dd7e4b7fc37982271da5654aec07Staffan Lindvall                        }
2322f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                    }
2332f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                    list.add(name);
2342f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                }
2352f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            }
236c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta        } catch (CursorWindowAllocationException e) {
237c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta            Log.e(TAG, "CursorWindowAllocationException while loading CallHistory");
2382f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        } finally {
2392f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (callCursor != null) {
2402f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                callCursor.close();
241c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta                callCursor = null;
2422c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
2432c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
2442f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        return list;
2452c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
2462c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
2472b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh    public final ArrayList<String> getPhonebookNameList(final int orderByWhat) {
2482f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        ArrayList<String> nameList = new ArrayList<String>();
249c7a57f31515107366589bd6875c3cc4af1fc806efredc        //Owner vCard enhancement. Use "ME" profile if configured
250c7a57f31515107366589bd6875c3cc4af1fc806efredc        String ownerName = null;
251c7a57f31515107366589bd6875c3cc4af1fc806efredc        if (BluetoothPbapConfig.useProfileForOwnerVcard()) {
252c7a57f31515107366589bd6875c3cc4af1fc806efredc            ownerName = BluetoothPbapUtils.getProfileName(mContext);
253c7a57f31515107366589bd6875c3cc4af1fc806efredc        }
254c7a57f31515107366589bd6875c3cc4af1fc806efredc        if (ownerName == null || ownerName.length()==0) {
255c7a57f31515107366589bd6875c3cc4af1fc806efredc            ownerName = BluetoothPbapService.getLocalPhoneName();
256c7a57f31515107366589bd6875c3cc4af1fc806efredc        }
257c7a57f31515107366589bd6875c3cc4af1fc806efredc        nameList.add(ownerName);
258c7a57f31515107366589bd6875c3cc4af1fc806efredc        //End enhancement
2594446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
2603178b08c6823899dbb58513673bf2a80f637be7cRicky Wai        final Uri myUri = DevicePolicyUtils.getEnterprisePhoneUri(mContext);
2612b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        Cursor contactCursor = null;
2623c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta        // By default order is indexed
2633c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta        String orderBy = Phone.CONTACT_ID;
2642f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        try {
2653c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta            if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_ALPHABETICAL) {
2663c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta                orderBy = Phone.DISPLAY_NAME;
2673c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta            }
2683c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta            contactCursor = mResolver.query(myUri, PHONES_CONTACTS_PROJECTION,
2693c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta                CLAUSE_ONLY_VISIBLE, null, orderBy);
2702b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            if (contactCursor != null) {
2715006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                appendDistinctNameIdList(nameList,
2729d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak                        mContext.getString(android.R.string.unknownName), contactCursor,
2739d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak                        Phone.CONTACT_ID, Phone.DISPLAY_NAME);
2745006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_INDEXED) {
2755006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    if (V) Log.v(TAG, "getPhonebookNameList, order by index");
2765006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    // Do not need to do anything, as we sort it by index already
2775006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                } else if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_ALPHABETICAL) {
2785006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    if (V) Log.v(TAG, "getPhonebookNameList, order by alpha");
2795006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    Collections.sort(nameList);
2802f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                }
2812f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            }
2823c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta        } catch (CursorWindowAllocationException e) {
2833c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta            Log.e(TAG, "CursorWindowAllocationException while getting phonebook name list");
284bf37a0295d110b77b635ca2986172bbdd59331bbAndre Eisenbach        } catch (Exception e) {
2853c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta            Log.e(TAG, "Exception while getting phonebook name list", e);
2862f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        } finally {
2872b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            if (contactCursor != null) {
2882b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh                contactCursor.close();
289c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta                contactCursor = null;
2902f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            }
2912f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        }
2922f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        return nameList;
2934446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    }
2944446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
2950dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao    public final ArrayList<String> getContactNamesByNumber(final String phoneNumber) {
2960dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao        ArrayList<String> nameList = new ArrayList<String>();
2971321cd814a7406260ba6282d9c71e1a2d8925262Hemant Gupta        ArrayList<String> tempNameList = new ArrayList<String>();
2980dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao
2990dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao        Cursor contactCursor = null;
3009d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak        Uri uri;
3019d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak        final String[] projection;
3029d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak        final String contactIdColumn, displayNameColumn;
3035006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        if (TextUtils.isEmpty(phoneNumber)) {
3043178b08c6823899dbb58513673bf2a80f637be7cRicky Wai            uri = DevicePolicyUtils.getEnterprisePhoneUri(mContext);
3059d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak            contactIdColumn = Phone.CONTACT_ID;
3069d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak            displayNameColumn = Phone.DISPLAY_NAME;
3074bba23a751f042596561eab0e677135d5267bcdfStaffan Lindvall        } else {
3089d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak            uri = Uri.withAppendedPath(getPhoneLookupFilterUri(), Uri.encode(phoneNumber));
3099d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak            contactIdColumn = PhoneLookup._ID;
3109d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak            displayNameColumn = PhoneLookup.DISPLAY_NAME;
3114bba23a751f042596561eab0e677135d5267bcdfStaffan Lindvall        }
3129d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak        projection = new String[]{contactIdColumn, displayNameColumn};
3134446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
3142f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        try {
3159d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak            contactCursor = mResolver
3169d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak                    .query(uri, projection, CLAUSE_ONLY_VISIBLE, null, contactIdColumn);
3170dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao
3180dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao            if (contactCursor != null) {
3195006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                appendDistinctNameIdList(nameList,
3205006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                        mContext.getString(android.R.string.unknownName),
3219d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak                        contactCursor, contactIdColumn, displayNameColumn);
3225006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                if (V) {
3235006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    for (String nameIdStr : nameList) {
3245006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                        Log.v(TAG, "got name " + nameIdStr + " by number " + phoneNumber);
3252f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                    }
3262f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                }
3272f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            }
328c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta        } catch (CursorWindowAllocationException e) {
329c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta            Log.e(TAG, "CursorWindowAllocationException while getting contact names");
3302f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        } finally {
3310dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao            if (contactCursor != null) {
3320dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao                contactCursor.close();
333c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta                contactCursor = null;
3342f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            }
3352c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
3361321cd814a7406260ba6282d9c71e1a2d8925262Hemant Gupta        int tempListSize = tempNameList.size();
3371321cd814a7406260ba6282d9c71e1a2d8925262Hemant Gupta        for (int index = 0; index < tempListSize; index++) {
3381321cd814a7406260ba6282d9c71e1a2d8925262Hemant Gupta            String object = tempNameList.get(index);
3391321cd814a7406260ba6282d9c71e1a2d8925262Hemant Gupta            if (!nameList.contains(object))
3401321cd814a7406260ba6282d9c71e1a2d8925262Hemant Gupta                nameList.add(object);
3411321cd814a7406260ba6282d9c71e1a2d8925262Hemant Gupta        }
3421321cd814a7406260ba6282d9c71e1a2d8925262Hemant Gupta
3430dcd2262d853c2011e11617a8efba6758370c41fLiejun Tao        return nameList;
3442c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
3452c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
3460b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue    public final int composeAndSendCallLogVcards(final int type, Operation op,
3476db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta            final int startPoint, final int endPoint, final boolean vcardType21,
3486db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta            boolean ignorefilter, byte[] filter) {
34959256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        if (startPoint < 1 || startPoint > endPoint) {
35059256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            Log.e(TAG, "internal error: startPoint or endPoint is not correct.");
35159256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
35259256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        }
3532f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        String typeSelection = BluetoothPbapObexServer.createSelectionPara(type);
35459256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh
3552b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        final Uri myUri = CallLog.Calls.CONTENT_URI;
35659256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        final String[] CALLLOG_PROJECTION = new String[] {
35759256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            CallLog.Calls._ID, // 0
35859256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        };
35959256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        final int ID_COLUMN_INDEX = 0;
36059256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh
36159256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        Cursor callsCursor = null;
36259256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        long startPointId = 0;
36359256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        long endPointId = 0;
36459256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        try {
36559256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            // Need test to see if order by _ID is ok here, or by date?
36659256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            callsCursor = mResolver.query(myUri, CALLLOG_PROJECTION, typeSelection, null,
3672b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh                    CALLLOG_SORT_ORDER);
36859256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            if (callsCursor != null) {
36959256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh                callsCursor.moveToPosition(startPoint - 1);
37059256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh                startPointId = callsCursor.getLong(ID_COLUMN_INDEX);
37159256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh                if (V) Log.v(TAG, "Call Log query startPointId = " + startPointId);
37259256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh                if (startPoint == endPoint) {
37359256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh                    endPointId = startPointId;
37459256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh                } else {
37559256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh                    callsCursor.moveToPosition(endPoint - 1);
37659256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh                    endPointId = callsCursor.getLong(ID_COLUMN_INDEX);
37759256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh                }
37859256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh                if (V) Log.v(TAG, "Call log query endPointId = " + endPointId);
37959256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            }
380c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta        } catch (CursorWindowAllocationException e) {
381c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta            Log.e(TAG, "CursorWindowAllocationException while composing calllog vcards");
38259256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        } finally {
38359256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            if (callsCursor != null) {
38459256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh                callsCursor.close();
385c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta                callsCursor = null;
38659256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            }
38759256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        }
38859256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh
3892f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        String recordSelection;
3902f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        if (startPoint == endPoint) {
39159256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            recordSelection = Calls._ID + "=" + startPointId;
3922f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        } else {
3932b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            // The query to call table is by "_id DESC" order, so change
3942b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            // correspondingly.
3952b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            recordSelection = Calls._ID + ">=" + endPointId + " AND " + Calls._ID + "<="
3962b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh                    + startPointId;
3974446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        }
3984446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
3992f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        String selection;
4002f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        if (typeSelection == null) {
4012f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            selection = recordSelection;
4022f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        } else {
4032f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            selection = "(" + typeSelection + ") AND (" + recordSelection + ")";
4044446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        }
4054446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
40659256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        if (V) Log.v(TAG, "Call log query selection is: " + selection);
4074446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
4085006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        return composeCallLogsAndSendVCards(op, selection, vcardType21, null, ignorefilter, filter);
4094446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    }
4104446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
4110b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue    public final int composeAndSendPhonebookVcards(Operation op, final int startPoint,
4126db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta            final int endPoint, final boolean vcardType21, String ownerVCard,
4136db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta            boolean ignorefilter, byte[] filter) {
41459256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        if (startPoint < 1 || startPoint > endPoint) {
41559256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            Log.e(TAG, "internal error: startPoint or endPoint is not correct.");
41659256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
41759256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        }
41859256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh
4193178b08c6823899dbb58513673bf2a80f637be7cRicky Wai        final Uri myUri = DevicePolicyUtils.getEnterprisePhoneUri(mContext);
42059256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        Cursor contactCursor = null;
4210ff315d60bb44c5cc4223abff48e086defaec8adTony Mak        Cursor contactIdCursor = new MatrixCursor(new String[] {
4220ff315d60bb44c5cc4223abff48e086defaec8adTony Mak            Phone.CONTACT_ID
4230ff315d60bb44c5cc4223abff48e086defaec8adTony Mak        });
42459256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        try {
4255006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            contactCursor = mResolver.query(myUri, PHONES_CONTACTS_PROJECTION, CLAUSE_ONLY_VISIBLE,
4265006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    null, Phone.CONTACT_ID);
42759256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            if (contactCursor != null) {
4280ff315d60bb44c5cc4223abff48e086defaec8adTony Mak                contactIdCursor = ContactCursorFilter.filterByRange(contactCursor, startPoint,
4290ff315d60bb44c5cc4223abff48e086defaec8adTony Mak                        endPoint);
43059256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            }
431c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta        } catch (CursorWindowAllocationException e) {
432c592e5a6de0011cd60f23ac18a7bd56d8eeb5dd1Hemant Gupta            Log.e(TAG, "CursorWindowAllocationException while composing phonebook vcards");
43359256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        } finally {
43459256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            if (contactCursor != null) {
43559256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh                contactCursor.close();
43659256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh            }
43759256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh        }
4380ff315d60bb44c5cc4223abff48e086defaec8adTony Mak        return composeContactsAndSendVCards(op, contactIdCursor, vcardType21, ownerVCard,
4390ff315d60bb44c5cc4223abff48e086defaec8adTony Mak                ignorefilter, filter);
4404446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    }
4414446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
4420b1b0069658326e8c12dc0f887e4319c5227feb5Lixin Yue    public final int composeAndSendPhonebookOneVcard(Operation op, final int offset,
4436db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta            final boolean vcardType21, String ownerVCard, int orderByWhat,
4446db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta            boolean ignorefilter, byte[] filter) {
4452b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        if (offset < 1) {
4462b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            Log.e(TAG, "Internal error: offset is not correct.");
4472b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
4482b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        }
4493178b08c6823899dbb58513673bf2a80f637be7cRicky Wai        final Uri myUri = DevicePolicyUtils.getEnterprisePhoneUri(mContext);
4500ff315d60bb44c5cc4223abff48e086defaec8adTony Mak
4512b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        Cursor contactCursor = null;
4520ff315d60bb44c5cc4223abff48e086defaec8adTony Mak        Cursor contactIdCursor = new MatrixCursor(new String[] {
4530ff315d60bb44c5cc4223abff48e086defaec8adTony Mak            Phone.CONTACT_ID
4540ff315d60bb44c5cc4223abff48e086defaec8adTony Mak        });
4553c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta        // By default order is indexed
4563c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta        String orderBy = Phone.CONTACT_ID;
4575006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        try {
4583c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta            if (orderByWhat == BluetoothPbapObexServer.ORDER_BY_ALPHABETICAL) {
4593c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta                orderBy = Phone.DISPLAY_NAME;
4603c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta            }
4615006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            contactCursor = mResolver.query(myUri, PHONES_CONTACTS_PROJECTION,
4623c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta                CLAUSE_ONLY_VISIBLE, null, orderBy);
4635006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        } catch (CursorWindowAllocationException e) {
4645006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            Log.e(TAG,
4653c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta                "CursorWindowAllocationException while composing phonebook one vcard");
4665006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        } finally {
4675006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            if (contactCursor != null) {
4683c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta                contactIdCursor = ContactCursorFilter.filterByOffset(contactCursor, offset);
4695006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                contactCursor.close();
4703c8b50f8dc1c4ce11168fb42a884f604d1810c46Hemant Gupta                contactCursor = null;
4712b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            }
4725006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        }
4730ff315d60bb44c5cc4223abff48e086defaec8adTony Mak        return composeContactsAndSendVCards(op, contactIdCursor, vcardType21, ownerVCard,
4740ff315d60bb44c5cc4223abff48e086defaec8adTony Mak                ignorefilter, filter);
4750ff315d60bb44c5cc4223abff48e086defaec8adTony Mak    }
4760ff315d60bb44c5cc4223abff48e086defaec8adTony Mak
4770ff315d60bb44c5cc4223abff48e086defaec8adTony Mak    /**
4780ff315d60bb44c5cc4223abff48e086defaec8adTony Mak     * Filter contact cursor by certain condition.
4790ff315d60bb44c5cc4223abff48e086defaec8adTony Mak     */
4800ff315d60bb44c5cc4223abff48e086defaec8adTony Mak    public static final class ContactCursorFilter {
4810ff315d60bb44c5cc4223abff48e086defaec8adTony Mak        /**
4820ff315d60bb44c5cc4223abff48e086defaec8adTony Mak         *
4830ff315d60bb44c5cc4223abff48e086defaec8adTony Mak         * @param contactCursor
4840ff315d60bb44c5cc4223abff48e086defaec8adTony Mak         * @param offset
4850ff315d60bb44c5cc4223abff48e086defaec8adTony Mak         * @return a cursor containing contact id of {@code offset} contact.
4860ff315d60bb44c5cc4223abff48e086defaec8adTony Mak         */
4870ff315d60bb44c5cc4223abff48e086defaec8adTony Mak        public static Cursor filterByOffset(Cursor contactCursor, int offset) {
4880ff315d60bb44c5cc4223abff48e086defaec8adTony Mak            return filterByRange(contactCursor, offset, offset);
4890ff315d60bb44c5cc4223abff48e086defaec8adTony Mak        }
4900ff315d60bb44c5cc4223abff48e086defaec8adTony Mak
4910ff315d60bb44c5cc4223abff48e086defaec8adTony Mak        /**
4920ff315d60bb44c5cc4223abff48e086defaec8adTony Mak         *
4930ff315d60bb44c5cc4223abff48e086defaec8adTony Mak         * @param contactCursor
4940ff315d60bb44c5cc4223abff48e086defaec8adTony Mak         * @param startPoint
4950ff315d60bb44c5cc4223abff48e086defaec8adTony Mak         * @param endPoint
4960ff315d60bb44c5cc4223abff48e086defaec8adTony Mak         * @return a cursor containing contact ids of {@code startPoint}th to {@code endPoint}th
4970ff315d60bb44c5cc4223abff48e086defaec8adTony Mak         * contact.
4980ff315d60bb44c5cc4223abff48e086defaec8adTony Mak         */
4990ff315d60bb44c5cc4223abff48e086defaec8adTony Mak        public static Cursor filterByRange(Cursor contactCursor, int startPoint, int endPoint) {
5000ff315d60bb44c5cc4223abff48e086defaec8adTony Mak            final int contactIdColumn = contactCursor.getColumnIndex(Data.CONTACT_ID);
5010ff315d60bb44c5cc4223abff48e086defaec8adTony Mak            long previousContactId = -1;
5020ff315d60bb44c5cc4223abff48e086defaec8adTony Mak            // As startPoint, endOffset index starts from 1 to n, we set
5030ff315d60bb44c5cc4223abff48e086defaec8adTony Mak            // currentPoint base as 1 not 0
5040ff315d60bb44c5cc4223abff48e086defaec8adTony Mak            int currentOffset = 1;
5050ff315d60bb44c5cc4223abff48e086defaec8adTony Mak            final MatrixCursor contactIdsCursor = new MatrixCursor(new String[]{
5060ff315d60bb44c5cc4223abff48e086defaec8adTony Mak                    Phone.CONTACT_ID
5070ff315d60bb44c5cc4223abff48e086defaec8adTony Mak            });
5080ff315d60bb44c5cc4223abff48e086defaec8adTony Mak            while (contactCursor.moveToNext() && currentOffset <= endPoint) {
5090ff315d60bb44c5cc4223abff48e086defaec8adTony Mak                long currentContactId = contactCursor.getLong(contactIdColumn);
5100ff315d60bb44c5cc4223abff48e086defaec8adTony Mak                if (previousContactId != currentContactId) {
5110ff315d60bb44c5cc4223abff48e086defaec8adTony Mak                    previousContactId = currentContactId;
5120ff315d60bb44c5cc4223abff48e086defaec8adTony Mak                    if (currentOffset >= startPoint) {
5130ff315d60bb44c5cc4223abff48e086defaec8adTony Mak                        contactIdsCursor.addRow(new Long[]{currentContactId});
5140ff315d60bb44c5cc4223abff48e086defaec8adTony Mak                        if (V) Log.v(TAG, "contactIdsCursor.addRow: " + currentContactId);
5150ff315d60bb44c5cc4223abff48e086defaec8adTony Mak                    }
5160ff315d60bb44c5cc4223abff48e086defaec8adTony Mak                    currentOffset++;
5172b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh                }
5182b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh            }
5190ff315d60bb44c5cc4223abff48e086defaec8adTony Mak            return contactIdsCursor;
5202b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh        }
5212b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh    }
5222b36e1731eb5ed784abc1a374eb69d8523123df1Jaikumar Ganesh
5235006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    /**
5245006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai     * Handler enterprise contact id in VCardComposer
5255006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai     */
5265006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    private static class EnterpriseRawContactEntitlesInfoCallback implements
5275006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            VCardComposer.RawContactEntitlesInfoCallback {
5285006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        @Override
5295006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        public VCardComposer.RawContactEntitlesInfo getRawContactEntitlesInfo(long contactId) {
5305006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            if (Contacts.isEnterpriseContactId(contactId)) {
5315006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                return new VCardComposer.RawContactEntitlesInfo(RawContactsEntity.CORP_CONTENT_URI,
5325006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                        contactId - Contacts.ENTERPRISE_CONTACT_ID_BASE);
5335006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            } else {
5345006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                return new VCardComposer.RawContactEntitlesInfo(RawContactsEntity.CONTENT_URI, contactId);
5355006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            }
5365006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        }
5375006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    }
5385006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai
5395006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    public final int composeContactsAndSendVCards(Operation op, final Cursor contactIdCursor,
5405006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            final boolean vcardType21, String ownerVCard, boolean ignorefilter, byte[] filter) {
5412f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        long timestamp = 0;
5422f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        if (V) timestamp = System.currentTimeMillis();
5434446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
5445006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        VCardComposer composer = null;
5455006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        VCardFilter vcardfilter = new VCardFilter(ignorefilter ? null : filter);
5465f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach
5475006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        HandlerForStringBuffer buffer = null;
5485006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        try {
5495006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            // Currently only support Generic Vcard 2.1 and 3.0
5505006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            int vcardType;
5515006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            if (vcardType21) {
5525006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                vcardType = VCardConfig.VCARD_TYPE_V21_GENERIC;
5535006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            } else {
5545006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                vcardType = VCardConfig.VCARD_TYPE_V30_GENERIC;
5555006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            }
5565006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            if (!vcardfilter.isPhotoEnabled()) {
5575006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                vcardType |= VCardConfig.FLAG_REFRAIN_IMAGE_EXPORT;
5585006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            }
5595006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai
5605006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            // Enhancement: customize Vcard based on preferences/settings and
5615006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            // input from caller
5625006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            composer = BluetoothPbapUtils.createFilteredVCardComposer(mContext, vcardType, null);
5635006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            // End enhancement
5645006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai
5655006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            // BT does want PAUSE/WAIT conversion while it doesn't want the
5665006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            // other formatting
5675006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            // done by vCard library by default.
5685006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            composer.setPhoneNumberTranslationCallback(new VCardPhoneNumberTranslationCallback() {
5695006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                public String onValueReceived(String rawValue, int type, String label,
5705006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                        boolean isPrimary) {
5715006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    // 'p' and 'w' are the standard characters for pause and
5725006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    // wait
5735006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    // (see RFC 3601)
5745006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    // so use those when exporting phone numbers via vCard.
5755006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    String numberWithControlSequence = rawValue
5765006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                            .replace(PhoneNumberUtils.PAUSE, 'p').replace(PhoneNumberUtils.WAIT,
5775006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                                    'w');
5785006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    return numberWithControlSequence;
5794a53a55dc10d3a26c94e5844f7d4a2565a67142cfredc                }
5805006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            });
5815006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            buffer = new HandlerForStringBuffer(op, ownerVCard);
5825006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            Log.v(TAG, "contactIdCursor size: " + contactIdCursor.getCount());
5835006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            if (!composer.initWithCallback(contactIdCursor,
5845006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    new EnterpriseRawContactEntitlesInfoCallback())
5855006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    || !buffer.onInit(mContext)) {
5865006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
5875006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            }
5884446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
5895006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            while (!composer.isAfterLast()) {
5905006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                if (BluetoothPbapObexServer.sIsAborted) {
5915006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    ((ServerOperation) op).isAborted = true;
5925006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    BluetoothPbapObexServer.sIsAborted = false;
5935006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    break;
5945006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                }
5955006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                String vcard = composer.createOneEntry();
5965006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                if (vcard == null) {
5975006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    Log.e(TAG,
5985006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                            "Failed to read a contact. Error reason: " + composer.getErrorReason());
5992f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                    return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
6004446eaa935994bc91d6d308303e8d27526b4590dLixin Yue                }
6015006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                if (V) Log.v(TAG, "vCard from composer: " + vcard);
602198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
6035006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                vcard = vcardfilter.apply(vcard, vcardType21);
6045006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                vcard = StripTelephoneNumber(vcard);
6055f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach
6065006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                if (V) Log.v(TAG, "vCard after cleanup: " + vcard);
607c7a57f31515107366589bd6875c3cc4af1fc806efredc
6085006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                if (!buffer.onEntryCreated(vcard)) {
6095006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    // onEntryCreate() already emits error.
6105006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
6113c4d2c77c2fffe675fbe89ba58856686b6873d2fDaisuke Miyakawa                }
6124446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            }
6135006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        } finally {
6145006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            if (composer != null) {
6155006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                composer.terminate();
6165006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            }
6175006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            if (buffer != null) {
6185006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                buffer.onTerminate();
6195006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            }
6205006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        }
6213c4d2c77c2fffe675fbe89ba58856686b6873d2fDaisuke Miyakawa
6225006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        if (V) Log.v(TAG, "Total vcard composing and sending out takes "
6235006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    + (System.currentTimeMillis() - timestamp) + " ms");
624198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
6255006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        return ResponseCodes.OBEX_HTTP_OK;
6265006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    }
6275006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai
6285006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    public final int composeCallLogsAndSendVCards(Operation op, final String selection,
6295006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            final boolean vcardType21, String ownerVCard, boolean ignorefilter,
6305006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            byte[] filter) {
6315006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        long timestamp = 0;
6325006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        if (V) timestamp = System.currentTimeMillis();
6335006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai
6345006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        BluetoothPbapCallLogComposer composer = null;
6355006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        HandlerForStringBuffer buffer = null;
6365006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        try {
6375006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai
6385006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            composer = new BluetoothPbapCallLogComposer(mContext);
6395006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            buffer = new HandlerForStringBuffer(op, ownerVCard);
6405006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            if (!composer.init(CallLog.Calls.CONTENT_URI, selection, null, CALLLOG_SORT_ORDER)
6415006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    || !buffer.onInit(mContext)) {
6425006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
6435006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            }
644c7a57f31515107366589bd6875c3cc4af1fc806efredc
6455006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            while (!composer.isAfterLast()) {
6465006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                if (BluetoothPbapObexServer.sIsAborted) {
6475006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    ((ServerOperation) op).isAborted = true;
6485006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    BluetoothPbapObexServer.sIsAborted = false;
6495006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    break;
650198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa                }
6515006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                String vcard = composer.createOneEntry(vcardType21);
6525006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                if (vcard == null) {
6535006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    Log.e(TAG,
6545006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                            "Failed to read a contact. Error reason: " + composer.getErrorReason());
6555006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
656198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa                }
6575006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                if (V) {
6585006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    Log.v(TAG, "Vcard Entry:");
6595006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                    Log.v(TAG, vcard);
6603c4d2c77c2fffe675fbe89ba58856686b6873d2fDaisuke Miyakawa                }
6615006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai
6625006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                buffer.onEntryCreated(vcard);
6635006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            }
6645006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        } finally {
6655006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            if (composer != null) {
6665006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                composer.terminate();
6675006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            }
6685006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            if (buffer != null) {
6695006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                buffer.onTerminate();
6704446eaa935994bc91d6d308303e8d27526b4590dLixin Yue            }
6714446eaa935994bc91d6d308303e8d27526b4590dLixin Yue        }
6724446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
6732f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        if (V) Log.v(TAG, "Total vcard composing and sending out takes "
6745006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                + (System.currentTimeMillis() - timestamp) + " ms");
6752f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        return ResponseCodes.OBEX_HTTP_OK;
6764446eaa935994bc91d6d308303e8d27526b4590dLixin Yue    }
6774446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
67829ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta    public String StripTelephoneNumber (String vCard){
67929ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta        String attr [] = vCard.split(System.getProperty("line.separator"));
68029ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta        String Vcard = "";
68129ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta            for (int i=0; i < attr.length; i++) {
68229ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta                if(attr[i].startsWith("TEL")) {
68329ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta                    attr[i] = attr[i].replace("(", "");
68429ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta                    attr[i] = attr[i].replace(")", "");
68529ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta                    attr[i] = attr[i].replace("-", "");
68629ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta                    attr[i] = attr[i].replace(" ", "");
68729ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta                }
68829ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta            }
68929ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta
69029ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta            for (int i=0; i < attr.length; i++) {
69129ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta                if(!attr[i].equals("")){
69229ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta                    Vcard = Vcard.concat(attr[i] + "\n");
69329ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta                }
69429ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta            }
69502fc1acb99dbf3ae0a710ee7e4b6de8dd779e84eRakesh Iyer        if (V) Log.v(TAG, "Vcard with stripped telephone no.: " + Vcard);
69629ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta        return Vcard;
69729ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta    }
69829ab94a024ffce08229f1c2c6776d1e72d2a3f75Hemant Gupta
6992f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue    /**
700ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita     * Handler to emit vCards to PCE.
7012f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue     */
7023c4d2c77c2fffe675fbe89ba58856686b6873d2fDaisuke Miyakawa    public class HandlerForStringBuffer {
7032f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        private Operation operation;
7044446eaa935994bc91d6d308303e8d27526b4590dLixin Yue
7052f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        private OutputStream outputStream;
7062f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue
7072f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        private String phoneOwnVCard = null;
7082f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue
7092f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        public HandlerForStringBuffer(Operation op, String ownerVCard) {
7102f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            operation = op;
7112f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (ownerVCard != null) {
7122f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                phoneOwnVCard = ownerVCard;
7132f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                if (V) Log.v(TAG, "phone own number vcard:");
7142f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                if (V) Log.v(TAG, phoneOwnVCard);
7152c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
7162c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
7172c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
718ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita        private boolean write(String vCard) {
719ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita            try {
720ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita                if (vCard != null) {
721ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita                    outputStream.write(vCard.getBytes());
722ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita                    return true;
723ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita                }
724ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita            } catch (IOException e) {
725ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita                Log.e(TAG, "write outputstrem failed" + e.toString());
726ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita            }
727ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita            return false;
728ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita        }
729ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita
7302f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        public boolean onInit(Context context) {
7312f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            try {
7322f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                outputStream = operation.openOutputStream();
7332f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                if (phoneOwnVCard != null) {
734ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita                    return write(phoneOwnVCard);
7352c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan                }
736ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita                return true;
7372f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            } catch (IOException e) {
7382f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                Log.e(TAG, "open outputstrem failed" + e.toString());
7392c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
740ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita            return false;
7412c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
7422c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
7432f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        public boolean onEntryCreated(String vcard) {
744ce8d51a3a43d113a4a6bad30d595c2a81d0f623cYoshiharu Kurita            return write(vcard);
7452c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
7462c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan
7472f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue        public void onTerminate() {
7482f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue            if (!BluetoothPbapObexServer.closeStream(outputStream, operation)) {
7492f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                if (V) Log.v(TAG, "CloseStream failed!");
7502c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            } else {
7512f8fe66f45bac2bc61395bd4f8de553f4c2b7c30Lixin Yue                if (V) Log.v(TAG, "CloseStream ok!");
7522c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan            }
7532c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan        }
7542c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan    }
7556db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta
7565f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach    public static class VCardFilter {
7575f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach        private static enum FilterBit {
7585f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            //       bit  property    onlyCheckV21  excludeForV21
7595f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            FN (       1, "FN",       true,         false),
7605f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            PHOTO(     3, "PHOTO",    false,        false),
7615f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            BDAY(      4, "BDAY",     false,        false),
7625f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            ADR(       5, "ADR",      false,        false),
7635f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            EMAIL(     8, "EMAIL",    false,        false),
7645f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            TITLE(    12, "TITLE",    false,        false),
7655f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            ORG(      16, "ORG",      false,        false),
766976a53f0f946e589aa2b5204ce3262abcf2afc55Hemant Gupta            NOTE(     17, "NOTE",     false,        false),
7675f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            URL(      20, "URL",      false,        false),
768976a53f0f946e589aa2b5204ce3262abcf2afc55Hemant Gupta            NICKNAME( 23, "NICKNAME", false,        true),
769976a53f0f946e589aa2b5204ce3262abcf2afc55Hemant Gupta            DATETIME( 28, "DATETIME", false,        true);
7705f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach
7715f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            public final int pos;
7725f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            public final String prop;
7735f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            public final boolean onlyCheckV21;
7745f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            public final boolean excludeForV21;
7755f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach
7765f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            FilterBit(int pos, String prop, boolean onlyCheckV21, boolean excludeForV21) {
7775f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                this.pos = pos;
7785f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                this.prop = prop;
7795f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                this.onlyCheckV21 = onlyCheckV21;
7805f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                this.excludeForV21 = excludeForV21;
7815f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            }
7825f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach        }
7835f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach
7845f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach        private static final String SEPARATOR = System.getProperty("line.separator");
7855f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach        private final byte[] filter;
7865f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach
787976a53f0f946e589aa2b5204ce3262abcf2afc55Hemant Gupta        //This function returns true if the attributes needs to be included in the filtered vcard.
788976a53f0f946e589aa2b5204ce3262abcf2afc55Hemant Gupta        private boolean isFilteredIn(FilterBit bit, boolean vCardType21) {
7895f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            final int offset = (bit.pos / 8) + 1;
7905f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            final int bit_pos = bit.pos % 8;
791976a53f0f946e589aa2b5204ce3262abcf2afc55Hemant Gupta            if (!vCardType21 && bit.onlyCheckV21) return true;
792976a53f0f946e589aa2b5204ce3262abcf2afc55Hemant Gupta            if (vCardType21 && bit.excludeForV21) return false;
793976a53f0f946e589aa2b5204ce3262abcf2afc55Hemant Gupta            if (filter == null || offset >= filter.length) return true;
7945f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            return ((filter[filter.length - offset] >> bit_pos) & 0x01) != 0;
7955f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach        }
7965f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach
7975f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach        VCardFilter(byte[] filter) {
7985f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            this.filter = filter;
7995f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach        }
8005f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach
8015f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach        public boolean isPhotoEnabled() {
802976a53f0f946e589aa2b5204ce3262abcf2afc55Hemant Gupta            return isFilteredIn(FilterBit.PHOTO, false);
8035f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach        }
8045f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach
8055f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach        public String apply(String vCard, boolean vCardType21){
8065f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            if (filter == null) return vCard;
8075f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            String lines[] = vCard.split(SEPARATOR);
8085f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            StringBuilder filteredVCard = new StringBuilder();
809976a53f0f946e589aa2b5204ce3262abcf2afc55Hemant Gupta            boolean filteredIn = false;
8105f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach
8115f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            for (String line : lines) {
8125f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                // Check whether the current property is changing (ignoring multi-line properties)
8135f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                // and determine if the current property is filtered in.
8145f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                if (!Character.isWhitespace(line.charAt(0)) && !line.startsWith("=")) {
8155f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                    String currentProp = line.split("[;:]")[0];
816976a53f0f946e589aa2b5204ce3262abcf2afc55Hemant Gupta                    filteredIn = true;
8175f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach
8185f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                    for (FilterBit bit : FilterBit.values()) {
8195f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                        if (bit.prop.equals(currentProp)) {
820976a53f0f946e589aa2b5204ce3262abcf2afc55Hemant Gupta                            filteredIn = isFilteredIn(bit, vCardType21);
8215f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                            break;
8226db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta                        }
8236db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta                    }
8246db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta
8255f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                    // Since PBAP does not have filter bits for IM and SIP,
8265f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                    // exclude them by default. Easiest way is to exclude all
8275f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                    // X- fields....
828976a53f0f946e589aa2b5204ce3262abcf2afc55Hemant Gupta                    if (currentProp.startsWith("X-")) filteredIn = false;
8296db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta                }
8306db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta
8315f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach                // Build filtered vCard
832976a53f0f946e589aa2b5204ce3262abcf2afc55Hemant Gupta                if (filteredIn) filteredVCard.append(line + SEPARATOR);
8336db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta            }
8346db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta
8355f659853fff6a50fd12e1f7956997cbef244f798Andre Eisenbach            return filteredVCard.toString();
8366db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta        }
8376db8e703719f301f75acdf4acacc3296cc1b5016Hemant Gupta    }
8385006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai
8395006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    private static final Uri getPhoneLookupFilterUri() {
8405006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        return PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI;
8415006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    }
8425006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    /**
8435006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai     * Get size of the cursor without duplicated contact id. This assumes the
8446a50944dff2081fc161974cfae7d85d834b123cfSmriti Gupta     * given cursor is sorted by CONTACT_ID.
8455006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai     */
8469d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak    /**
8479d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak     * Count number of rows having distinct contact id. It assumes
8489d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak     * @param cursor cursor to be counted.
8499d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak     * @param contactIdColumn column name of contact id
8509d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak     * @return number of rows that have distinct contact id.
8519d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak     */
8529d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak    private static final int getDistinctContactIdSize(Cursor cursor, String contactIdColumn) {
8539d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak        final int contactIdColumnIndex = cursor.getColumnIndexOrThrow(contactIdColumn);
8545006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        long previousContactId = -1;
8555006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        int count = 0;
8565006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        cursor.moveToPosition(-1);
8575006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        while (cursor.moveToNext()) {
8589d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak            final long contactId = cursor.getLong(contactIdColumnIndex);
8595006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            if (previousContactId != contactId) {
8605006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                count++;
8615006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                previousContactId = contactId;
8625006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            }
8635006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        }
8645006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        if (V) {
8655006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            Log.i(TAG, "getDistinctContactIdSize result: " + count);
8665006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        }
8675006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        return count;
8685006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    }
8695006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai
8705006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    /**
8719d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak     * Construct "display_name,contact_id" strings and insert into a arraylist.
8729d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak     *
8739d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak     * @param resultList  list to be inserted.
8749d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak     * @param defaultName default name if the name of contact is empty.
8759d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak     * @param cursor      a cursor containing contact id and display name.
8769d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak     * @param contactIdColumnName name of column that stores contact id.
8779d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak     * @param displayNameColumnName name of column that stores display name.
8785006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai     */
8795006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    private static void appendDistinctNameIdList(ArrayList<String> resultList,
8809d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak            String defaultName, Cursor cursor, String contactIdColumnName,
8819d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak            String displayNameColumnName) {
8829d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak        final int contactIdColumnIndex = cursor.getColumnIndexOrThrow(contactIdColumnName);
8839d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak        final int displayNameColumnIndex = cursor.getColumnIndexOrThrow(displayNameColumnName);
8849d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak
8855006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        long previousContactId = -1;
8865006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        cursor.moveToPosition(-1);
8875006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        while (cursor.moveToNext()) {
8889d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak            final long contactId = cursor.getLong(contactIdColumnIndex);
8899d68ffa1079ca2e85a8ccf62bf8dca2f43f1ade3Tony Mak            String displayName = cursor.getString(displayNameColumnIndex);
8905006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            if (TextUtils.isEmpty(displayName)) {
8915006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                displayName = defaultName;
8925006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            }
8935006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai
8946a50944dff2081fc161974cfae7d85d834b123cfSmriti Gupta            String newString = displayName + "," + contactId;
8956a50944dff2081fc161974cfae7d85d834b123cfSmriti Gupta            if (!resultList.contains(newString)) {
8966a50944dff2081fc161974cfae7d85d834b123cfSmriti Gupta                resultList.add(newString);
8975006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            }
8985006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        }
8995006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        if (V) {
9005006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            for (String nameId : resultList) {
9015006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai                Log.i(TAG, "appendDistinctNameIdList result: " + nameId);
9025006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai            }
9035006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai        }
9045006c8597521a7652eafa89a6fb5483b5cb567b6Ricky Wai    }
9052c282d5898ac0916470ebfa9ff26ba784cf4bb24Jackson Fan}
906